Skip to content

Commit

Permalink
feat(Combobox): add resetSearchTermOnSelect props to allow whether …
Browse files Browse the repository at this point in the history
…to clear search term on select (#1257)

* feat(combobox): add `clearSearchTermOnSelect` param to `ComboboxRoot`

* docs(combobox): add `clearSearchTermOnSelect` parameter in `ComboboxRoot` markdown

* chore(lint): run lint:fix

* fix(combobox): rename `clear` to `reset` on select

* fix(combobox): update resetSearchTerm to accept mode parameter for enhanced behavior
  • Loading branch information
hrynevychroman authored Jan 21, 2025
1 parent 1f472e2 commit 1fad29d
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 13 deletions.
7 changes: 7 additions & 0 deletions docs/content/meta/ComboboxRoot.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@
'required': false,
'default': 'true'
},
{
'name': 'resetSearchTermOnSelect',
'description': '<p>Whether to reset the searchTerm when the Combobox value is selected</p>\n',
'type': 'boolean',
'required': false,
'default': 'true'
},
{
'name': 'searchTerm',
'description': '<p>The controlled search term of the Combobox. Can be binded with with v-model:searchTerm.</p>\n',
Expand Down
6 changes: 3 additions & 3 deletions packages/plugins/src/namespaced/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ const namespaced = filteredComponent.map((curr: keyof typeof components) => {
}
else {
return `export const ${key} = {\n${
Object.keys(tmp).map((k) => { return ` ${k}: ${tmp[k]},\n` }).join('')
Object.keys(tmp).map((k) => { return ` ${k}: ${tmp[k]},\n` }).join('')
}} as {\n${Object.keys(tmp).map((k) => {
return ` ${k}: typeof ${tmp[k]}\n`
}).join('')}}`
return ` ${k}: typeof ${tmp[k]}\n`
}).join('')}}`
}
})

Expand Down
19 changes: 14 additions & 5 deletions packages/radix-vue/src/Combobox/ComboboxRoot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ export interface ComboboxRootProps<T = AcceptableValue> extends PrimitiveProps {
* @defaultValue `true`
*/
resetSearchTermOnBlur?: boolean
/**
* Whether to reset the searchTerm when the Combobox value is selected
* @defaultValue `true`
*/
resetSearchTermOnSelect?: boolean
}
</script>

Expand All @@ -91,6 +96,7 @@ import isEqual from 'fast-deep-equal'
const props = withDefaults(defineProps<ComboboxRootProps<T>>(), {
open: undefined,
resetSearchTermOnBlur: true,
resetSearchTermOnSelect: true,
})
const emit = defineEmits<ComboboxRootEmits<T>>()
Expand Down Expand Up @@ -148,7 +154,7 @@ async function onOpenChange(val: boolean) {
else {
isUserInputted.value = false
if (props.resetSearchTermOnBlur)
resetSearchTerm()
resetSearchTerm('blur')
}
}
Expand Down Expand Up @@ -194,16 +200,19 @@ const filteredOptions = computed(() => {
return options.value
})
function resetSearchTerm() {
function resetSearchTerm(mode?: 'blur' | 'select') {
// clear when blur or when select and resetSearchTermOnSelect is true
const condition = mode === 'blur' || (mode === 'select' && props.resetSearchTermOnSelect)
if (!multiple.value && modelValue.value && !Array.isArray(modelValue.value)) {
if (props.displayValue)
searchTerm.value = props.displayValue(modelValue.value)
else if (typeof modelValue.value !== 'object')
searchTerm.value = modelValue.value.toString()
else
else if (condition)
searchTerm.value = ''
}
else {
else if (condition) {
searchTerm.value = ''
}
}
Expand All @@ -219,7 +228,7 @@ const stringifiedModelValue = computed(() => JSON.stringify(modelValue.value))
watch(stringifiedModelValue, async () => {
await nextTick()
await nextTick()
resetSearchTerm()
resetSearchTerm('select')
}, {
// If searchTerm is provided with value during initialization, we don't reset it immediately
immediate: !props.searchTerm,
Expand Down
2 changes: 0 additions & 2 deletions packages/radix-vue/src/Menu/MenuRoot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,7 @@ export const [injectMenuRootContext, provideMenuRootContext]
import {
ref,
toRefs,
watchEffect,
} from 'vue'
import { isClient } from '@vueuse/shared'
import { useVModel } from '@vueuse/core'
import { PopperRoot } from '@/Popper'
Expand Down
4 changes: 2 additions & 2 deletions packages/radix-vue/src/shared/createContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ export function createContext<ContextValue>(
`Injection \`${injectionKey.toString()}\` not found. Component must be used within ${
Array.isArray(providerComponentName)
? `one of the following components: ${providerComponentName.join(
', ',
)}`
', ',
)}`
: `\`${providerComponentName}\``
}`,
)
Expand Down
2 changes: 1 addition & 1 deletion packages/radix-vue/src/shared/useSingleOrMultipleValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function validateProps({ type, defaultValue, modelValue }: SingleOrMultipleProps

if (modelValue !== undefined && defaultValue !== undefined && typeof modelValue !== typeof defaultValue) {
throw new Error(
`Invalid prop \`value\` of value \`${modelValue}\` supplied, should be the same type as the \`defaultValue\` prop, which is \`${defaultValue}\`. The \`value\` prop must be:
`Invalid prop \`value\` of value \`${modelValue}\` supplied, should be the same type as the \`defaultValue\` prop, which is \`${defaultValue}\`. The \`value\` prop must be:
${type === 'single' ? '- a string' : type === 'multiple' ? '- an array of strings' : '- a string\n- an array of strings'}
- \`undefined\``,
)
Expand Down

0 comments on commit 1fad29d

Please sign in to comment.