@veltra/desktop 1.3.4 → 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 (75) hide show
  1. package/dist/components/action/action-group.vue.d.ts +2 -2
  2. package/dist/components/action/action.vue.d.ts +1 -1
  3. package/dist/components/auto-complete/auto-complete.vue.d.ts +2 -2
  4. package/dist/components/cascade/cascade.js +8 -2
  5. package/dist/components/cascade/cascade.js.map +1 -1
  6. package/dist/components/cascade/cascade.vue.d.ts +4 -4
  7. package/dist/components/cascade/style2.css +4 -0
  8. package/dist/components/checkbox/checkbox-button.vue.d.ts +1 -1
  9. package/dist/components/checkbox-group/checkbox-group.vue.d.ts +2 -2
  10. package/dist/components/code-editor/code-editor.vue.d.ts +2 -2
  11. package/dist/components/date-panel/date-panel.vue.d.ts +1 -1
  12. package/dist/components/date-picker/date-picker.vue.d.ts +2 -2
  13. package/dist/components/date-range-picker/date-range-picker.js +5 -2
  14. package/dist/components/date-range-picker/date-range-picker.js.map +1 -1
  15. package/dist/components/date-range-picker/date-range-picker.vue.d.ts +2 -2
  16. package/dist/components/date-range-picker/style2.css +4 -0
  17. package/dist/components/empty/empty.vue.d.ts +1 -1
  18. package/dist/components/form-item/form-item.js.map +1 -1
  19. package/dist/components/form-item/form-item.vue_vue_type_script_setup_true_lang.js +2 -2
  20. package/dist/components/form-item/form-item.vue_vue_type_script_setup_true_lang.js.map +1 -1
  21. package/dist/components/form-item/style2.css +2 -1
  22. package/dist/components/grid-input/style2.css +3 -0
  23. package/dist/components/input/input.vue.d.ts +4 -4
  24. package/dist/components/multi-select/multi-select.js +67 -40
  25. package/dist/components/multi-select/multi-select.js.map +1 -1
  26. package/dist/components/multi-select/multi-select.vue.d.ts +6 -6
  27. package/dist/components/multi-select/style2.css +23 -10
  28. package/dist/components/multi-tree-select/multi-tree-select.js +52 -35
  29. package/dist/components/multi-tree-select/multi-tree-select.js.map +1 -1
  30. package/dist/components/multi-tree-select/multi-tree-select.vue.d.ts +4 -4
  31. package/dist/components/multi-tree-select/style2.css +26 -16
  32. package/dist/components/number-input/number-input.vue.d.ts +4 -4
  33. package/dist/components/number-range-input/number-range-input.vue.d.ts +1 -1
  34. package/dist/components/password-input/password-input.vue.d.ts +1 -1
  35. package/dist/components/pop-confirm/pop-confirm.vue.d.ts +1 -1
  36. package/dist/components/radio-group/radio-group.vue.d.ts +2 -2
  37. package/dist/components/rich-text-editor/rich-text-editor.vue.d.ts +1 -1
  38. package/dist/components/select/select.js +159 -95
  39. package/dist/components/select/select.js.map +1 -1
  40. package/dist/components/select/select.vue.d.ts +2 -2
  41. package/dist/components/select/style2.css +4 -17
  42. package/dist/components/select/use-options.js +67 -26
  43. package/dist/components/select/use-options.js.map +1 -1
  44. package/dist/components/steps/steps.vue.d.ts +2 -2
  45. package/dist/components/textarea/style2.css +1 -0
  46. package/dist/components/textarea/textarea.vue.d.ts +5 -5
  47. package/dist/components/tip/tip.vue.d.ts +1 -1
  48. package/dist/components/tree/use-tree-nodes.js +14 -17
  49. package/dist/components/tree/use-tree-nodes.js.map +1 -1
  50. package/dist/components/tree-select/style2.css +6 -15
  51. package/dist/components/tree-select/tree-select.js +95 -41
  52. package/dist/components/tree-select/tree-select.js.map +1 -1
  53. package/dist/components/tree-select/tree-select.vue.d.ts +4 -4
  54. package/dist/types/tree.d.ts +4 -1
  55. package/package.json +6 -6
  56. package/src/components/cascade/cascade.vue +15 -2
  57. package/src/components/cascade/style.scss +5 -0
  58. package/src/components/date-range-picker/date-range-picker.vue +9 -1
  59. package/src/components/date-range-picker/style.scss +5 -0
  60. package/src/components/form-item/form-item.vue +2 -2
  61. package/src/components/form-item/style.scss +2 -1
  62. package/src/components/grid-input/style.scss +1 -0
  63. package/src/components/multi-select/multi-select.vue +50 -19
  64. package/src/components/multi-select/style.scss +27 -4
  65. package/src/components/multi-tree-select/multi-tree-select.vue +34 -14
  66. package/src/components/multi-tree-select/style.scss +28 -9
  67. package/src/components/select/__test__/select.test.ts +110 -0
  68. package/src/components/select/select.vue +130 -46
  69. package/src/components/select/style.scss +5 -14
  70. package/src/components/select/use-options.ts +83 -39
  71. package/src/components/textarea/style.scss +1 -0
  72. package/src/components/tree/use-tree-nodes.ts +19 -24
  73. package/src/components/tree-select/style.scss +4 -8
  74. package/src/components/tree-select/tree-select.vue +90 -17
  75. package/src/types/tree.ts +4 -1
@@ -30,8 +30,8 @@ $root-name: tree-select;
30
30
  background: none;
31
31
  }
32
32
 
33
- @include m.e(filter) {
34
- margin-bottom: 4px;
33
+ @include m.e(clear) {
34
+ cursor: pointer;
35
35
  }
36
36
 
37
37
  @include m.e(content-header) {
@@ -42,17 +42,13 @@ $root-name: tree-select;
42
42
  }
43
43
 
44
44
  @include m.e(content-tree) {
45
- max-height: 200px;
45
+ max-height: 240px;
46
46
  }
47
47
 
48
48
  @include m.e(panel) {
49
49
  @include m.size using ($size) {
50
- @include m.bem($root-name, content-filter) {
51
- padding: calc(fn.use-var(gap, $size) / 2) fn.use-var(gap, $size);
52
- }
53
-
54
50
  @include m.bem($root-name, content-tree) {
55
- padding: calc(fn.use-var(gap, $size) / 2) fn.use-var(gap, $size);
51
+ padding: fn.use-var(gap, $size);
56
52
  }
57
53
 
58
54
  @include m.bem($root-name, empty) {
@@ -7,38 +7,46 @@
7
7
  :content-class="[cls.e('panel'), cls.em('panel', size), contentClass]"
8
8
  :content-style="contentStyle"
9
9
  ref="dropdownRef"
10
+ v-model:visible="dropdownVisible"
10
11
  :min-width="minWidth"
11
12
  :width="width"
12
13
  :disabled="disabled"
13
14
  @update:visible="handleDropdownVisible"
15
+ @mouseenter="hovered = true"
16
+ @mouseleave="hovered = false"
14
17
  >
15
18
  <template #trigger>
16
19
  <u-input
20
+ ref="inputRef"
17
21
  :size="size"
18
22
  :disabled="disabled"
19
- :placeholder="placeholder"
20
- :clearable="clearable"
21
- :model-value="text ?? (model ? label : undefined)"
22
- @clear="handleClear"
23
- native-readonly
23
+ :placeholder="inputPlaceholder"
24
+ :clearable="false"
25
+ :model-value="inputValue"
26
+ @update:model-value="handleQueryInput"
27
+ :native-readonly="!filterable || !querying"
28
+ @click.capture="handleTriggerClickCapture"
24
29
  >
25
30
  <template #prefix v-if="$slots.prefix">
26
31
  <slot name="prefix" />
27
32
  </template>
28
33
  <template #suffix>
29
- <u-icon :class="cls.e('arrow')"><ArrowDown /></u-icon>
34
+ <transition name="zoom-in" mode="out-in">
35
+ <u-icon
36
+ v-if="showClear"
37
+ :class="cls.e('clear')"
38
+ title="清除"
39
+ key="clear"
40
+ @click.stop="handleClear"
41
+ >
42
+ <Close />
43
+ </u-icon>
44
+ <u-icon v-else :class="cls.e('arrow')" key="arrow"><ArrowDown /></u-icon>
45
+ </transition>
30
46
  </template>
31
47
  </u-input>
32
48
  </template>
33
49
  <template #content>
34
- <!-- 过滤器 -->
35
- <div v-if="filterable" :class="[cls.e('content-filter'), cls.m(size)]">
36
- <u-input placeholder="输入关键字进行过滤" v-model="qs">
37
- <template #suffix>
38
- <u-icon><Search /></u-icon>
39
- </template>
40
- </u-input>
41
- </div>
42
50
  <!-- 菜单列表 -->
43
51
 
44
52
  <u-tree
@@ -62,12 +70,12 @@
62
70
  <script lang="ts" setup>
63
71
  import { dfs, o } from '@cat-kit/core'
64
72
  import { useFormFallbackProps } from '@veltra/compositions'
65
- import { ArrowDown, Search } from '@veltra/icons/normal'
73
+ import { ArrowDown, Close } from '@veltra/icons/normal'
66
74
  import { bem, fieldKey, FORM_EMPTY_CONTENT } from '@veltra/utils'
67
75
  import { injectFormContext } from '@veltra/utils'
68
- import { computed, nextTick, shallowRef, watch } from 'vue'
76
+ import { computed, nextTick, shallowRef, useTemplateRef, watch } from 'vue'
69
77
 
70
- import type { TreeSelectProps, TreeSelectEmits, TreeExposed } from '../../types'
78
+ import type { TreeSelectProps, TreeSelectEmits, TreeExposed, InputExposed } from '../../types'
71
79
  import { UDropdown } from '../dropdown'
72
80
  import { UIcon } from '../icon'
73
81
  import { UInput } from '../input'
@@ -127,6 +135,68 @@ const model = defineModel<string | number>()
127
135
 
128
136
  const label = shallowRef<string>()
129
137
 
138
+ const dropdownVisible = shallowRef(false)
139
+
140
+ /**
141
+ * 是否处于查询态:决定触发输入框显示查询串还是选中标签。
142
+ * 与面板可见状态解耦 —— 选择后立即退出查询态,
143
+ * 不等面板关闭动画结束(否则显示值会延迟一个动画时长才恢复)。
144
+ */
145
+ const querying = shallowRef(false)
146
+
147
+ const inputRef = useTemplateRef<InputExposed>('inputRef')
148
+
149
+ /** 触发输入框的值:查询态下承载查询串,否则展示选中标签 */
150
+ const inputValue = computed(() => {
151
+ if (props.filterable && querying.value) return qs.value
152
+ return props.text ?? (model.value ? label.value : undefined)
153
+ })
154
+
155
+ /** 查询态下已选标签降级为占位提示 */
156
+ const inputPlaceholder = computed(() => {
157
+ const display = props.text ?? (model.value ? label.value : undefined)
158
+ if (props.filterable && querying.value && display) {
159
+ return display
160
+ }
161
+ return props.placeholder
162
+ })
163
+
164
+ function handleQueryInput(value: string) {
165
+ if (!props.filterable) return
166
+ qs.value = value
167
+ }
168
+
169
+ const hovered = shallowRef(false)
170
+
171
+ /** 悬停且存在选中值时展示清除按钮(替代下拉箭头) */
172
+ const showClear = computed(() => {
173
+ if (!props.clearable || disabled.value || !hovered.value) return false
174
+ return !!(props.text ?? (model.value ? label.value : undefined))
175
+ })
176
+
177
+ /**
178
+ * 过滤模式下拦截输入区域的点击:
179
+ * 阻止 dropdown 的 trigger 开合切换,保持面板展开以不中断输入。
180
+ * 非输入区域(箭头、留白)放行,维持原开合行为。
181
+ */
182
+ function handleTriggerClickCapture(e: MouseEvent) {
183
+ if (!props.filterable || disabled.value) return
184
+ if (!(e.target instanceof HTMLInputElement)) return
185
+
186
+ e.stopPropagation()
187
+ if (!dropdownVisible.value) dropdownRef.value?.open()
188
+ }
189
+
190
+ watch(dropdownVisible, (visible) => {
191
+ if (visible && props.filterable) {
192
+ // 面板展开后进入查询态并聚焦输入框,可以立即输入查询
193
+ querying.value = true
194
+ nextTick(() => inputRef.value?.el?.focus())
195
+ } else if (!visible) {
196
+ querying.value = false
197
+ }
198
+ })
199
+
130
200
  const { formProps } = injectFormContext()
131
201
 
132
202
  const { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props])
@@ -192,6 +262,9 @@ const handleSelect = (selected?: string | number, selectedData?: Record<string,
192
262
 
193
263
  emit('change', selectedData)
194
264
  emit('update:text', label.value)
265
+ // 立即退出查询态,输入框同步恢复显示选中标签
266
+ querying.value = false
267
+ qs.value = ''
195
268
  dropdownRef.value?.close()
196
269
  }
197
270
 
package/src/types/tree.ts CHANGED
@@ -38,7 +38,10 @@ export interface TreeProps {
38
38
  childrenKey?: string
39
39
  /** 数据 */
40
40
  data?: Record<string, any>[]
41
- /** 禁止单选或多选的节点 */
41
+ /**
42
+ * 禁止单选或多选的节点。
43
+ * 在整棵树构建完成后调用,可安全访问 `node.children` / `node.isLeaf`。
44
+ */
42
45
  disabledNode?: (item: Record<string, any>, node: TreeNode) => boolean
43
46
  /** 可多选 */
44
47
  checkable?: boolean