Skip to content

Commit 41c45d7

Browse files
aibayanyu20claude
andcommitted
feat(select): support function tokenSeparators
Mirrors react-component/select#1220 (rc-select 1.7.0). When `tokenSeparators` is a function, it receives the raw input and returns the tokens to split into chips. Useful for callers that need richer than character-based tokenization (e.g. regex, async tokenization hints, custom token detection logic). Extract the split decision into a `splitByTokenSeparators` helper so the BaseSelect search path can route through either the function or the legacy string-array `getSeparatedContent` branch. `tokenWithEnter` is also updated to short-circuit to `true` for the function form (can't predict whether a function will emit newlines). Bumps `@v-c/select` from 1.0.23 to 1.1.0-rc.1 to ship the API change behind the rc tag. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b73bd92 commit 41c45d7

2 files changed

Lines changed: 25 additions & 10 deletions

File tree

packages/select/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@v-c/select",
33
"type": "module",
4-
"version": "1.0.23",
4+
"version": "1.1.0-rc.1",
55
"description": "",
66
"author": "",
77
"license": "MIT",

packages/select/src/BaseSelect/index.tsx

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ export interface BaseSelectProps extends BaseSelectPrivateProps {
175175
maxTagPlaceholder?: VueNode | ((omittedValues: DisplayValueType[]) => any)
176176

177177
// >>> Search
178-
tokenSeparators?: string[]
178+
tokenSeparators?: string[] | ((input: string) => string[])
179179

180180
// >>> Icons
181181
allowClear?: boolean | { clearIcon?: VueNode }
@@ -378,9 +378,29 @@ export const BaseSelect = defineComponent<
378378

379379
// ============================= Search =============================
380380
const tokenWithEnter = computed(() => {
381-
return (tokenSeparators.value || []).some((tokenSeparator: string) => ['\n', '\r\n'].includes(tokenSeparator))
381+
const value = tokenSeparators.value
382+
return typeof value === 'function'
383+
|| (value || []).some((tokenSeparator: string) => ['\n', '\r\n'].includes(tokenSeparator))
382384
})
383385

386+
/**
387+
* ant-design#57391 / rc-select#1220: when `tokenSeparators` is a
388+
* function, defer the split decision to the user callback. Otherwise
389+
* fall back to the static-string-array behaviour via getSeparatedContent.
390+
*/
391+
const splitByTokenSeparators = (input: string, end?: number): string[] | null => {
392+
const value = tokenSeparators.value
393+
if (typeof value === 'function') {
394+
const tokens = value(input)
395+
const isUnchanged = Array.isArray(tokens) && tokens.length === 1 && tokens[0] === input
396+
if (!Array.isArray(tokens) || !tokens.length || isUnchanged) {
397+
return null
398+
}
399+
return typeof end !== 'undefined' ? tokens.slice(0, end) : tokens
400+
}
401+
return getSeparatedContent(input, value as string[] | undefined, end)
402+
}
403+
384404
const onInternalSearch = (searchText: string, fromTyping: boolean, isCompositing: boolean) => {
385405
const { maxCount } = props
386406
if (multiple.value && isValidCount(maxCount) && displayValues.value.length >= maxCount!) {
@@ -390,14 +410,9 @@ export const BaseSelect = defineComponent<
390410
let newSearchText = searchText
391411
props?.onActiveValueChange?.(null)
392412

393-
const separatedList = getSeparatedContent(
394-
searchText,
395-
tokenSeparators.value as string[],
396-
isValidCount(maxCount) ? maxCount! - displayValues.value.length : undefined,
397-
)
398-
413+
const cap = isValidCount(maxCount) ? maxCount! - displayValues.value.length : undefined
399414
// Check if match the `tokenSeparators`
400-
const patchLabels: string[] | null = isCompositing ? null : separatedList
415+
const patchLabels: string[] | null = isCompositing ? null : splitByTokenSeparators(searchText, cap)
401416

402417
// Ignore combobox since it's not split-able
403418
if (mode.value !== 'combobox' && patchLabels) {

0 commit comments

Comments
 (0)