Skip to content

Commit

Permalink
feat(combobox): focusEl logic implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
hrynevychroman committed Jun 24, 2024
1 parent 65d3b62 commit 255d6e6
Show file tree
Hide file tree
Showing 7 changed files with 2,368 additions and 1,738 deletions.
4 changes: 3 additions & 1 deletion docs/components/demo/Combobox/css/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Icon } from '@iconify/vue'
import './styles.css'
const v = ref('')
const focusEl = ref('')
const options = ['Apple', 'Banana', 'Blueberry', 'Grapes', 'Pineapple']
const vegetables = ['Aubergine', 'Broccoli', 'Carrot', 'Courgette', 'Leek']
</script>
Expand All @@ -13,6 +14,7 @@ const vegetables = ['Aubergine', 'Broccoli', 'Carrot', 'Courgette', 'Leek']
<ComboboxRoot
v-model="v"
class="ComboboxRoot"
@update:focus-el="(val) => console.log('focus-el:', val)"
>
<ComboboxAnchor class="ComboboxAnchor">
<ComboboxInput
Expand All @@ -33,7 +35,7 @@ const vegetables = ['Aubergine', 'Broccoli', 'Carrot', 'Courgette', 'Leek']

<ComboboxGroup>
<ComboboxLabel class="ComboboxLabel">
Fruits
{{ focusEl }}
</ComboboxLabel>

<ComboboxItem
Expand Down
1 change: 1 addition & 0 deletions docs/components/demo/Combobox/tailwind/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const vegetables = ['Aubergine', 'Broccoli', 'Carrot', 'Courgette', 'Leek']
<ComboboxRoot
v-model="v"
class="relative"
@update:focus-el="(val) => console.log('focus-el:', val)"
>
<ComboboxAnchor class="min-w-[160px] inline-flex items-center justify-between rounded px-[15px] text-[13px] leading-none h-[35px] gap-[5px] bg-white text-grass11 shadow-[0_2px_10px] shadow-black/10 hover:bg-mauve3 focus:shadow-[0_0_0_2px] focus:shadow-black data-[placeholder]:text-grass9 outline-none">
<ComboboxInput
Expand Down
5 changes: 5 additions & 0 deletions docs/content/meta/ComboboxRoot.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@
'name': 'update:searchTerm',
'description': '<p>Event handler called when the searchTerm of the combobox changes.</p>\n',
'type': '[value: string]'
},
{
'name': 'update:focusEl',
'description': '<p>Event handler called when the focusEl of the combobox changes.</p>\n',
'type': '[value: string]'
}
]" />

Expand Down
1 change: 0 additions & 1 deletion packages/radix-vue/src/Collection/Collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export function createCollection<ItemData = {}>(attrName = ITEM_DATA_ATTR) {
const itemMap = ref<Map<HTMLElement, { ref: HTMLElement } & ItemData>>(new Map())
const collectionRef = ref<HTMLElement>()

// @ts-expect-error Type instantiation is excessively deep and possibly infinite.
const context = provideCollectionContext({
collectionRef,
itemMap,
Expand Down
17 changes: 11 additions & 6 deletions packages/radix-vue/src/Combobox/ComboboxItem.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
<script lang="ts">
import type { Ref } from 'vue'
import {
computed,
nextTick,
ref,
toRefs,
} from 'vue'
import type { PrimitiveProps } from '@/Primitive'
import { createContext, handleAndDispatchCustomEvent, useForwardExpose, useId } from '@/shared'
import type { AcceptableValue } from './ComboboxRoot.vue'
import { whenever } from '@vueuse/core'
export type SelectEvent<T> = CustomEvent<{ originalEvent: PointerEvent, value?: T }>
interface ComboboxItemContext {
Expand All @@ -28,12 +35,6 @@ const COMBOBOX_SELECT = 'combobox.select'
</script>

<script setup lang="ts" generic="T extends AcceptableValue = AcceptableValue">
import {
computed,
nextTick,
ref,
toRefs,
} from 'vue'
import { injectComboboxRootContext } from './ComboboxRoot.vue'
import { injectComboboxGroupContext } from './ComboboxGroup.vue'
import {
Expand Down Expand Up @@ -100,6 +101,10 @@ if (props.value === '') {
provideComboboxItemContext({
isSelected,
})
whenever(isFocused, () => {
rootContext.onFocusElChange(props.value)
})
</script>

<template>
Expand Down
16 changes: 16 additions & 0 deletions packages/radix-vue/src/Combobox/ComboboxRoot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ type ComboboxRootContext<T> = {
selectedElement: ComputedRef<HTMLElement | undefined>
onSelectedValueChange: (val: T) => void
parentElement: Ref<HTMLElement | undefined>
focusEl: Ref<T | undefined>
onFocusElChange: (val: T) => void
}
export const [injectComboboxRootContext, provideComboboxRootContext]
Expand All @@ -41,6 +44,8 @@ export type ComboboxRootEmits<T = AcceptableValue> = {
'update:open': [value: boolean]
/** Event handler called when the searchTerm of the combobox changes. */
'update:searchTerm': [value: string]
/** Event handler called when the focused value of the combobox changes. */
'update:focusEl': [value: T]
}
export interface ComboboxRootProps<T = AcceptableValue> extends PrimitiveProps {
Expand All @@ -52,6 +57,8 @@ export interface ComboboxRootProps<T = AcceptableValue> extends PrimitiveProps {
open?: boolean
/** The open state of the combobox when it is initially rendered. <br> Use when you do not need to control its open state. */
defaultOpen?: boolean
/** The controlled focused value of the Combobox. Can be binded-with with v-model:focus. */
focusEl?: T
/** The controlled search term of the Combobox. Can be binded-with with v-model:searchTerm. */
searchTerm?: string
/** Whether multiple options can be selected or not. */
Expand Down Expand Up @@ -118,6 +125,12 @@ const open = useVModel(props, 'open', emit, {
passive: (props.open === undefined) as false,
}) as Ref<boolean>
const focusEl = useVModel(props, 'focusEl', emit, {
// @ts-expect-error ignore the type error here
defaultValue: '',
passive: false,
}) as Ref<T | undefined>
const selectedValue = ref<T>()
async function onOpenChange(val: boolean) {
Expand Down Expand Up @@ -278,6 +291,9 @@ provideComboboxRootContext({
parentElement,
contentElement,
onContentElementChange: val => contentElement.value = val,
focusEl,
onFocusElChange: val => focusEl.value = val as T,
})
</script>

Expand Down
Loading

0 comments on commit 255d6e6

Please sign in to comment.