@veltra/desktop 1.3.5 → 1.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/components/action/action-group.vue.d.ts +1 -1
  2. package/dist/components/action/action.vue.d.ts +1 -1
  3. package/dist/components/cascade/cascade.js +8 -2
  4. package/dist/components/cascade/cascade.js.map +1 -1
  5. package/dist/components/cascade/style2.css +4 -0
  6. package/dist/components/date-range-picker/date-range-picker.js +5 -2
  7. package/dist/components/date-range-picker/date-range-picker.js.map +1 -1
  8. package/dist/components/date-range-picker/style2.css +4 -0
  9. package/dist/components/empty/empty.vue.d.ts +1 -1
  10. package/dist/components/form-item/form-item.js.map +1 -1
  11. package/dist/components/form-item/form-item.vue_vue_type_script_setup_true_lang.js +2 -2
  12. package/dist/components/form-item/form-item.vue_vue_type_script_setup_true_lang.js.map +1 -1
  13. package/dist/components/form-item/style2.css +2 -1
  14. package/dist/components/grid-input/style2.css +3 -0
  15. package/dist/components/multi-select/multi-select.js +67 -40
  16. package/dist/components/multi-select/multi-select.js.map +1 -1
  17. package/dist/components/multi-select/multi-select.vue.d.ts +4 -4
  18. package/dist/components/multi-select/style2.css +23 -10
  19. package/dist/components/multi-tree-select/multi-tree-select.js +52 -35
  20. package/dist/components/multi-tree-select/multi-tree-select.js.map +1 -1
  21. package/dist/components/multi-tree-select/multi-tree-select.vue.d.ts +1 -1
  22. package/dist/components/multi-tree-select/style2.css +26 -16
  23. package/dist/components/progress-nodes/progress-nodes.vue.d.ts +1 -1
  24. package/dist/components/select/select.js +159 -95
  25. package/dist/components/select/select.js.map +1 -1
  26. package/dist/components/select/style2.css +4 -17
  27. package/dist/components/select/use-options.js +67 -26
  28. package/dist/components/select/use-options.js.map +1 -1
  29. package/dist/components/steps/steps.vue.d.ts +2 -2
  30. package/dist/components/tabs/tabs-horizontal.vue.d.ts +2 -2
  31. package/dist/components/tabs/tabs-vertical.vue.d.ts +2 -2
  32. package/dist/components/tabs/tabs.vue.d.ts +2 -2
  33. package/dist/components/textarea/style2.css +1 -0
  34. package/dist/components/textarea/textarea.vue.d.ts +1 -1
  35. package/dist/components/tree/tree.vue.d.ts +1 -1
  36. package/dist/components/tree-select/style2.css +6 -15
  37. package/dist/components/tree-select/tree-select.js +95 -41
  38. package/dist/components/tree-select/tree-select.js.map +1 -1
  39. package/dist/components/tree-select/tree-select.vue.d.ts +1 -1
  40. package/package.json +6 -6
  41. package/src/components/cascade/cascade.vue +15 -2
  42. package/src/components/cascade/style.scss +5 -0
  43. package/src/components/date-range-picker/date-range-picker.vue +9 -1
  44. package/src/components/date-range-picker/style.scss +5 -0
  45. package/src/components/form-item/form-item.vue +2 -2
  46. package/src/components/form-item/style.scss +2 -1
  47. package/src/components/grid-input/style.scss +1 -0
  48. package/src/components/multi-select/multi-select.vue +50 -19
  49. package/src/components/multi-select/style.scss +27 -4
  50. package/src/components/multi-tree-select/multi-tree-select.vue +34 -14
  51. package/src/components/multi-tree-select/style.scss +28 -9
  52. package/src/components/select/__test__/select.test.ts +110 -0
  53. package/src/components/select/select.vue +130 -46
  54. package/src/components/select/style.scss +5 -14
  55. package/src/components/select/use-options.ts +83 -39
  56. package/src/components/textarea/style.scss +1 -0
  57. package/src/components/tree-select/style.scss +4 -8
  58. package/src/components/tree-select/tree-select.vue +90 -17
@@ -1 +1 @@
1
- {"version":3,"file":"use-options.js","names":["o","chainObj"],"sources":["../../../src/components/select/use-options.ts"],"sourcesContent":["import { debounce, o as chainObj } from '@cat-kit/core'\nimport { fieldKey } from '@veltra/utils'\nimport { computed, shallowRef, watch, type ShallowRef, type ComputedRef } from 'vue'\n\nimport type { SelectProps } from '../../types'\n\ninterface Options {\n props: SelectProps\n}\n\ninterface UseOptionsReturned {\n /** 查询字符串 */\n queryString: ShallowRef<string>\n /** 选项 */\n options: ComputedRef<Record<string, any>[]>\n /** 所有选项 */\n allOptions: ComputedRef<Record<string, any>[]>\n /** 将临时选项转换为创建的选项 */\n temOptionsToCreatedOptions: () => void\n /** 清空用户创建的选项 */\n clearCreatedOptions: () => void\n}\n\n// 允许创建的实现\n// 1. 在过滤时将选项加入待选列表中\n// 2. 如果选择了改临时选项,则取消该选项的临时标记\n// 3. 如果第二次重新选择\n\nexport function useOptions(o: Options): UseOptionsReturned {\n const { props } = o\n\n /** 筛选 */\n const queryString = shallowRef('')\n\n const remoteOptions = shallowRef<Record<string, any>[]>([])\n const filteredOptions = shallowRef<Record<string, any>[]>([])\n // 临时选项\n const tempOptions = shallowRef<({ __isTemp: true } & Record<string, any>)[]>([])\n // 创建的选项\n const createdOptions = shallowRef<({ __isTemp: false } & Record<string, any>)[]>([])\n\n function temOptionsToCreatedOptions() {\n createdOptions.value = tempOptions.value.map((item) => {\n return { ...item, __isTemp: false }\n })\n }\n\n function clearCreatedOptions() {\n createdOptions.value = []\n }\n\n const setTempOption = (qs: string, options?: Record<string, any>[]) => {\n if (!qs?.trim() || !props.creatable) {\n tempOptions.value = []\n return\n }\n const labelKey = fieldKey(props.labelKey, 'label')\n const valueKey = fieldKey(props.valueKey, 'value')\n const exactMatch = options\n ? options.some((option) => {\n return chainObj(option).get(labelKey) === qs\n })\n : false\n\n if (!exactMatch) {\n tempOptions.value = [{ [labelKey]: qs, [valueKey]: qs, __isTemp: true }]\n }\n }\n\n const allOptions = computed(() => {\n const { options } = props\n if (typeof options === 'function') return remoteOptions.value\n return options ?? []\n })\n\n /** 展示的选项 */\n const options = computed(() => {\n const { options } = props\n\n if (typeof options === 'function') return remoteOptions.value\n\n const prependOptions = tempOptions.value?.length ? tempOptions.value : createdOptions.value\n\n if (!options) {\n return prependOptions\n }\n\n return [...prependOptions, ...filteredOptions.value]\n })\n\n // TODO: 如有性能问题可以考虑优化\n watch(\n [queryString, () => props.options],\n debounce(async ([qs, propsOptions]) => {\n if (typeof propsOptions === 'function') {\n const options = await propsOptions(qs)\n remoteOptions.value = options\n setTempOption(qs, options)\n } else {\n // 当选项不是函数时,可以创建选项\n const labelKey = fieldKey(props.labelKey, 'label')\n\n if (!qs) {\n filteredOptions.value = propsOptions ?? []\n setTempOption(qs, filteredOptions.value)\n return\n }\n\n const _filteredOptions =\n propsOptions?.filter((item) => {\n return chainObj(item).get(labelKey)?.includes(qs) ?? false\n }) ?? []\n\n setTempOption(qs, _filteredOptions)\n filteredOptions.value = _filteredOptions\n }\n }, 200),\n { immediate: true }\n )\n\n return { queryString, options, allOptions, temOptionsToCreatedOptions, clearCreatedOptions }\n}\n"],"mappings":";;;;AA4BA,SAAgB,WAAW,KAAgC;CACzD,MAAM,EAAE,UAAUA;;CAGlB,MAAM,cAAc,WAAW,EAAE;CAEjC,MAAM,gBAAgB,WAAkC,CAAC,CAAC;CAC1D,MAAM,kBAAkB,WAAkC,CAAC,CAAC;CAE5D,MAAM,cAAc,WAAyD,CAAC,CAAC;CAE/E,MAAM,iBAAiB,WAA0D,CAAC,CAAC;CAEnF,SAAS,6BAA6B;EACpC,eAAe,QAAQ,YAAY,MAAM,KAAK,SAAS;GACrD,OAAO;IAAE,GAAG;IAAM,UAAU;GAAM;EACpC,CAAC;CACH;CAEA,SAAS,sBAAsB;EAC7B,eAAe,QAAQ,CAAC;CAC1B;CAEA,MAAM,iBAAiB,IAAY,YAAoC;EACrE,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,WAAW;GACnC,YAAY,QAAQ,CAAC;GACrB;EACF;EACA,MAAM,WAAW,SAAS,MAAM,UAAU,OAAO;EACjD,MAAM,WAAW,SAAS,MAAM,UAAU,OAAO;EAOjD,IAAI,EANe,UACf,QAAQ,MAAM,WAAW;GACvB,OAAOC,EAAS,MAAM,CAAC,CAAC,IAAI,QAAQ,MAAM;EAC5C,CAAC,IACD,QAGF,YAAY,QAAQ,CAAC;IAAG,WAAW;IAAK,WAAW;GAAI,UAAU;EAAK,CAAC;CAE3E;CAEA,MAAM,aAAa,eAAe;EAChC,MAAM,EAAE,YAAY;EACpB,IAAI,OAAO,YAAY,YAAY,OAAO,cAAc;EACxD,OAAO,WAAW,CAAC;CACrB,CAAC;;CAGD,MAAM,UAAU,eAAe;EAC7B,MAAM,EAAE,YAAY;EAEpB,IAAI,OAAO,YAAY,YAAY,OAAO,cAAc;EAExD,MAAM,iBAAiB,YAAY,OAAO,SAAS,YAAY,QAAQ,eAAe;EAEtF,IAAI,CAAC,SACH,OAAO;EAGT,OAAO,CAAC,GAAG,gBAAgB,GAAG,gBAAgB,KAAK;CACrD,CAAC;CAGD,MACE,CAAC,mBAAmB,MAAM,OAAO,GACjC,SAAS,OAAO,CAAC,IAAI,kBAAkB;EACrC,IAAI,OAAO,iBAAiB,YAAY;GACtC,MAAM,UAAU,MAAM,aAAa,EAAE;GACrC,cAAc,QAAQ;GACtB,cAAc,IAAI,OAAO;EAC3B,OAAO;GAEL,MAAM,WAAW,SAAS,MAAM,UAAU,OAAO;GAEjD,IAAI,CAAC,IAAI;IACP,gBAAgB,QAAQ,gBAAgB,CAAC;IACzC,cAAc,IAAI,gBAAgB,KAAK;IACvC;GACF;GAEA,MAAM,mBACJ,cAAc,QAAQ,SAAS;IAC7B,OAAOA,EAAS,IAAI,CAAC,CAAC,IAAI,QAAQ,CAAC,EAAE,SAAS,EAAE,KAAK;GACvD,CAAC,KAAK,CAAC;GAET,cAAc,IAAI,gBAAgB;GAClC,gBAAgB,QAAQ;EAC1B;CACF,GAAG,GAAG,GACN,EAAE,WAAW,KAAK,CACpB;CAEA,OAAO;EAAE;EAAa;EAAS;EAAY;EAA4B;CAAoB;AAC7F"}
1
+ {"version":3,"file":"use-options.js","names":["o","chainObj"],"sources":["../../../src/components/select/use-options.ts"],"sourcesContent":["import { debounce, o as chainObj } from '@cat-kit/core'\nimport { fieldKey } from '@veltra/utils'\nimport { computed, shallowRef, watch, type ShallowRef, type ComputedRef } from 'vue'\n\nimport type { SelectProps } from '../../types'\n\ninterface Options {\n props: SelectProps\n}\n\ninterface UseOptionsReturned {\n /** 查询字符串 */\n queryString: ShallowRef<string>\n /** 选项 */\n options: ComputedRef<Record<string, any>[]>\n /** 所有选项 */\n allOptions: ComputedRef<Record<string, any>[]>\n /** 将临时选项转换为创建的选项 */\n temOptionsToCreatedOptions: () => void\n /** 清空用户创建的选项 */\n clearCreatedOptions: () => void\n}\n\n// 允许创建的实现\n// 1. 在过滤时将选项加入待选列表中\n// 2. 如果选择了该临时选项,则取消该选项的临时标记并并入已创建列表\n// 3. 多次创建累计保留,已创建项参与后续过滤匹配\n\nexport function useOptions(o: Options): UseOptionsReturned {\n const { props } = o\n\n /** 筛选 */\n const queryString = shallowRef('')\n\n const remoteOptions = shallowRef<Record<string, any>[]>([])\n const filteredOptions = shallowRef<Record<string, any>[]>([])\n // 临时选项\n const tempOptions = shallowRef<({ __isTemp: true } & Record<string, any>)[]>([])\n // 创建的选项\n const createdOptions = shallowRef<({ __isTemp: false } & Record<string, any>)[]>([])\n\n function getSourceOptions(propsOptions: SelectProps['options']) {\n if (typeof propsOptions === 'function') return remoteOptions.value\n return [...createdOptions.value, ...(propsOptions ?? [])]\n }\n\n /** 无查询时同步展示完整列表(含已创建项),避免选择后等高亮索引错位 */\n function resetToSourceOptions() {\n const sourceOptions = getSourceOptions(props.options)\n if (typeof props.options === 'function') {\n setTempOption('', remoteOptions.value)\n return\n }\n filteredOptions.value = sourceOptions\n tempOptions.value = []\n }\n\n function temOptionsToCreatedOptions() {\n if (!tempOptions.value.length) return\n\n createdOptions.value = [\n ...createdOptions.value,\n ...tempOptions.value.map((item) => {\n return { ...item, __isTemp: false as const }\n })\n ]\n // 立即清掉临时项并回到完整列表,不等待过滤防抖\n resetToSourceOptions()\n }\n\n function clearCreatedOptions() {\n createdOptions.value = []\n resetToSourceOptions()\n }\n\n const setTempOption = (qs: string, options?: Record<string, any>[]) => {\n if (!qs?.trim() || !props.creatable) {\n tempOptions.value = []\n return\n }\n const labelKey = fieldKey(props.labelKey, 'label')\n const valueKey = fieldKey(props.valueKey, 'value')\n const exactMatch = options\n ? options.some((option) => {\n return chainObj(option).get(labelKey) === qs\n })\n : false\n\n tempOptions.value = exactMatch ? [] : [{ [labelKey]: qs, [valueKey]: qs, __isTemp: true }]\n }\n\n const allOptions = computed(() => {\n const { options } = props\n if (typeof options === 'function') return remoteOptions.value\n return [...createdOptions.value, ...(options ?? [])]\n })\n\n /**\n * 展示的选项\n * @description 已创建选项并入过滤数据源参与匹配;临时选项(待创建)固定置顶\n */\n const options = computed(() => {\n const { options } = props\n\n if (typeof options === 'function') return remoteOptions.value\n\n return [...tempOptions.value, ...filteredOptions.value]\n })\n\n const applyLocalFilter = (qs: string, propsOptions: Record<string, any>[] | undefined) => {\n const labelKey = fieldKey(props.labelKey, 'label')\n const sourceOptions = [...createdOptions.value, ...(propsOptions ?? [])]\n\n if (!qs) {\n filteredOptions.value = sourceOptions\n setTempOption(qs, filteredOptions.value)\n return\n }\n\n const _filteredOptions = sourceOptions.filter((item) => {\n return chainObj(item).get(labelKey)?.includes(qs) ?? false\n })\n\n setTempOption(qs, _filteredOptions)\n filteredOptions.value = _filteredOptions\n }\n\n // 仅对「有查询词」的本地过滤做防抖;清空查询同步生效,避免选中后列表延迟重建\n const debouncedLocalFilter = debounce(\n (qs: string, propsOptions: Record<string, any>[] | undefined) => {\n // 防抖回调可能晚于清空查询到达,以当前 queryString 为准\n if (!queryString.value) {\n applyLocalFilter('', propsOptions)\n return\n }\n applyLocalFilter(qs, propsOptions)\n },\n 200\n )\n\n const debouncedRemoteFilter = debounce(async (qs: string, propsOptions: Function) => {\n const options = await propsOptions(queryString.value)\n remoteOptions.value = options\n setTempOption(queryString.value, options)\n }, 200)\n\n watch(\n [queryString, () => props.options, createdOptions],\n ([qs, propsOptions]) => {\n if (typeof propsOptions === 'function') {\n debouncedRemoteFilter(qs, propsOptions)\n return\n }\n\n if (!qs) {\n applyLocalFilter('', propsOptions)\n return\n }\n\n debouncedLocalFilter(qs, propsOptions)\n },\n { immediate: true }\n )\n\n return { queryString, options, allOptions, temOptionsToCreatedOptions, clearCreatedOptions }\n}\n"],"mappings":";;;;AA4BA,SAAgB,WAAW,KAAgC;CACzD,MAAM,EAAE,UAAUA;;CAGlB,MAAM,cAAc,WAAW,EAAE;CAEjC,MAAM,gBAAgB,WAAkC,CAAC,CAAC;CAC1D,MAAM,kBAAkB,WAAkC,CAAC,CAAC;CAE5D,MAAM,cAAc,WAAyD,CAAC,CAAC;CAE/E,MAAM,iBAAiB,WAA0D,CAAC,CAAC;CAEnF,SAAS,iBAAiB,cAAsC;EAC9D,IAAI,OAAO,iBAAiB,YAAY,OAAO,cAAc;EAC7D,OAAO,CAAC,GAAG,eAAe,OAAO,GAAI,gBAAgB,CAAC,CAAE;CAC1D;;CAGA,SAAS,uBAAuB;EAC9B,MAAM,gBAAgB,iBAAiB,MAAM,OAAO;EACpD,IAAI,OAAO,MAAM,YAAY,YAAY;GACvC,cAAc,IAAI,cAAc,KAAK;GACrC;EACF;EACA,gBAAgB,QAAQ;EACxB,YAAY,QAAQ,CAAC;CACvB;CAEA,SAAS,6BAA6B;EACpC,IAAI,CAAC,YAAY,MAAM,QAAQ;EAE/B,eAAe,QAAQ,CACrB,GAAG,eAAe,OAClB,GAAG,YAAY,MAAM,KAAK,SAAS;GACjC,OAAO;IAAE,GAAG;IAAM,UAAU;GAAe;EAC7C,CAAC,CACH;EAEA,qBAAqB;CACvB;CAEA,SAAS,sBAAsB;EAC7B,eAAe,QAAQ,CAAC;EACxB,qBAAqB;CACvB;CAEA,MAAM,iBAAiB,IAAY,YAAoC;EACrE,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,WAAW;GACnC,YAAY,QAAQ,CAAC;GACrB;EACF;EACA,MAAM,WAAW,SAAS,MAAM,UAAU,OAAO;EACjD,MAAM,WAAW,SAAS,MAAM,UAAU,OAAO;EACjD,MAAM,aAAa,UACf,QAAQ,MAAM,WAAW;GACvB,OAAOC,EAAS,MAAM,CAAC,CAAC,IAAI,QAAQ,MAAM;EAC5C,CAAC,IACD;EAEJ,YAAY,QAAQ,aAAa,CAAC,IAAI,CAAC;IAAG,WAAW;IAAK,WAAW;GAAI,UAAU;EAAK,CAAC;CAC3F;CAEA,MAAM,aAAa,eAAe;EAChC,MAAM,EAAE,YAAY;EACpB,IAAI,OAAO,YAAY,YAAY,OAAO,cAAc;EACxD,OAAO,CAAC,GAAG,eAAe,OAAO,GAAI,WAAW,CAAC,CAAE;CACrD,CAAC;;;;;CAMD,MAAM,UAAU,eAAe;EAC7B,MAAM,EAAE,YAAY;EAEpB,IAAI,OAAO,YAAY,YAAY,OAAO,cAAc;EAExD,OAAO,CAAC,GAAG,YAAY,OAAO,GAAG,gBAAgB,KAAK;CACxD,CAAC;CAED,MAAM,oBAAoB,IAAY,iBAAoD;EACxF,MAAM,WAAW,SAAS,MAAM,UAAU,OAAO;EACjD,MAAM,gBAAgB,CAAC,GAAG,eAAe,OAAO,GAAI,gBAAgB,CAAC,CAAE;EAEvE,IAAI,CAAC,IAAI;GACP,gBAAgB,QAAQ;GACxB,cAAc,IAAI,gBAAgB,KAAK;GACvC;EACF;EAEA,MAAM,mBAAmB,cAAc,QAAQ,SAAS;GACtD,OAAOA,EAAS,IAAI,CAAC,CAAC,IAAI,QAAQ,CAAC,EAAE,SAAS,EAAE,KAAK;EACvD,CAAC;EAED,cAAc,IAAI,gBAAgB;EAClC,gBAAgB,QAAQ;CAC1B;CAGA,MAAM,uBAAuB,UAC1B,IAAY,iBAAoD;EAE/D,IAAI,CAAC,YAAY,OAAO;GACtB,iBAAiB,IAAI,YAAY;GACjC;EACF;EACA,iBAAiB,IAAI,YAAY;CACnC,GACA,GACF;CAEA,MAAM,wBAAwB,SAAS,OAAO,IAAY,iBAA2B;EACnF,MAAM,UAAU,MAAM,aAAa,YAAY,KAAK;EACpD,cAAc,QAAQ;EACtB,cAAc,YAAY,OAAO,OAAO;CAC1C,GAAG,GAAG;CAEN,MACE;EAAC;QAAmB,MAAM;EAAS;CAAc,IAChD,CAAC,IAAI,kBAAkB;EACtB,IAAI,OAAO,iBAAiB,YAAY;GACtC,sBAAsB,IAAI,YAAY;GACtC;EACF;EAEA,IAAI,CAAC,IAAI;GACP,iBAAiB,IAAI,YAAY;GACjC;EACF;EAEA,qBAAqB,IAAI,YAAY;CACvC,GACA,EAAE,WAAW,KAAK,CACpB;CAEA,OAAO;EAAE;EAAa;EAAS;EAAY;EAA4B;CAAoB;AAC7F"}
@@ -7,11 +7,11 @@ type __VLS_Slots = {
7
7
  tip?: (scope: StepsSlotScope) => any;
8
8
  };
9
9
  declare const __VLS_base: import("vue").DefineComponent<StepsProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
10
- "item-click": (item: Record<string, any>, index: number) => any;
11
10
  "update:current": (value?: string | number | undefined) => any;
11
+ "item-click": (item: Record<string, any>, index: number) => any;
12
12
  }, string, import("vue").PublicProps, Readonly<StepsProps> & Readonly<{
13
- "onItem-click"?: ((item: Record<string, any>, index: number) => any) | undefined;
14
13
  "onUpdate:current"?: ((value?: string | number | undefined) => any) | undefined;
14
+ "onItem-click"?: ((item: Record<string, any>, index: number) => any) | undefined;
15
15
  }>, {
16
16
  labelKey: string;
17
17
  direction: "horizontal" | "vertical";
@@ -16,12 +16,12 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
16
16
  "update:modelValue": (value: string | undefined) => any;
17
17
  } & {
18
18
  "update:modelValue": (value: string) => any;
19
- click: (item: TabItem, index: number) => any;
20
19
  close: (item: TabItem, index: number) => any;
20
+ click: (item: TabItem, index: number) => any;
21
21
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
22
22
  "onUpdate:modelValue"?: ((value: string) => any) | undefined;
23
- onClick?: ((item: TabItem, index: number) => any) | undefined;
24
23
  onClose?: ((item: TabItem, index: number) => any) | undefined;
24
+ onClick?: ((item: TabItem, index: number) => any) | undefined;
25
25
  }>, {
26
26
  closable: boolean;
27
27
  block: boolean;
@@ -16,12 +16,12 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
16
16
  "update:modelValue": (value: string | undefined) => any;
17
17
  } & {
18
18
  "update:modelValue": (value: string) => any;
19
- click: (item: TabItem, index: number) => any;
20
19
  close: (item: TabItem, index: number) => any;
20
+ click: (item: TabItem, index: number) => any;
21
21
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
22
22
  "onUpdate:modelValue"?: ((value: string) => any) | undefined;
23
- onClick?: ((item: TabItem, index: number) => any) | undefined;
24
23
  onClose?: ((item: TabItem, index: number) => any) | undefined;
24
+ onClick?: ((item: TabItem, index: number) => any) | undefined;
25
25
  }>, {
26
26
  closable: boolean;
27
27
  rounded: boolean;
@@ -11,12 +11,12 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
11
11
  "update:modelValue": (value: string | undefined) => any;
12
12
  } & {
13
13
  "update:modelValue": (value: string) => any;
14
- click: (item: TabItem, index: number) => any;
15
14
  close: (item: TabItem, index: number) => any;
15
+ click: (item: TabItem, index: number) => any;
16
16
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
17
17
  "onUpdate:modelValue"?: ((value: string) => any) | undefined;
18
- onClick?: ((item: TabItem, index: number) => any) | undefined;
19
18
  onClose?: ((item: TabItem, index: number) => any) | undefined;
19
+ onClick?: ((item: TabItem, index: number) => any) | undefined;
20
20
  }>, {
21
21
  closable: boolean;
22
22
  block: boolean;
@@ -82,6 +82,7 @@
82
82
  }
83
83
  .u-textarea.is-focus {
84
84
  border-color: var(--u-color-primary);
85
+ box-shadow: var(--u-focus-ring);
85
86
  }
86
87
  .u-textarea.is-disabled {
87
88
  background-color: var(--u-color-disabled);
@@ -21,11 +21,11 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
21
21
  onFocus?: (() => any) | undefined;
22
22
  onBlur?: (() => any) | undefined;
23
23
  }>, {
24
+ resize: boolean;
24
25
  placeholder: string;
25
26
  clearable: boolean;
26
27
  disabled: boolean;
27
28
  readonly: boolean;
28
- resize: boolean;
29
29
  autosize: boolean;
30
30
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
31
31
  declare const _default: typeof __VLS_export;
@@ -21,9 +21,9 @@ declare const __VLS_base: import("vue").DefineComponent<TreeProps, _TreeExposed,
21
21
  "onNode-contextmenu"?: ((event: MouseEvent, node: TreeNode<Record<string, any>>) => any) | undefined;
22
22
  "onSelected-synced"?: ((selected?: Record<string, any> | undefined) => any) | undefined;
23
23
  }>, {
24
+ expandOnClickNode: boolean;
24
25
  labelKey: string;
25
26
  valueKey: string;
26
- expandOnClickNode: boolean;
27
27
  childrenKey: string;
28
28
  data: Record<string, any>[];
29
29
  checkStrictly: boolean;
@@ -35,8 +35,8 @@
35
35
  padding: 0;
36
36
  background: none;
37
37
  }
38
- .u-tree-select__filter {
39
- margin-bottom: 4px;
38
+ .u-tree-select__clear {
39
+ cursor: pointer;
40
40
  }
41
41
  .u-tree-select__content-header {
42
42
  padding: 4px 12px;
@@ -48,35 +48,26 @@
48
48
  flex-wrap: nowrap;
49
49
  }
50
50
  .u-tree-select__content-tree {
51
- max-height: 200px;
52
- }
53
- .u-tree-select__panel--small .u-tree-select__content-filter {
54
- padding: calc(var(--u-gap-small) / 2) var(--u-gap-small);
51
+ max-height: 240px;
55
52
  }
56
53
  .u-tree-select__panel--small .u-tree-select__content-tree {
57
- padding: calc(var(--u-gap-small) / 2) var(--u-gap-small);
54
+ padding: var(--u-gap-small);
58
55
  }
59
56
  .u-tree-select__panel--small .u-tree-select__empty {
60
57
  height: var(--u-form-component-height-small);
61
58
  line-height: var(--u-form-component-height-small);
62
59
  padding: 0 var(--u-gap-small);
63
60
  }
64
- .u-tree-select__panel--default .u-tree-select__content-filter {
65
- padding: calc(var(--u-gap-default) / 2) var(--u-gap-default);
66
- }
67
61
  .u-tree-select__panel--default .u-tree-select__content-tree {
68
- padding: calc(var(--u-gap-default) / 2) var(--u-gap-default);
62
+ padding: var(--u-gap-default);
69
63
  }
70
64
  .u-tree-select__panel--default .u-tree-select__empty {
71
65
  height: var(--u-form-component-height-default);
72
66
  line-height: var(--u-form-component-height-default);
73
67
  padding: 0 var(--u-gap-default);
74
68
  }
75
- .u-tree-select__panel--large .u-tree-select__content-filter {
76
- padding: calc(var(--u-gap-large) / 2) var(--u-gap-large);
77
- }
78
69
  .u-tree-select__panel--large .u-tree-select__content-tree {
79
- padding: calc(var(--u-gap-large) / 2) var(--u-gap-large);
70
+ padding: var(--u-gap-large);
80
71
  }
81
72
  .u-tree-select__panel--large .u-tree-select__empty {
82
73
  height: var(--u-form-component-height-large);
@@ -2,10 +2,10 @@ import _sfc_main$1 from "../icon/icon.js";
2
2
  import _sfc_main$2 from "../dropdown/dropdown.js";
3
3
  import input_default from "../input/input.js";
4
4
  import _sfc_main$3 from "../tree/tree.js";
5
- import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createSlots, createTextVNode, createVNode, defineComponent, mergeModels, mergeProps, nextTick, normalizeClass, openBlock, renderSlot, shallowRef, toDisplayString, unref, useModel, useSlots, watch, withCtx } from "vue";
5
+ import { Fragment, Transition, computed, createBlock, createCommentVNode, createElementBlock, createSlots, createTextVNode, createVNode, defineComponent, mergeModels, mergeProps, nextTick, normalizeClass, openBlock, renderSlot, shallowRef, toDisplayString, unref, useModel, useSlots, useTemplateRef, watch, withCtx, withModifiers } from "vue";
6
6
  import { useFormFallbackProps } from "@veltra/compositions";
7
7
  import { FORM_EMPTY_CONTENT, bem, fieldKey, injectFormContext } from "@veltra/utils";
8
- import { ArrowDown, Search } from "@veltra/icons/normal";
8
+ import { ArrowDown, Close } from "@veltra/icons/normal";
9
9
  import { dfs, o } from "@cat-kit/core";
10
10
  //#region src/components/tree-select/tree-select.vue
11
11
  const _sfc_main = /*@__PURE__*/ defineComponent({
@@ -93,6 +93,52 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
93
93
  });
94
94
  const model = useModel(__props, "modelValue");
95
95
  const label = shallowRef();
96
+ const dropdownVisible = shallowRef(false);
97
+ /**
98
+ * 是否处于查询态:决定触发输入框显示查询串还是选中标签。
99
+ * 与面板可见状态解耦 —— 选择后立即退出查询态,
100
+ * 不等面板关闭动画结束(否则显示值会延迟一个动画时长才恢复)。
101
+ */
102
+ const querying = shallowRef(false);
103
+ const inputRef = useTemplateRef("inputRef");
104
+ /** 触发输入框的值:查询态下承载查询串,否则展示选中标签 */
105
+ const inputValue = computed(() => {
106
+ if (props.filterable && querying.value) return qs.value;
107
+ return props.text ?? (model.value ? label.value : void 0);
108
+ });
109
+ /** 查询态下已选标签降级为占位提示 */
110
+ const inputPlaceholder = computed(() => {
111
+ const display = props.text ?? (model.value ? label.value : void 0);
112
+ if (props.filterable && querying.value && display) return display;
113
+ return props.placeholder;
114
+ });
115
+ function handleQueryInput(value) {
116
+ if (!props.filterable) return;
117
+ qs.value = value;
118
+ }
119
+ const hovered = shallowRef(false);
120
+ /** 悬停且存在选中值时展示清除按钮(替代下拉箭头) */
121
+ const showClear = computed(() => {
122
+ if (!props.clearable || disabled.value || !hovered.value) return false;
123
+ return !!(props.text ?? (model.value ? label.value : void 0));
124
+ });
125
+ /**
126
+ * 过滤模式下拦截输入区域的点击:
127
+ * 阻止 dropdown 的 trigger 开合切换,保持面板展开以不中断输入。
128
+ * 非输入区域(箭头、留白)放行,维持原开合行为。
129
+ */
130
+ function handleTriggerClickCapture(e) {
131
+ if (!props.filterable || disabled.value) return;
132
+ if (!(e.target instanceof HTMLInputElement)) return;
133
+ e.stopPropagation();
134
+ if (!dropdownVisible.value) dropdownRef.value?.open();
135
+ }
136
+ watch(dropdownVisible, (visible) => {
137
+ if (visible && props.filterable) {
138
+ querying.value = true;
139
+ nextTick(() => inputRef.value?.el?.focus());
140
+ } else if (!visible) querying.value = false;
141
+ });
96
142
  const { formProps } = injectFormContext();
97
143
  const { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props]);
98
144
  const treeRef = shallowRef();
@@ -136,6 +182,8 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
136
182
  else label.value = "";
137
183
  emit("change", selectedData);
138
184
  emit("update:text", label.value);
185
+ querying.value = false;
186
+ qs.value = "";
139
187
  dropdownRef.value?.close();
140
188
  };
141
189
  const handleDropdownVisible = (visible) => {
@@ -153,24 +201,47 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
153
201
  "content-style": __props.contentStyle,
154
202
  ref_key: "dropdownRef",
155
203
  ref: dropdownRef,
204
+ visible: dropdownVisible.value,
205
+ "onUpdate:visible": [_cache[0] || (_cache[0] = ($event) => dropdownVisible.value = $event), handleDropdownVisible],
156
206
  "min-width": __props.minWidth,
157
207
  width: __props.width,
158
208
  disabled: unref(disabled),
159
- "onUpdate:visible": handleDropdownVisible
209
+ onMouseenter: _cache[1] || (_cache[1] = ($event) => hovered.value = true),
210
+ onMouseleave: _cache[2] || (_cache[2] = ($event) => hovered.value = false)
160
211
  }), {
161
212
  trigger: withCtx(() => [createVNode(unref(input_default), {
213
+ ref_key: "inputRef",
214
+ ref: inputRef,
162
215
  size: unref(size),
163
216
  disabled: unref(disabled),
164
- placeholder: __props.placeholder,
165
- clearable: __props.clearable,
166
- "model-value": __props.text ?? (model.value ? label.value : void 0),
167
- onClear: handleClear,
168
- "native-readonly": ""
217
+ placeholder: inputPlaceholder.value,
218
+ clearable: false,
219
+ "model-value": inputValue.value,
220
+ "onUpdate:modelValue": handleQueryInput,
221
+ "native-readonly": !__props.filterable || !querying.value,
222
+ onClickCapture: handleTriggerClickCapture
169
223
  }, createSlots({
170
- suffix: withCtx(() => [createVNode(unref(_sfc_main$1), { class: normalizeClass(unref(cls).e("arrow")) }, {
171
- default: withCtx(() => [createVNode(unref(ArrowDown))]),
224
+ suffix: withCtx(() => [createVNode(Transition, {
225
+ name: "zoom-in",
226
+ mode: "out-in"
227
+ }, {
228
+ default: withCtx(() => [showClear.value ? (openBlock(), createBlock(unref(_sfc_main$1), {
229
+ class: normalizeClass(unref(cls).e("clear")),
230
+ title: "清除",
231
+ key: "clear",
232
+ onClick: withModifiers(handleClear, ["stop"])
233
+ }, {
234
+ default: withCtx(() => [createVNode(unref(Close))]),
235
+ _: 1
236
+ }, 8, ["class"])) : (openBlock(), createBlock(unref(_sfc_main$1), {
237
+ class: normalizeClass(unref(cls).e("arrow")),
238
+ key: "arrow"
239
+ }, {
240
+ default: withCtx(() => [createVNode(unref(ArrowDown))]),
241
+ _: 1
242
+ }, 8, ["class"]))]),
172
243
  _: 1
173
- }, 8, ["class"])]),
244
+ })]),
174
245
  _: 2
175
246
  }, [_ctx.$slots.prefix ? {
176
247
  name: "prefix",
@@ -180,42 +251,25 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
180
251
  "size",
181
252
  "disabled",
182
253
  "placeholder",
183
- "clearable",
184
- "model-value"
254
+ "model-value",
255
+ "native-readonly"
185
256
  ])]),
186
- content: withCtx(() => [
187
- createCommentVNode(" 过滤器 "),
188
- __props.filterable ? (openBlock(), createElementBlock("div", {
189
- key: 0,
190
- class: normalizeClass([unref(cls).e("content-filter"), unref(cls).m(unref(size))])
191
- }, [createVNode(unref(input_default), {
192
- placeholder: "输入关键字进行过滤",
193
- modelValue: qs.value,
194
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => qs.value = $event)
195
- }, {
196
- suffix: withCtx(() => [createVNode(unref(_sfc_main$1), null, {
197
- default: withCtx(() => [createVNode(unref(Search))]),
198
- _: 1
199
- })]),
200
- _: 1
201
- }, 8, ["modelValue"])], 2)) : createCommentVNode("v-if", true),
202
- createCommentVNode(" 菜单列表 "),
203
- createVNode(unref(_sfc_main$3), mergeProps(treeProps.value, {
204
- selected: model.value,
205
- "onUpdate:selected": handleSelect,
206
- ref_key: "treeRef",
207
- ref: treeRef,
208
- selectable: "",
209
- class: unref(cls).e("content-tree"),
210
- slots,
211
- "scroll-to-view": ""
212
- }), null, 16, ["selected", "class"])
213
- ]),
257
+ content: withCtx(() => [createCommentVNode(" 菜单列表 "), createVNode(unref(_sfc_main$3), mergeProps(treeProps.value, {
258
+ selected: model.value,
259
+ "onUpdate:selected": handleSelect,
260
+ ref_key: "treeRef",
261
+ ref: treeRef,
262
+ selectable: "",
263
+ class: unref(cls).e("content-tree"),
264
+ slots,
265
+ "scroll-to-view": ""
266
+ }), null, 16, ["selected", "class"])]),
214
267
  _: 3
215
268
  }, 16, [
216
269
  "class",
217
270
  "content-class",
218
271
  "content-style",
272
+ "visible",
219
273
  "min-width",
220
274
  "width",
221
275
  "disabled"
@@ -1 +1 @@
1
- {"version":3,"file":"tree-select.js","names":["$attrs","$slots"],"sources":["../../../src/components/tree-select/tree-select.vue"],"sourcesContent":["<template>\n <u-dropdown\n v-if=\"!readonly\"\n v-bind=\"$attrs\"\n :class=\"[cls.b, bem.is('disabled', disabled)]\"\n trigger=\"click\"\n :content-class=\"[cls.e('panel'), cls.em('panel', size), contentClass]\"\n :content-style=\"contentStyle\"\n ref=\"dropdownRef\"\n :min-width=\"minWidth\"\n :width=\"width\"\n :disabled=\"disabled\"\n @update:visible=\"handleDropdownVisible\"\n >\n <template #trigger>\n <u-input\n :size=\"size\"\n :disabled=\"disabled\"\n :placeholder=\"placeholder\"\n :clearable=\"clearable\"\n :model-value=\"text ?? (model ? label : undefined)\"\n @clear=\"handleClear\"\n native-readonly\n >\n <template #prefix v-if=\"$slots.prefix\">\n <slot name=\"prefix\" />\n </template>\n <template #suffix>\n <u-icon :class=\"cls.e('arrow')\"><ArrowDown /></u-icon>\n </template>\n </u-input>\n </template>\n <template #content>\n <!-- 过滤器 -->\n <div v-if=\"filterable\" :class=\"[cls.e('content-filter'), cls.m(size)]\">\n <u-input placeholder=\"输入关键字进行过滤\" v-model=\"qs\">\n <template #suffix>\n <u-icon><Search /></u-icon>\n </template>\n </u-input>\n </div>\n <!-- 菜单列表 -->\n\n <u-tree\n v-bind=\"treeProps\"\n :selected=\"model\"\n @update:selected=\"handleSelect\"\n ref=\"treeRef\"\n selectable\n :class=\"cls.e('content-tree')\"\n :slots=\"slots\"\n scroll-to-view\n />\n </template>\n </u-dropdown>\n\n <template v-else>\n {{ text || label || FORM_EMPTY_CONTENT }}\n </template>\n</template>\n\n<script lang=\"ts\" setup>\nimport { dfs, o } from '@cat-kit/core'\nimport { useFormFallbackProps } from '@veltra/compositions'\nimport { ArrowDown, Search } from '@veltra/icons/normal'\nimport { bem, fieldKey, FORM_EMPTY_CONTENT } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport { computed, nextTick, shallowRef, watch } from 'vue'\n\nimport type { TreeSelectProps, TreeSelectEmits, TreeExposed } from '../../types'\nimport { UDropdown } from '../dropdown'\nimport { UIcon } from '../icon'\nimport { UInput } from '../input'\nimport { UTree } from '../tree'\nimport type { TreeSlotsScope } from '../tree/di'\n\ndefineOptions({ name: 'UTreeSelect', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<TreeSelectProps>(), {\n labelKey: 'label',\n valueKey: 'value',\n placeholder: '请选择',\n expandAll: false,\n clearable: true,\n disabled: undefined,\n readonly: undefined,\n filterable: false,\n minWidth: '280px'\n})\n\nconst emit = defineEmits<TreeSelectEmits>()\n\nconst slots = defineSlots<{\n /** 默认插槽 */\n default?: (props: TreeSlotsScope) => any\n /** 前缀插槽 */\n prefix?: () => any\n}>()\n\nconst treeProps = computed(() => {\n return o(props as Record<string, any>).omit([\n 'tips',\n 'field',\n 'placeholder',\n 'disabled',\n 'label',\n 'readonly',\n 'contentClass',\n 'contentStyle',\n 'minWidth',\n 'width'\n ])\n})\n\nconst cls = bem('tree-select')\n\nconst labelKey = computed(() => fieldKey(props.labelKey, 'label'))\nconst valueKey = computed(() => fieldKey(props.valueKey, 'value'))\n\n/**过滤 */\nconst qs = shallowRef('')\nwatch(qs, (qs) => {\n treeRef.value?.filter(qs)\n})\n\nconst model = defineModel<string | number>()\n\nconst label = shallowRef<string>()\n\nconst { formProps } = injectFormContext()\n\nconst { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props])\n\nconst treeRef = shallowRef<TreeExposed>()\n\nconst dropdownRef = shallowRef<InstanceType<typeof UDropdown>>()\n\n/**清空 */\nconst handleClear = () => {\n model.value = ''\n label.value = undefined\n emit('clear')\n emit('change', undefined)\n emit('update:text', '')\n}\n\nlet changedByEvent = false\nwatch(\n [() => props.data, model],\n ([data, model]) => {\n if (changedByEvent) return\n if (!data?.length || model === undefined) {\n label.value = undefined\n model = undefined\n return\n }\n\n let founded = false\n const childrenKey = props.childrenKey ?? 'children'\n data.some((item) => {\n dfs(\n item,\n (v) => {\n if (v[valueKey.value] === model) {\n label.value = v[labelKey.value]\n founded = true\n return true\n }\n },\n childrenKey\n )\n\n return founded\n })\n },\n { immediate: true }\n)\n\nconst handleSelect = (selected?: string | number, selectedData?: Record<string, any>) => {\n changedByEvent = true\n nextTick(() => {\n changedByEvent = false\n })\n\n model.value = selected ?? ''\n\n if (selectedData) {\n label.value = o(selectedData).get(labelKey.value)\n } else {\n label.value = ''\n }\n\n emit('change', selectedData)\n emit('update:text', label.value)\n dropdownRef.value?.close()\n}\n\nconst handleDropdownVisible = (visible: boolean) => {\n if (!visible) {\n qs.value = ''\n }\n}\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"tree-select.js","names":["$attrs","$slots"],"sources":["../../../src/components/tree-select/tree-select.vue"],"sourcesContent":["<template>\n <u-dropdown\n v-if=\"!readonly\"\n v-bind=\"$attrs\"\n :class=\"[cls.b, bem.is('disabled', disabled)]\"\n trigger=\"click\"\n :content-class=\"[cls.e('panel'), cls.em('panel', size), contentClass]\"\n :content-style=\"contentStyle\"\n ref=\"dropdownRef\"\n v-model:visible=\"dropdownVisible\"\n :min-width=\"minWidth\"\n :width=\"width\"\n :disabled=\"disabled\"\n @update:visible=\"handleDropdownVisible\"\n @mouseenter=\"hovered = true\"\n @mouseleave=\"hovered = false\"\n >\n <template #trigger>\n <u-input\n ref=\"inputRef\"\n :size=\"size\"\n :disabled=\"disabled\"\n :placeholder=\"inputPlaceholder\"\n :clearable=\"false\"\n :model-value=\"inputValue\"\n @update:model-value=\"handleQueryInput\"\n :native-readonly=\"!filterable || !querying\"\n @click.capture=\"handleTriggerClickCapture\"\n >\n <template #prefix v-if=\"$slots.prefix\">\n <slot name=\"prefix\" />\n </template>\n <template #suffix>\n <transition name=\"zoom-in\" mode=\"out-in\">\n <u-icon\n v-if=\"showClear\"\n :class=\"cls.e('clear')\"\n title=\"清除\"\n key=\"clear\"\n @click.stop=\"handleClear\"\n >\n <Close />\n </u-icon>\n <u-icon v-else :class=\"cls.e('arrow')\" key=\"arrow\"><ArrowDown /></u-icon>\n </transition>\n </template>\n </u-input>\n </template>\n <template #content>\n <!-- 菜单列表 -->\n\n <u-tree\n v-bind=\"treeProps\"\n :selected=\"model\"\n @update:selected=\"handleSelect\"\n ref=\"treeRef\"\n selectable\n :class=\"cls.e('content-tree')\"\n :slots=\"slots\"\n scroll-to-view\n />\n </template>\n </u-dropdown>\n\n <template v-else>\n {{ text || label || FORM_EMPTY_CONTENT }}\n </template>\n</template>\n\n<script lang=\"ts\" setup>\nimport { dfs, o } from '@cat-kit/core'\nimport { useFormFallbackProps } from '@veltra/compositions'\nimport { ArrowDown, Close } from '@veltra/icons/normal'\nimport { bem, fieldKey, FORM_EMPTY_CONTENT } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport { computed, nextTick, shallowRef, useTemplateRef, watch } from 'vue'\n\nimport type { TreeSelectProps, TreeSelectEmits, TreeExposed, InputExposed } from '../../types'\nimport { UDropdown } from '../dropdown'\nimport { UIcon } from '../icon'\nimport { UInput } from '../input'\nimport { UTree } from '../tree'\nimport type { TreeSlotsScope } from '../tree/di'\n\ndefineOptions({ name: 'UTreeSelect', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<TreeSelectProps>(), {\n labelKey: 'label',\n valueKey: 'value',\n placeholder: '请选择',\n expandAll: false,\n clearable: true,\n disabled: undefined,\n readonly: undefined,\n filterable: false,\n minWidth: '280px'\n})\n\nconst emit = defineEmits<TreeSelectEmits>()\n\nconst slots = defineSlots<{\n /** 默认插槽 */\n default?: (props: TreeSlotsScope) => any\n /** 前缀插槽 */\n prefix?: () => any\n}>()\n\nconst treeProps = computed(() => {\n return o(props as Record<string, any>).omit([\n 'tips',\n 'field',\n 'placeholder',\n 'disabled',\n 'label',\n 'readonly',\n 'contentClass',\n 'contentStyle',\n 'minWidth',\n 'width'\n ])\n})\n\nconst cls = bem('tree-select')\n\nconst labelKey = computed(() => fieldKey(props.labelKey, 'label'))\nconst valueKey = computed(() => fieldKey(props.valueKey, 'value'))\n\n/**过滤 */\nconst qs = shallowRef('')\nwatch(qs, (qs) => {\n treeRef.value?.filter(qs)\n})\n\nconst model = defineModel<string | number>()\n\nconst label = shallowRef<string>()\n\nconst dropdownVisible = shallowRef(false)\n\n/**\n * 是否处于查询态:决定触发输入框显示查询串还是选中标签。\n * 与面板可见状态解耦 —— 选择后立即退出查询态,\n * 不等面板关闭动画结束(否则显示值会延迟一个动画时长才恢复)。\n */\nconst querying = shallowRef(false)\n\nconst inputRef = useTemplateRef<InputExposed>('inputRef')\n\n/** 触发输入框的值:查询态下承载查询串,否则展示选中标签 */\nconst inputValue = computed(() => {\n if (props.filterable && querying.value) return qs.value\n return props.text ?? (model.value ? label.value : undefined)\n})\n\n/** 查询态下已选标签降级为占位提示 */\nconst inputPlaceholder = computed(() => {\n const display = props.text ?? (model.value ? label.value : undefined)\n if (props.filterable && querying.value && display) {\n return display\n }\n return props.placeholder\n})\n\nfunction handleQueryInput(value: string) {\n if (!props.filterable) return\n qs.value = value\n}\n\nconst hovered = shallowRef(false)\n\n/** 悬停且存在选中值时展示清除按钮(替代下拉箭头) */\nconst showClear = computed(() => {\n if (!props.clearable || disabled.value || !hovered.value) return false\n return !!(props.text ?? (model.value ? label.value : undefined))\n})\n\n/**\n * 过滤模式下拦截输入区域的点击:\n * 阻止 dropdown 的 trigger 开合切换,保持面板展开以不中断输入。\n * 非输入区域(箭头、留白)放行,维持原开合行为。\n */\nfunction handleTriggerClickCapture(e: MouseEvent) {\n if (!props.filterable || disabled.value) return\n if (!(e.target instanceof HTMLInputElement)) return\n\n e.stopPropagation()\n if (!dropdownVisible.value) dropdownRef.value?.open()\n}\n\nwatch(dropdownVisible, (visible) => {\n if (visible && props.filterable) {\n // 面板展开后进入查询态并聚焦输入框,可以立即输入查询\n querying.value = true\n nextTick(() => inputRef.value?.el?.focus())\n } else if (!visible) {\n querying.value = false\n }\n})\n\nconst { formProps } = injectFormContext()\n\nconst { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props])\n\nconst treeRef = shallowRef<TreeExposed>()\n\nconst dropdownRef = shallowRef<InstanceType<typeof UDropdown>>()\n\n/**清空 */\nconst handleClear = () => {\n model.value = ''\n label.value = undefined\n emit('clear')\n emit('change', undefined)\n emit('update:text', '')\n}\n\nlet changedByEvent = false\nwatch(\n [() => props.data, model],\n ([data, model]) => {\n if (changedByEvent) return\n if (!data?.length || model === undefined) {\n label.value = undefined\n model = undefined\n return\n }\n\n let founded = false\n const childrenKey = props.childrenKey ?? 'children'\n data.some((item) => {\n dfs(\n item,\n (v) => {\n if (v[valueKey.value] === model) {\n label.value = v[labelKey.value]\n founded = true\n return true\n }\n },\n childrenKey\n )\n\n return founded\n })\n },\n { immediate: true }\n)\n\nconst handleSelect = (selected?: string | number, selectedData?: Record<string, any>) => {\n changedByEvent = true\n nextTick(() => {\n changedByEvent = false\n })\n\n model.value = selected ?? ''\n\n if (selectedData) {\n label.value = o(selectedData).get(labelKey.value)\n } else {\n label.value = ''\n }\n\n emit('change', selectedData)\n emit('update:text', label.value)\n // 立即退出查询态,输入框同步恢复显示选中标签\n querying.value = false\n qs.value = ''\n dropdownRef.value?.close()\n}\n\nconst handleDropdownVisible = (visible: boolean) => {\n if (!visible) {\n qs.value = ''\n }\n}\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsFA,MAAM,QAAQ;EAYd,MAAM,OAAO;EAEb,MAAM,QAAQ,SAAA;EAOd,MAAM,YAAY,eAAe;GAC/B,OAAO,EAAE,KAA4B,CAAC,CAAC,KAAK;IAC1C;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;GACF,CAAC;EACH,CAAC;EAED,MAAM,MAAM,IAAI,aAAa;EAE7B,MAAM,WAAW,eAAe,SAAS,MAAM,UAAU,OAAO,CAAC;EACjE,MAAM,WAAW,eAAe,SAAS,MAAM,UAAU,OAAO,CAAC;;EAGjE,MAAM,KAAK,WAAW,EAAE;EACxB,MAAM,KAAK,OAAO;GAChB,QAAQ,OAAO,OAAO,EAAE;EAC1B,CAAC;EAED,MAAM,QAAQ,SAA4B,SAAA,YAAC;EAE3C,MAAM,QAAQ,WAAmB;EAEjC,MAAM,kBAAkB,WAAW,KAAK;;;;;;EAOxC,MAAM,WAAW,WAAW,KAAK;EAEjC,MAAM,WAAW,eAA6B,UAAU;;EAGxD,MAAM,aAAa,eAAe;GAChC,IAAI,MAAM,cAAc,SAAS,OAAO,OAAO,GAAG;GAClD,OAAO,MAAM,SAAS,MAAM,QAAQ,MAAM,QAAQ,KAAA;EACpD,CAAC;;EAGD,MAAM,mBAAmB,eAAe;GACtC,MAAM,UAAU,MAAM,SAAS,MAAM,QAAQ,MAAM,QAAQ,KAAA;GAC3D,IAAI,MAAM,cAAc,SAAS,SAAS,SACxC,OAAO;GAET,OAAO,MAAM;EACf,CAAC;EAED,SAAS,iBAAiB,OAAe;GACvC,IAAI,CAAC,MAAM,YAAY;GACvB,GAAG,QAAQ;EACb;EAEA,MAAM,UAAU,WAAW,KAAK;;EAGhC,MAAM,YAAY,eAAe;GAC/B,IAAI,CAAC,MAAM,aAAa,SAAS,SAAS,CAAC,QAAQ,OAAO,OAAO;GACjE,OAAO,CAAC,EAAE,MAAM,SAAS,MAAM,QAAQ,MAAM,QAAQ,KAAA;EACvD,CAAC;;;;;;EAOD,SAAS,0BAA0B,GAAe;GAChD,IAAI,CAAC,MAAM,cAAc,SAAS,OAAO;GACzC,IAAI,EAAE,EAAE,kBAAkB,mBAAmB;GAE7C,EAAE,gBAAgB;GAClB,IAAI,CAAC,gBAAgB,OAAO,YAAY,OAAO,KAAK;EACtD;EAEA,MAAM,kBAAkB,YAAY;GAClC,IAAI,WAAW,MAAM,YAAY;IAE/B,SAAS,QAAQ;IACjB,eAAe,SAAS,OAAO,IAAI,MAAM,CAAC;GAC5C,OAAO,IAAI,CAAC,SACV,SAAS,QAAQ;EAErB,CAAC;EAED,MAAM,EAAE,cAAc,kBAAkB;EAExC,MAAM,EAAE,MAAM,UAAU,aAAa,qBAAqB,CAAC,aAAa,CAAC,GAAG,KAAK,CAAC;EAElF,MAAM,UAAU,WAAwB;EAExC,MAAM,cAAc,WAA2C;;EAG/D,MAAM,oBAAoB;GACxB,MAAM,QAAQ;GACd,MAAM,QAAQ,KAAA;GACd,KAAK,OAAO;GACZ,KAAK,UAAU,KAAA,CAAS;GACxB,KAAK,eAAe,EAAE;EACxB;EAEA,IAAI,iBAAiB;EACrB,MACE,OAAO,MAAM,MAAM,KAAK,IACvB,CAAC,MAAM,WAAW;GACjB,IAAI,gBAAgB;GACpB,IAAI,CAAC,MAAM,UAAU,UAAU,KAAA,GAAW;IACxC,MAAM,QAAQ,KAAA;IACd,QAAQ,KAAA;IACR;GACF;GAEA,IAAI,UAAU;GACd,MAAM,cAAc,MAAM,eAAe;GACzC,KAAK,MAAM,SAAS;IAClB,IACE,OACC,MAAM;KACL,IAAI,EAAE,SAAS,WAAW,OAAO;MAC/B,MAAM,QAAQ,EAAE,SAAS;MACzB,UAAU;MACV,OAAO;KACT;IACF,GACA,WACF;IAEA,OAAO;GACT,CAAC;EACH,GACA,EAAE,WAAW,KAAK,CACpB;EAEA,MAAM,gBAAgB,UAA4B,iBAAuC;GACvF,iBAAiB;GACjB,eAAe;IACb,iBAAiB;GACnB,CAAC;GAED,MAAM,QAAQ,YAAY;GAE1B,IAAI,cACF,MAAM,QAAQ,EAAE,YAAY,CAAC,CAAC,IAAI,SAAS,KAAK;QAEhD,MAAM,QAAQ;GAGhB,KAAK,UAAU,YAAY;GAC3B,KAAK,eAAe,MAAM,KAAK;GAE/B,SAAS,QAAQ;GACjB,GAAG,QAAQ;GACX,YAAY,OAAO,MAAM;EAC3B;EAEA,MAAM,yBAAyB,YAAqB;GAClD,IAAI,CAAC,SACH,GAAG,QAAQ;EAEf;;WAhRW,MAAA,QAAA,KAAA,UAAA,GADT,YA6Da,MAAA,WAAA,GA7Db,WA6Da,EAAA,KAAA,EAAA,GA3DHA,KAAAA,QAAM;IACb,OAAK,CAAG,MAAA,GAAA,CAAG,CAAC,GAAG,MAAA,GAAA,CAAG,CAAC,GAAE,YAAa,MAAA,QAAA,CAAQ,CAAA;IAC3C,SAAQ;IACP,iBAAa;KAAG,MAAA,GAAA,CAAG,CAAC,EAAC,OAAA;KAAW,MAAA,GAAA,CAAG,CAAC,GAAE,SAAU,MAAA,IAAA,CAAI;KAAG,QAAA;IAAY;IACnE,iBAAe,QAAA;aACZ;IAAJ,KAAI;IACI,SAAS,gBAAA;+DAAA,gBAAe,QAAA,SAIf,qBAAA;IAHhB,aAAW,QAAA;IACX,OAAO,QAAA;IACP,UAAU,MAAA,QAAA;IAEV,cAAU,OAAA,OAAA,OAAA,MAAA,WAAE,QAAA,QAAO;IACnB,cAAU,OAAA,OAAA,OAAA,MAAA,WAAE,QAAA,QAAO;;IAET,SAAO,cA6BN,CA5BV,YA4BU,MAAA,aAAA,GAAA;cA3BJ;KAAJ,KAAI;KACH,MAAM,MAAA,IAAA;KACN,UAAU,MAAA,QAAA;KACV,aAAa,iBAAA;KACb,WAAW;KACX,eAAa,WAAA;KACb,uBAAoB;KACpB,mBAAe,CAAG,QAAA,cAAU,CAAK,SAAA;qBAClB;;KAKL,QAAM,cAYF,CAXb,YAWa,YAAA;MAXD,MAAK;MAAU,MAAK;;6BASrB,CAPD,UAAA,SAAA,UAAA,GADR,YAQS,MAAA,WAAA,GAAA;OANN,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,OAAA,CAAA;OACb,OAAM;OACN,KAAI;OACH,SAAK,cAAO,aAAW,CAAA,MAAA,CAAA;;8BAEf,CAAT,YAAS,MAAA,KAAA,CAAA,CAAA,CAAA;;wCAEX,YAAyE,MAAA,WAAA,GAAA;OAAzD,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,OAAA,CAAA;OAAW,KAAI;;8BAAqB,CAAb,YAAa,MAAA,SAAA,CAAA,CAAA,CAAA;;;;;;QAd5CC,KAAAA,OAAO,SAAA;WAApB;uBACa,CAAtB,WAAsB,KAAA,QAAA,QAAA,CAAA,CAAA;;;;;;;;;IAkBjB,SAAO,cACH,CAAb,mBAAA,QAAA,GAEA,YASE,MAAA,WAAA,GATF,WACU,UAQR,OARiB;KAChB,UAAU,MAAA;KACV,qBAAiB;cACd;KAAJ,KAAI;KACJ,YAAA;KACC,OAAO,MAAA,GAAA,CAAG,CAAC,EAAC,cAAA;KACL;KACR,kBAAA;;;;;;;;;;;uBAKN,mBAEW,UAAA,EAAA,KAAA,EAAA,GAAA,CAAA,gBAAA,gBADN,QAAA,QAAQ,MAAA,SAAS,MAAA,kBAAA,CAAkB,GAAA,CAAA,CAAA,GAAA,EAAA"}
@@ -26,9 +26,9 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
26
26
  onChange?: ((selectedData?: Record<string, any> | undefined) => any) | undefined;
27
27
  "onUpdate:text"?: ((text?: string | undefined) => any) | undefined;
28
28
  }>, {
29
+ expandAll: boolean;
29
30
  labelKey: string;
30
31
  valueKey: string;
31
- expandAll: boolean;
32
32
  placeholder: string;
33
33
  clearable: boolean;
34
34
  filterable: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veltra/desktop",
3
- "version": "1.3.5",
3
+ "version": "1.3.6",
4
4
  "files": [
5
5
  "dist",
6
6
  "src"
@@ -57,11 +57,11 @@
57
57
  "@cat-kit/core": ">=1.1.8",
58
58
  "@cat-kit/excel": ">=1.0.0",
59
59
  "@cat-kit/fe": "^1.1.8",
60
- "@veltra/compositions": "1.3.5",
61
- "@veltra/directives": "1.3.5",
62
- "@veltra/icons": "1.3.5",
63
- "@veltra/styles": "1.3.5",
64
- "@veltra/utils": "1.3.5",
60
+ "@veltra/compositions": "1.3.6",
61
+ "@veltra/directives": "1.3.6",
62
+ "@veltra/icons": "1.3.6",
63
+ "@veltra/styles": "1.3.6",
64
+ "@veltra/utils": "1.3.6",
65
65
  "vue": ">=3.5.40"
66
66
  },
67
67
  "devDependencies": {
@@ -2,7 +2,13 @@
2
2
  <u-dropdown
3
3
  v-if="!readonly"
4
4
  v-bind="$attrs"
5
- :class="[cls.b, bem.is('disabled', disabled), bem.is('multiple', multiple), cls.m(size)]"
5
+ :class="[
6
+ cls.b,
7
+ bem.is('disabled', disabled),
8
+ bem.is('multiple', multiple),
9
+ cls.m(size),
10
+ bem.is('focus', multiple && dropdownVisible)
11
+ ]"
6
12
  :content-class="[cls.e('panel'), cls.em('panel', size)]"
7
13
  trigger="click"
8
14
  ref="dropdownRef"
@@ -10,7 +16,7 @@
10
16
  width="auto"
11
17
  @mouseenter="hovered = true"
12
18
  @mouseleave="hovered = false"
13
- @update:visible="!$event && (qs = '')"
19
+ @update:visible="handleDropdownVisible"
14
20
  >
15
21
  <template #trigger>
16
22
  <!-- 单选展示 -->
@@ -233,6 +239,13 @@ function handleClear() {
233
239
  // 过滤
234
240
  const qs = shallowRef<string>('')
235
241
 
242
+ const dropdownVisible = shallowRef(false)
243
+
244
+ const handleDropdownVisible = (visible: boolean) => {
245
+ dropdownVisible.value = visible
246
+ if (!visible) qs.value = ''
247
+ }
248
+
236
249
  watch([qs, forest], ([qs, forest]) => {
237
250
  const { filterable } = props
238
251
  if (!filterable || !qs) {
@@ -23,6 +23,11 @@ $menu-name: $root-name + '-panel-item';
23
23
  &:hover {
24
24
  border-color: fn.use-var(color, primary);
25
25
  }
26
+
27
+ @include m.is(focus) {
28
+ border-color: fn.use-var(color, primary);
29
+ box-shadow: fn.use-var(focus-ring);
30
+ }
26
31
  }
27
32
 
28
33
  @include m.size using ($size) {
@@ -10,6 +10,7 @@
10
10
  :disabled="disabled"
11
11
  @mouseenter.native="hovered = true"
12
12
  @mouseleave.native="hovered = false"
13
+ @update:visible="dropdownVisible = $event"
13
14
  >
14
15
  <template #trigger>
15
16
  <input
@@ -87,8 +88,15 @@ const emit = defineEmits<DateRangePickerEmits>()
87
88
 
88
89
  const cls = bem('date-range-picker')
89
90
 
91
+ const dropdownVisible = shallowRef(false)
92
+
90
93
  const className = computed(() => {
91
- return [cls.b, cls.m(size.value), bem.is('disabled', disabled.value)]
94
+ return [
95
+ cls.b,
96
+ cls.m(size.value),
97
+ bem.is('disabled', disabled.value),
98
+ bem.is('focus', dropdownVisible.value)
99
+ ]
92
100
  })
93
101
 
94
102
  const { formProps } = injectFormContext()
@@ -32,6 +32,11 @@ $root-name: date-range-picker;
32
32
  border-color: fn.use-var(color, primary);
33
33
  }
34
34
 
35
+ @include m.is(focus) {
36
+ border-color: fn.use-var(color, primary);
37
+ box-shadow: fn.use-var(focus-ring);
38
+ }
39
+
35
40
  @include m.e(input) {
36
41
  outline: none;
37
42
  border: none;
@@ -7,11 +7,11 @@
7
7
  >
8
8
  <u-tip v-if="tips" :content="tips" :class="cls.e('tips')" :show-delay="500">
9
9
  <span :class="cls.e('tip-label')">
10
- <slot name="label">{{ label }}:</slot>
10
+ <slot name="label">{{ label }}{{ labelPosition === 'top' ? '' : ':' }}</slot>
11
11
  </span>
12
12
  </u-tip>
13
13
  <template v-else>
14
- <slot name="label">{{ label }}:</slot>
14
+ <slot name="label">{{ label }}{{ labelPosition === 'top' ? '' : ':' }}</slot>
15
15
  </template>
16
16
  </label>
17
17
 
@@ -28,7 +28,7 @@ $root-name: form-item;
28
28
  color: fn.use-var(text-color, main);
29
29
  text-align: right;
30
30
  line-height: 1.3;
31
- font-weight: 300;
31
+ font-weight: 400;
32
32
 
33
33
  @include m.flex($justify: flex-end);
34
34
 
@@ -99,6 +99,7 @@ $root-name: form-item;
99
99
  padding-right: 0;
100
100
  padding-bottom: 4px;
101
101
  text-align: left;
102
+ color: fn.use-var(text-color, second);
102
103
  justify-content: flex-start;
103
104
  }
104
105
  }
@@ -26,6 +26,7 @@ $root-name: grid-input;
26
26
 
27
27
  @include m.is(focus) {
28
28
  border-color: fn.use-var(color, primary);
29
+ box-shadow: fn.use-var(focus-ring);
29
30
 
30
31
  @keyframes fade {
31
32
  0% {