@veltra/desktop 1.0.7 → 1.0.9

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 (247) hide show
  1. package/dist/components/action/action-group.vue.d.ts +1 -1
  2. package/dist/components/action/action.vue.d.ts +3 -3
  3. package/dist/components/action/style.js +3 -0
  4. package/dist/components/auto-complete/auto-complete.vue.d.ts +2 -2
  5. package/dist/components/auto-complete/style.js +5 -0
  6. package/dist/components/batch-edit/style.js +9 -0
  7. package/dist/components/breadcrumb/style2.css +0 -6
  8. package/dist/components/button/style.js +1 -0
  9. package/dist/components/cascade/cascade.js +15 -13
  10. package/dist/components/cascade/cascade.js.map +1 -1
  11. package/dist/components/cascade/cascade.vue.d.ts +3 -3
  12. package/dist/components/cascade/node.js.map +1 -1
  13. package/dist/components/cascade/style.js +7 -0
  14. package/dist/components/cascade/use-check.js +3 -2
  15. package/dist/components/cascade/use-check.js.map +1 -1
  16. package/dist/components/cascade/use-select.js +3 -3
  17. package/dist/components/cascade/use-select.js.map +1 -1
  18. package/dist/components/checkbox/style.js +1 -0
  19. package/dist/components/checkbox/style2.css +0 -8
  20. package/dist/components/checkbox-group/checkbox-group.vue.d.ts +2 -2
  21. package/dist/components/checkbox-group/style.js +1 -0
  22. package/dist/components/context-menu/style.js +1 -0
  23. package/dist/components/date-panel/date-panel.vue.d.ts +1 -1
  24. package/dist/components/date-picker/date-picker.js +9 -9
  25. package/dist/components/date-picker/date-picker.js.map +1 -1
  26. package/dist/components/date-picker/date-picker.vue.d.ts +2 -2
  27. package/dist/components/date-picker/style.js +3 -0
  28. package/dist/components/date-range-picker/date-range-picker.js +9 -9
  29. package/dist/components/date-range-picker/date-range-picker.js.map +1 -1
  30. package/dist/components/date-range-picker/date-range-picker.vue.d.ts +2 -2
  31. package/dist/components/date-range-picker/style.js +3 -0
  32. package/dist/components/dialog/style.js +2 -0
  33. package/dist/components/drawer/style.js +1 -0
  34. package/dist/components/drawer/style2.css +4 -16
  35. package/dist/components/empty/style.js +1 -0
  36. package/dist/components/expression-editor/style.js +6 -0
  37. package/dist/components/file-picker/file-picker.vue.d.ts +1 -1
  38. package/dist/components/file-picker/helper.js +19 -7
  39. package/dist/components/file-picker/helper.js.map +1 -1
  40. package/dist/components/file-viewer/file-viewer.js +294 -0
  41. package/dist/components/file-viewer/file-viewer.js.map +1 -0
  42. package/dist/components/file-viewer/file-viewer.vue.d.ts +42 -0
  43. package/dist/components/file-viewer/helper.js +185 -0
  44. package/dist/components/file-viewer/helper.js.map +1 -0
  45. package/dist/components/file-viewer/index.d.ts +1 -0
  46. package/dist/components/file-viewer/previewers/docx-previewer.js +76 -0
  47. package/dist/components/file-viewer/previewers/docx-previewer.js.map +1 -0
  48. package/dist/components/file-viewer/previewers/image-previewer.js +64 -0
  49. package/dist/components/file-viewer/previewers/image-previewer.js.map +1 -0
  50. package/dist/components/file-viewer/previewers/pdf-previewer.js +90 -0
  51. package/dist/components/file-viewer/previewers/pdf-previewer.js.map +1 -0
  52. package/dist/components/file-viewer/previewers/sheet-previewer.js +175 -0
  53. package/dist/components/file-viewer/previewers/sheet-previewer.js.map +1 -0
  54. package/dist/components/file-viewer/previewers/text-previewer.js +74 -0
  55. package/dist/components/file-viewer/previewers/text-previewer.js.map +1 -0
  56. package/dist/components/file-viewer/previewers/video-previewer.js +62 -0
  57. package/dist/components/file-viewer/previewers/video-previewer.js.map +1 -0
  58. package/dist/components/file-viewer/style.d.ts +1 -0
  59. package/dist/components/file-viewer/style.js +4 -0
  60. package/dist/components/file-viewer/style2.css +445 -0
  61. package/dist/components/float-button/style.js +1 -0
  62. package/dist/components/form/style.js +2 -0
  63. package/dist/components/form-item/style.js +1 -0
  64. package/dist/components/form-item/style2.css +2 -3
  65. package/dist/components/grid-input/grid-input.vue.d.ts +1 -1
  66. package/dist/components/index.d.ts +12 -9
  67. package/dist/components/input/input.vue.d.ts +2 -2
  68. package/dist/components/input/style.js +1 -0
  69. package/dist/components/layout/style.js +1 -0
  70. package/dist/components/list/style.js +1 -0
  71. package/dist/components/loading/style2.css +16 -20
  72. package/dist/components/menu/style.js +2 -0
  73. package/dist/components/menu/style2.css +0 -78
  74. package/dist/components/multi-select/multi-select-option.js +14 -10
  75. package/dist/components/multi-select/multi-select-option.js.map +1 -1
  76. package/dist/components/multi-select/multi-select.js +16 -19
  77. package/dist/components/multi-select/multi-select.js.map +1 -1
  78. package/dist/components/multi-select/multi-select.vue.d.ts +3 -3
  79. package/dist/components/multi-select/style.js +7 -0
  80. package/dist/components/multi-tree-select/multi-tree-select.vue.d.ts +4 -4
  81. package/dist/components/multi-tree-select/style.js +7 -0
  82. package/dist/components/notification/notification.vue.d.ts +1 -1
  83. package/dist/components/number-input/number-input.vue.d.ts +2 -2
  84. package/dist/components/number-input/style.js +1 -0
  85. package/dist/components/number-range-input/number-range-input.vue.d.ts +2 -2
  86. package/dist/components/number-range-input/style.js +1 -0
  87. package/dist/components/paginator/style.js +3 -0
  88. package/dist/components/palette/di.js.map +1 -1
  89. package/dist/components/palette/palette-alpha.js +7 -10
  90. package/dist/components/palette/palette-alpha.js.map +1 -1
  91. package/dist/components/palette/palette-hue.js +5 -7
  92. package/dist/components/palette/palette-hue.js.map +1 -1
  93. package/dist/components/palette/palette-sv.js +8 -10
  94. package/dist/components/palette/palette-sv.js.map +1 -1
  95. package/dist/components/palette/palette.js +22 -24
  96. package/dist/components/palette/palette.js.map +1 -1
  97. package/dist/components/palette/style.js +3 -0
  98. package/dist/components/password-input/password-input.vue.d.ts +1 -1
  99. package/dist/components/password-input/style.js +2 -0
  100. package/dist/components/pop-confirm/pop-confirm.vue.d.ts +1 -1
  101. package/dist/components/pop-confirm/style.js +3 -0
  102. package/dist/components/progress-nodes/progress-nodes.vue.d.ts +2 -2
  103. package/dist/components/progress-nodes/style2.css +79 -33
  104. package/dist/components/radio/style2.css +0 -8
  105. package/dist/components/radio-group/radio-group.vue.d.ts +2 -2
  106. package/dist/components/radio-group/style.js +1 -0
  107. package/dist/components/rich-text-editor/rich-text-editor.vue.d.ts +2 -2
  108. package/dist/components/select/select.js +14 -12
  109. package/dist/components/select/select.js.map +1 -1
  110. package/dist/components/select/select.vue.d.ts +2 -2
  111. package/dist/components/select/style.js +5 -0
  112. package/dist/components/select/style2.css +0 -20
  113. package/dist/components/slider/slider-thumb.js +10 -13
  114. package/dist/components/slider/slider-thumb.js.map +1 -1
  115. package/dist/components/slider/slider.js +12 -15
  116. package/dist/components/slider/slider.js.map +1 -1
  117. package/dist/components/steps/style.js +2 -0
  118. package/dist/components/steps/style2.css +28 -35
  119. package/dist/components/switch/style2.css +0 -3
  120. package/dist/components/table/di.js.map +1 -1
  121. package/dist/components/table/node/row.d.ts +10 -1
  122. package/dist/components/table/node/row.js +9 -0
  123. package/dist/components/table/node/row.js.map +1 -1
  124. package/dist/components/table/style.js +7 -0
  125. package/dist/components/table/style2.css +0 -41
  126. package/dist/components/table/table-body.js +25 -26
  127. package/dist/components/table/table-body.js.map +1 -1
  128. package/dist/components/table/table-cell.js +16 -9
  129. package/dist/components/table/table-cell.js.map +1 -1
  130. package/dist/components/table/table-row.js +78 -19
  131. package/dist/components/table/table-row.js.map +1 -1
  132. package/dist/components/table/table.js +76 -34
  133. package/dist/components/table/table.js.map +1 -1
  134. package/dist/components/table/use-fixed-columns.js +27 -8
  135. package/dist/components/table/use-fixed-columns.js.map +1 -1
  136. package/dist/components/table/use-rows.js +2 -2
  137. package/dist/components/table/use-rows.js.map +1 -1
  138. package/dist/components/table/use-table.js +25 -3
  139. package/dist/components/table/use-table.js.map +1 -1
  140. package/dist/components/table-editor/style.js +2 -0
  141. package/dist/components/tabs/index.d.ts +3 -1
  142. package/dist/components/tabs/style.js +2 -0
  143. package/dist/components/tabs/style2.css +169 -107
  144. package/dist/components/tabs/tabs-horizontal.js +133 -0
  145. package/dist/components/tabs/tabs-horizontal.js.map +1 -0
  146. package/dist/components/tabs/tabs-horizontal.vue.d.ts +29 -0
  147. package/dist/components/tabs/tabs-vertical.js +89 -0
  148. package/dist/components/tabs/tabs-vertical.js.map +1 -0
  149. package/dist/components/tabs/tabs-vertical.vue.d.ts +28 -0
  150. package/dist/components/tabs/tabs.js +75 -105
  151. package/dist/components/tabs/tabs.js.map +1 -1
  152. package/dist/components/tabs/tabs.vue.d.ts +9 -23
  153. package/dist/components/tabs/use-tabs-bar.js +105 -0
  154. package/dist/components/tabs/use-tabs-bar.js.map +1 -0
  155. package/dist/components/tag/style2.css +0 -6
  156. package/dist/components/textarea/style.js +1 -0
  157. package/dist/components/textarea/textarea.vue.d.ts +2 -2
  158. package/dist/components/theme/style.js +5 -0
  159. package/dist/components/tip/tip.vue.d.ts +2 -2
  160. package/dist/components/tree/style.js +4 -0
  161. package/dist/components/tree/style2.css +45 -23
  162. package/dist/components/tree/tree-node.js +50 -35
  163. package/dist/components/tree/tree-node.js.map +1 -1
  164. package/dist/components/tree/tree.js +27 -20
  165. package/dist/components/tree/tree.js.map +1 -1
  166. package/dist/components/tree/tree.vue.d.ts +1 -1
  167. package/dist/components/tree/use-check.js +52 -14
  168. package/dist/components/tree/use-check.js.map +1 -1
  169. package/dist/components/tree/use-tree-nodes.js +51 -24
  170. package/dist/components/tree/use-tree-nodes.js.map +1 -1
  171. package/dist/components/tree-select/style.js +4 -0
  172. package/dist/components/tree-select/tree-select.vue.d.ts +3 -3
  173. package/dist/components/watermark/watermark.vue.d.ts +1 -1
  174. package/dist/index.d.ts +57 -53
  175. package/dist/index.js +51 -48
  176. package/dist/types/file-viewer.d.ts +71 -0
  177. package/dist/types/index.d.ts +4 -3
  178. package/dist/types/tabs.d.ts +106 -14
  179. package/dist/types/tree.d.ts +6 -1
  180. package/package.json +32 -31
  181. package/src/components/breadcrumb/style.scss +0 -6
  182. package/src/components/cascade/cascade.vue +18 -18
  183. package/src/components/cascade/node.ts +4 -1
  184. package/src/components/cascade/use-check.ts +5 -4
  185. package/src/components/cascade/use-select.ts +4 -5
  186. package/src/components/checkbox/style.scss +0 -4
  187. package/src/components/date-picker/date-picker.vue +10 -9
  188. package/src/components/date-range-picker/date-range-picker.vue +12 -12
  189. package/src/components/drawer/style.scss +18 -11
  190. package/src/components/file-picker/helper.ts +21 -10
  191. package/src/components/file-viewer/file-viewer.vue +311 -0
  192. package/src/components/file-viewer/helper.ts +193 -0
  193. package/src/components/file-viewer/index.ts +1 -0
  194. package/src/components/file-viewer/previewers/docx-previewer.vue +78 -0
  195. package/src/components/file-viewer/previewers/image-previewer.vue +64 -0
  196. package/src/components/file-viewer/previewers/pdf-previewer.vue +90 -0
  197. package/src/components/file-viewer/previewers/sheet-previewer.vue +210 -0
  198. package/src/components/file-viewer/previewers/text-previewer.vue +76 -0
  199. package/src/components/file-viewer/previewers/video-previewer.vue +72 -0
  200. package/src/components/file-viewer/style.scss +504 -0
  201. package/src/components/file-viewer/style.ts +4 -0
  202. package/src/components/form-item/style.scss +2 -3
  203. package/src/components/index.ts +2 -0
  204. package/src/components/loading/style.scss +125 -126
  205. package/src/components/menu/style.scss +0 -31
  206. package/src/components/multi-select/multi-select-option.vue +16 -3
  207. package/src/components/multi-select/multi-select.vue +17 -9
  208. package/src/components/palette/di.ts +5 -3
  209. package/src/components/palette/palette-alpha.vue +7 -10
  210. package/src/components/palette/palette-hue.vue +5 -7
  211. package/src/components/palette/palette-sv.vue +12 -14
  212. package/src/components/palette/palette.vue +19 -21
  213. package/src/components/progress-nodes/style.scss +28 -22
  214. package/src/components/radio/style.scss +0 -4
  215. package/src/components/select/select.vue +21 -19
  216. package/src/components/select/style.scss +0 -12
  217. package/src/components/slider/slider-thumb.vue +11 -14
  218. package/src/components/slider/slider.vue +15 -15
  219. package/src/components/steps/style.scss +10 -10
  220. package/src/components/switch/style.scss +0 -4
  221. package/src/components/table/di.ts +20 -3
  222. package/src/components/table/node/row.ts +10 -1
  223. package/src/components/table/style.scss +0 -26
  224. package/src/components/table/table-body.vue +28 -33
  225. package/src/components/table/table-cell.vue +17 -9
  226. package/src/components/table/table-row.tsx +83 -17
  227. package/src/components/table/table.vue +73 -45
  228. package/src/components/table/use-fixed-columns.ts +46 -12
  229. package/src/components/table/use-rows.ts +14 -3
  230. package/src/components/table/use-table.ts +27 -3
  231. package/src/components/tabs/index.ts +2 -0
  232. package/src/components/tabs/style.scss +217 -134
  233. package/src/components/tabs/tabs-horizontal.vue +125 -0
  234. package/src/components/tabs/tabs-vertical.vue +75 -0
  235. package/src/components/tabs/tabs.vue +56 -127
  236. package/src/components/tabs/use-tabs-bar.ts +119 -0
  237. package/src/components/tag/style.scss +0 -6
  238. package/src/components/tree/style.scss +74 -29
  239. package/src/components/tree/tree-node.vue +10 -4
  240. package/src/components/tree/tree.vue +39 -12
  241. package/src/components/tree/use-check.ts +79 -23
  242. package/src/components/tree/use-tree-nodes.ts +85 -34
  243. package/src/types/file-viewer.ts +69 -0
  244. package/src/types/index.ts +1 -0
  245. package/src/types/tabs.ts +113 -19
  246. package/src/types/tree.ts +6 -1
  247. package/dist/types/index.js +0 -0
@@ -24,7 +24,7 @@
24
24
  </template>
25
25
 
26
26
  <script lang="ts" setup>
27
- import { useFormComponent, useFormFallbackProps, useUpdateLock } from '@veltra/compositions'
27
+ import { useFormComponent, useFormFallbackProps, useUserAction } from '@veltra/compositions'
28
28
  import { bem } from '@veltra/utils'
29
29
  import { computed, provide, shallowRef, useTemplateRef, watch } from 'vue'
30
30
 
@@ -61,7 +61,7 @@ const { HSV, alpha, ...rest } = useHSV()
61
61
 
62
62
  const color = defineModel<string>()
63
63
  const RGB = computed(() => HSV2RGB(HSV))
64
- const updater = useUpdateLock()
64
+ const { userAction, isUserActive } = useUserAction()
65
65
 
66
66
  watch([alpha, RGB], ([alpha, RGB]) => {
67
67
  color.value = `#${RGB2HEX(RGB, alpha)}`
@@ -69,13 +69,11 @@ watch([alpha, RGB], ([alpha, RGB]) => {
69
69
 
70
70
  const visible = shallowRef(false)
71
71
 
72
- function handleClear() {
73
- updater.updateAndLock(() => {
74
- color.value = ''
75
- rest.updateAlpha(1)
76
- visible.value = false
77
- })
78
- }
72
+ const handleClear = userAction(() => {
73
+ color.value = ''
74
+ rest.updateAlpha(1)
75
+ visible.value = false
76
+ })
79
77
 
80
78
  const paletteSVRef = useTemplateRef('palette-sv')
81
79
  const paletteHueRef = useTemplateRef('palette-hue')
@@ -85,18 +83,17 @@ watch(
85
83
  color,
86
84
  (color) => {
87
85
  if (!color) return
86
+ if (isUserActive()) return
87
+
88
+ const { RGB, alpha } = HEX2RGBA(color)
89
+ const hsv = RGB2HSV(RGB)
90
+ rest.updateHue(hsv.h)
91
+ rest.updateSV({ s: hsv.s, v: hsv.v })
92
+ rest.updateAlpha(alpha)
88
93
 
89
- updater.update(() => {
90
- const { RGB, alpha } = HEX2RGBA(color)
91
- const hsv = RGB2HSV(RGB)
92
- rest.updateHue(hsv.h)
93
- rest.updateSV({ s: hsv.s, v: hsv.v })
94
- rest.updateAlpha(alpha)
95
-
96
- paletteSVRef.value?.init()
97
- paletteHueRef.value?.init()
98
- paletteAlphaRef.value?.init()
99
- })
94
+ paletteSVRef.value?.init()
95
+ paletteHueRef.value?.init()
96
+ paletteAlphaRef.value?.init()
100
97
  },
101
98
  { immediate: true }
102
99
  )
@@ -106,7 +103,8 @@ provide(PaletteDIKey, {
106
103
  HSV,
107
104
  RGB,
108
105
  alpha,
109
- updater,
106
+ userAction,
107
+ isUserActive,
110
108
  ...rest
111
109
  })
112
110
  </script>
@@ -5,13 +5,8 @@
5
5
  $root-name: progress-nodes;
6
6
 
7
7
  @include m.b($root-name) {
8
- // CSS 变量定义
9
- --checked-color: #{fn.use-var(color, primary)};
10
- --node-color: #{fn.use-var(text-color, placeholder)};
11
- --dot-size: 14px;
12
-
13
8
  position: relative;
14
- color: var(--node-color);
9
+ color: #{fn.use-var(text-color, placeholder)};
15
10
  overflow: auto;
16
11
  cursor: default;
17
12
 
@@ -28,13 +23,6 @@ $root-name: progress-nodes;
28
23
  cursor: grabbing;
29
24
  }
30
25
 
31
- // 颜色类型变体
32
- @each $type in vars.$color-types {
33
- @include m.m($type) {
34
- --checked-color: #{fn.use-var(color, $type)};
35
- }
36
- }
37
-
38
26
  // 列表容器
39
27
  @include m.e(list) {
40
28
  position: relative;
@@ -82,8 +70,8 @@ $root-name: progress-nodes;
82
70
  // 节点圆点
83
71
  @include m.e(dot) {
84
72
  position: relative;
85
- width: var(--dot-size);
86
- height: var(--dot-size);
73
+ width: 14px;
74
+ height: 14px;
87
75
  border: 2px solid currentColor;
88
76
  border-radius: 50%;
89
77
  background-color: fn.use-var(bg-color, top);
@@ -107,18 +95,36 @@ $root-name: progress-nodes;
107
95
  @include m.ellipsis;
108
96
  }
109
97
 
110
- // checked 状态 - 圆点填充 colorType 颜色
111
98
  @include m.bem($root-name, item) {
112
99
  @include m.is(checked) {
113
- color: var(--checked-color);
100
+ color: #{fn.use-var(color, primary)};
114
101
 
115
102
  @include m.bem($root-name, dot) {
116
- background-color: var(--checked-color);
117
- border-color: var(--checked-color);
103
+ background-color: #{fn.use-var(color, primary)};
104
+ border-color: #{fn.use-var(color, primary)};
118
105
  }
119
106
 
120
107
  @include m.bem($root-name, label) {
121
- color: var(--checked-color);
108
+ color: #{fn.use-var(color, primary)};
109
+ }
110
+ }
111
+ }
112
+
113
+ @each $type in vars.$color-types {
114
+ @include m.m($type) {
115
+ @include m.bem($root-name, item) {
116
+ @include m.is(checked) {
117
+ color: #{fn.use-var(color, $type)};
118
+
119
+ @include m.bem($root-name, dot) {
120
+ background-color: #{fn.use-var(color, $type)};
121
+ border-color: #{fn.use-var(color, $type)};
122
+ }
123
+
124
+ @include m.bem($root-name, label) {
125
+ color: #{fn.use-var(color, $type)};
126
+ }
127
+ }
122
128
  }
123
129
  }
124
130
  }
@@ -164,10 +170,10 @@ $root-name: progress-nodes;
164
170
 
165
171
  @include m.e(link) {
166
172
  // 宽度需要跨越当前 item 的右 padding + 下一个 item 的左 padding
167
- width: calc(100% - var(--dot-size) + 24px);
173
+ width: calc(100% - 14px + 24px);
168
174
  height: 0;
169
175
  border-width: 1px 0 0 0;
170
- left: calc(50% + var(--dot-size) / 2);
176
+ left: calc(50% + 14px / 2);
171
177
  top: 50%;
172
178
  transform: translateY(-50%);
173
179
  }
@@ -4,10 +4,6 @@
4
4
 
5
5
  $root-name: radio;
6
6
  @include m.b($root-name) {
7
- @include m.dark() {
8
- --u-radio-border: #595959;
9
- }
10
-
11
7
  cursor: pointer;
12
8
  vertical-align: middle;
13
9
  user-select: none;
@@ -50,7 +50,10 @@
50
50
  </u-input>
51
51
  </div>
52
52
 
53
- <!-- 单选列表 -->
53
+ <!--
54
+ 单选列表。虚拟化启用时,内容容器 height 由 useVirtualizer 命令式写入;
55
+ 此处 content-style 仅承担 grid 相关样式,避免 height 变化触发模板重渲染。
56
+ -->
54
57
  <u-scroll
55
58
  v-if="options.length"
56
59
  tag="ul"
@@ -62,7 +65,6 @@
62
65
  bem.is('grid', !!grid)
63
66
  ]"
64
67
  :content-style="{
65
- height: virtualEnabled ? withUnit(totalHeight, 'px') : undefined,
66
68
  gridTemplateColumns: grid ? `repeat(${grid.cols}, minmax(0px, 1fr))` : undefined,
67
69
  gridGap: grid ? withUnit(grid.gap, 'px') : undefined
68
70
  }"
@@ -76,7 +78,7 @@
76
78
  :key="key"
77
79
  :style="{ transform: `translateY(${offset}px)` }"
78
80
  :data-index="index"
79
- :ref="measureElement"
81
+ :ref="(el) => measureElement(index, el as Element | null)"
80
82
  >
81
83
  <slot v-bind="{ option, index }">
82
84
  {{ label }}
@@ -113,7 +115,7 @@
113
115
 
114
116
  <script lang="ts" setup>
115
117
  import { o } from '@cat-kit/core'
116
- import { useFormComponent, useFormFallbackProps, useVirtual } from '@veltra/compositions'
118
+ import { useFormComponent, useFormFallbackProps, useVirtualizer } from '@veltra/compositions'
117
119
  import { vFocus } from '@veltra/directives'
118
120
  import { ArrowDown, Search } from '@veltra/icons/normal'
119
121
  import { bem, FORM_EMPTY_CONTENT, scrollIntoContainerView, withUnit } from '@veltra/utils'
@@ -212,40 +214,40 @@ watch(
212
214
  { immediate: true }
213
215
  )
214
216
 
215
- const {
216
- virtualList,
217
- totalHeight,
218
- virtualEnabled: _virtualEnabled,
219
- scrollTo,
220
- measureElement
221
- } = useVirtual({
217
+ const baseVirtualEnabled = computed(() => options.value.length > 80)
218
+ const virtualEnabled = computed(() => baseVirtualEnabled.value && !props.grid)
219
+
220
+ const { virtualizer, items } = useVirtualizer({
222
221
  count: computed(() => options.value.length),
223
- virtualThreshold: 80,
224
- scrollEl: computed(() => scrollRef.value?.containerRef ?? null),
222
+ scrollEl: () => scrollRef.value?.containerRef ?? null,
223
+ contentEl: () => (virtualEnabled.value ? (scrollRef.value?.contentRef ?? null) : null),
225
224
  gap: 4,
226
225
  estimateSize: () => 40
227
226
  })
228
227
 
229
- const virtualEnabled = computed(() => {
230
- return _virtualEnabled.value && !props.grid
231
- })
232
-
233
228
  const virtualOptions = computed(() => {
234
229
  const _options = options.value
235
230
  const { labelKey, valueKey } = props
236
- return virtualList.value.map((item) => {
231
+ return items.value.map((item) => {
237
232
  const option = _options[item.index]!
238
233
  return {
239
234
  option,
240
235
  index: item.index,
241
236
  label: o(option).get(labelKey),
242
237
  val: o(option).get(valueKey),
243
- key: item.key,
238
+ key: item.index,
244
239
  offset: item.start
245
240
  }
246
241
  })
247
242
  })
248
243
 
244
+ const measureElement: (index: number, el: Element | null) => void = (index, el) =>
245
+ virtualizer.measureElement(index, el)
246
+
247
+ function scrollTo(index: number): void {
248
+ virtualizer.scrollToIndex(index, { align: 'center' })
249
+ }
250
+
249
251
  watch([scrollRef, virtualEnabled], ([scroll, virtualEnabled]) => {
250
252
  if (!scroll || !props.modelValue) return
251
253
 
@@ -3,18 +3,6 @@
3
3
 
4
4
  $root-name: select;
5
5
  @include m.b($root-name) {
6
- --u-menu-hover-bg: rgba(148, 163, 184, 0.12);
7
- --u-menu-hover-color: #{fn.use-var(text-color, title)};
8
- --u-menu-active-bg: rgba(59, 130, 246, 0.12);
9
- --u-menu-active-color: var(--u-color-primary-dark-1);
10
-
11
- @include m.dark() {
12
- --u-menu-hover-bg: rgba(148, 163, 184, 0.14);
13
- --u-menu-hover-color: #{fn.use-var(text-color, title)};
14
- --u-menu-active-bg: rgba(96, 165, 250, 0.2);
15
- --u-menu-active-color: #{fn.use-var(text-color, white)};
16
- }
17
-
18
6
  width: 100%;
19
7
 
20
8
  @include m.e(content-filter) {
@@ -2,7 +2,7 @@
2
2
  <div ref="thumb" :class="cls.e('thumb')" :style></div>
3
3
  </template>
4
4
  <script lang="ts" setup>
5
- import { useDrag, useUpdateLock } from '@veltra/compositions'
5
+ import { useDrag, useUserAction } from '@veltra/compositions'
6
6
  import { computed, inject, useTemplateRef, watch } from 'vue'
7
7
 
8
8
  import { sliderContextKey } from './di'
@@ -30,7 +30,7 @@ const style = computed(() => {
30
30
  }
31
31
  })
32
32
 
33
- const { updateAndLock, update } = useUpdateLock()
33
+ const { userAction, isUserActive } = useUserAction()
34
34
 
35
35
  function updateModel(offset: number) {
36
36
  offset = getOffsetByStep(offset)
@@ -41,19 +41,15 @@ function updateModel(offset: number) {
41
41
  const dragger = useDrag({
42
42
  target: computed(() => (disabled.value ? null : thumbRef.value)),
43
43
 
44
- onDrag({ offsetX, offsetY }) {
45
- updateAndLock(() => {
46
- updateModel(sliderProps.vertical ? offsetY : offsetX)
47
- })
48
- },
44
+ onDrag: userAction(({ offsetX, offsetY }) => {
45
+ updateModel(sliderProps.vertical ? offsetY : offsetX)
46
+ }),
49
47
  rangeX: range,
50
48
  rangeY: range,
51
- onDragEnd({ offsetX, offsetY }) {
52
- updateAndLock(() => {
53
- const offset = updateModel(sliderProps.vertical ? offsetY : offsetX)
54
- updateDragger(offset)
55
- })
56
- }
49
+ onDragEnd: userAction(({ offsetX, offsetY }) => {
50
+ const offset = updateModel(sliderProps.vertical ? offsetY : offsetX)
51
+ updateDragger(offset)
52
+ })
57
53
  })
58
54
 
59
55
  function updateDragger(offset: number) {
@@ -67,7 +63,8 @@ function updateDragger(offset: number) {
67
63
  watch(
68
64
  () => props.modelValue,
69
65
  (offset) => {
70
- update(() => updateDragger(offset))
66
+ if (isUserActive()) return
67
+ updateDragger(offset)
71
68
  }
72
69
  )
73
70
  </script>
@@ -20,7 +20,7 @@
20
20
  </template>
21
21
 
22
22
  <script lang="ts" setup generic="T extends number | [number, number]">
23
- import { useFormComponent, useFormFallbackProps, useUpdateLock } from '@veltra/compositions'
23
+ import { useFormComponent, useFormFallbackProps, useUserAction } from '@veltra/compositions'
24
24
  import { bem } from '@veltra/utils'
25
25
  import { computed, provide, watch } from 'vue'
26
26
 
@@ -87,21 +87,20 @@ const barStyles = computed(() => {
87
87
  }
88
88
  })
89
89
 
90
- const { updateAndLock, update } = useUpdateLock()
90
+ const { userAction, isUserActive } = useUserAction()
91
91
 
92
92
  watch(
93
93
  [sliderSize, ...['modelValue', 'range', 'max', 'min', 'vertical'].map((k) => () => props[k])],
94
94
  ([size, value, range]) => {
95
- update(() => {
96
- if (value === undefined || size === 0) return
97
-
98
- if (range) {
99
- offset1.value = value2SliderOffset((value as [number, number])[0])
100
- offset2.value = value2SliderOffset((value as [number, number])[1])
101
- } else {
102
- offset1.value = value2SliderOffset(value as number)
103
- }
104
- })
95
+ if (isUserActive()) return
96
+ if (value === undefined || size === 0) return
97
+
98
+ if (range) {
99
+ offset1.value = value2SliderOffset((value as [number, number])[0])
100
+ offset2.value = value2SliderOffset((value as [number, number])[1])
101
+ } else {
102
+ offset1.value = value2SliderOffset(value as number)
103
+ }
105
104
  },
106
105
  { immediate: true }
107
106
  )
@@ -115,15 +114,16 @@ const ticks = computed(() => {
115
114
  return [...Array.from({ length: tickLength }, (_, i) => i * offsetPercent), 100]
116
115
  })
117
116
 
118
- watch([offset1, offset2], (v) => {
119
- updateAndLock(() => {
117
+ watch(
118
+ [offset1, offset2],
119
+ userAction((v) => {
120
120
  if (props.range) {
121
121
  emit('update:modelValue', v.map(sliderOffset2Value).sort() as T)
122
122
  } else {
123
123
  emit('update:modelValue', sliderOffset2Value(v[0]) as T)
124
124
  }
125
125
  })
126
- })
126
+ )
127
127
 
128
128
  function handleClickSlider(e: MouseEvent) {
129
129
  if (disabled.value || props.range) return
@@ -10,13 +10,20 @@ $root-name: steps;
10
10
  padding: 0;
11
11
  margin: 0;
12
12
 
13
- /** 颜色变量 */
14
13
  @each $type in vars.$color-types {
15
14
  @include m.em(finished, $type) {
16
- --finished-color: #{fn.use-var(color, $type)};
15
+ @include m.e(item) {
16
+ @include m.is(finished) {
17
+ color: fn.use-var(color, $type);
18
+ }
19
+ }
17
20
  }
18
21
  @include m.em(current, $type) {
19
- --current-color: #{fn.use-var(color, $type)};
22
+ @include m.e(item) {
23
+ @include m.is(current) {
24
+ color: fn.use-var(color, $type);
25
+ }
26
+ }
20
27
  }
21
28
  }
22
29
 
@@ -24,13 +31,6 @@ $root-name: steps;
24
31
  @include m.e(item) {
25
32
  font-weight: 600;
26
33
  color: fn.use-var(text-color, placeholder);
27
-
28
- @include m.is(finished) {
29
- color: var(--finished-color);
30
- }
31
- @include m.is(current) {
32
- color: var(--current-color);
33
- }
34
34
  }
35
35
 
36
36
  @include m.e(node) {
@@ -4,10 +4,6 @@
4
4
 
5
5
  $root-name: switch;
6
6
  @include m.b($root-name) {
7
- --u-switch-height-small: 18px;
8
- --u-switch-height-default: 20px;
9
- --u-switch-height-large: 24px;
10
-
11
7
  display: inline-flex;
12
8
  align-items: center;
13
9
  cursor: pointer;
@@ -1,6 +1,6 @@
1
- import type { VirtualReturned } from '@veltra/compositions'
1
+ import type { VirtualItem } from '@veltra/compositions'
2
2
  import type { BEM } from '@veltra/utils'
3
- import type { InjectionKey, ShallowRef, Slots } from 'vue'
3
+ import type { ComputedRef, InjectionKey, ShallowRef, Slots } from 'vue'
4
4
 
5
5
  import type {
6
6
  TableProps,
@@ -53,7 +53,24 @@ export const TableDIKey: InjectionKey<
53
53
  row: TableRow,
54
54
  column: ColumnNode
55
55
  ) => TableColumnSlotsScope | TableColumnRenderContext
56
- } & VirtualReturned
56
+
57
+ /**
58
+ * 当前渲染窗口的虚拟项列表。
59
+ *
60
+ * 由 `useVirtualizer` 拆分出的 `items` shallowRef:仅在底层 `items`
61
+ * 引用变化时才更新,`isScrolling` / 纯尺寸变化不会导致此 ref 更新。
62
+ */
63
+ virtualList: ShallowRef<VirtualItem[]>
64
+ /** 是否启用虚拟列表 */
65
+ virtualEnabled: ComputedRef<boolean>
66
+ /**
67
+ * 测量行元素尺寸(参数顺序与底层 `Virtualizer.measureElement` 一致)。
68
+ *
69
+ * 元素卸载(`el === null`)时会从底层解绑,避免被移除的 `<tr>` 继续触发
70
+ * size=0 测量回调。
71
+ */
72
+ measureElement: (index: number, el: Element | null) => void
73
+ }
57
74
  > = Symbol('TableDIKey')
58
75
 
59
76
  export const TableResizeKey: InjectionKey<{
@@ -28,7 +28,16 @@ export class TableRowNode<Data extends Record<string, any> = Record<string, any>
28
28
  /** 是否选中 */
29
29
  checked = false
30
30
 
31
- uid: number | string
31
+ /**
32
+ * 行的稳定唯一标识。
33
+ *
34
+ * E2 不变式:`uid` 在单个 `TableRowNode` 实例的生命周期内不可变更。
35
+ * `useVirtualizer` 的 `getItemKey: i => rows[i].uid` 依赖该不变式来复用测量缓存;
36
+ * 若 uid 在运行时变更,虚拟列表的尺寸表会错配导致滚动抖动。
37
+ * 当前代码路径(`createRow` / `copy`)始终为每个新节点分配一次 uid,
38
+ * 所以该不变式天然成立;此处使用 `readonly` 做编译期锁定。
39
+ */
40
+ readonly uid: number | string
32
41
 
33
42
  override children?: TableRowNode<Data>[] = undefined
34
43
 
@@ -14,32 +14,6 @@ $root-name: table;
14
14
  }
15
15
 
16
16
  @include m.b($root-name) {
17
- --u-table-border-color: #e9e9e9;
18
- --u-table-header-bg: #f4f5f7;
19
- --u-table-header-color: #{fn.use-var(text-color, title)};
20
- --u-table-stripe-bg: #f8fafc;
21
- --u-table-stripe-color: inherit;
22
- --u-table-hover-bg: #{fn.use-var(bg-color, hover)};
23
- --u-table-hover-color: inherit;
24
- --u-table-current-bg: #{fn.use-var(bg-color, hover)};
25
- --u-table-current-color: inherit;
26
- --u-table-checked-bg: var(--u-color-primary-light-9);
27
- --u-table-checked-color: inherit;
28
-
29
- @include m.dark() {
30
- --u-table-border-color: #404040;
31
- --u-table-header-bg: #2a2a2a;
32
- --u-table-header-color: #{fn.use-var(text-color, main)};
33
- --u-table-stripe-bg: #2a2a2a;
34
- --u-table-stripe-color: #{fn.use-var(text-color, main)};
35
- --u-table-hover-bg: #333333;
36
- --u-table-hover-color: #{fn.use-var(text-color, title)};
37
- --u-table-current-bg: #{fn.use-var(bg-color, hover)};
38
- --u-table-current-color: inherit;
39
- --u-table-checked-bg: var(--u-color-primary-dark-1);
40
- --u-table-checked-color: inherit;
41
- }
42
-
43
17
  width: 100%;
44
18
  position: relative;
45
19
  border: 1px solid var(--u-table-border-color);
@@ -1,20 +1,15 @@
1
1
  <template>
2
- <tbody :class="cls.e('body')" ref="bodyRef">
2
+ <tbody :class="bodyCls">
3
3
  <template v-for="{ row, index, stripeIndex } of tableRows" :key="row.uid">
4
- <UExpandTableRow v-if="row.isExpandRow" :row="row" :data-index="index" />
5
- <UTableRow
6
- v-else
7
- :row="row"
8
- :data-index="index"
9
- :class="[bem.is('current', row.isCurrent), getStripeCls(stripeIndex)]"
10
- />
4
+ <UExpandTableRow v-if="row.isExpandRow" :row="row" :index="index" />
5
+ <UTableRow v-else :row="row" :index="index" :class="getStripeCls(stripeIndex)" />
11
6
  </template>
12
7
 
13
8
  <!-- 空 -->
14
- <tr v-if="!rows.length" :class="cls.e('row')">
9
+ <tr v-if="!rows.length" :class="emptyRowCls">
15
10
  <td :colspan="leafColumns.length">
16
11
  <slot name="empty">
17
- <UEmpty :class="cls.e('empty')" />
12
+ <UEmpty :class="emptyCls" />
18
13
  </slot>
19
14
  </td>
20
15
  </tr>
@@ -24,8 +19,8 @@
24
19
  </template>
25
20
 
26
21
  <script lang="ts" setup>
27
- import { bem, setStyles } from '@veltra/utils'
28
- import { computed, inject, shallowRef, watch } from 'vue'
22
+ import { bem } from '@veltra/utils'
23
+ import { computed, inject } from 'vue'
29
24
 
30
25
  import { UEmpty } from '../empty'
31
26
  import { TableDIKey } from './di'
@@ -38,9 +33,26 @@ defineOptions({
38
33
  const { cls, rows, virtualList, columnConfig, tableProps, virtualEnabled } = inject(TableDIKey)!
39
34
  const { leafColumns } = columnConfig
40
35
 
41
- const getStripeCls = computed(() => {
42
- return tableProps.stripe ? (index: number) => bem.is('stripe', index % 2 === 1) : () => ''
43
- })
36
+ // A1 的同族优化:把 body / empty / empty-row 等静态 class 一次性取出,
37
+ // 避免每次 render 触发 `cls.e` 的字符串拼接。
38
+ const bodyCls = cls.e('body')
39
+ const emptyRowCls = cls.e('row')
40
+ const emptyCls = cls.e('empty')
41
+
42
+ /**
43
+ * C1:stripe class 查找表。
44
+ *
45
+ * `bem.is('stripe', true) === 'is-stripe'`,`bem.is('stripe', false) === ''`。
46
+ * 两种输出是全局常量,无需每次调用 `bem.is`;按奇偶直接查表即可。
47
+ * 非 stripe 模式下两个位置均返回空串。
48
+ */
49
+ const STRIPE_CLS_ON: readonly [string, string] = [bem.is('stripe', false), bem.is('stripe', true)]
50
+ const STRIPE_CLS_OFF: readonly [string, string] = ['', '']
51
+
52
+ const stripeTable = computed<readonly [string, string]>(() =>
53
+ tableProps.stripe ? STRIPE_CLS_ON : STRIPE_CLS_OFF
54
+ )
55
+ const getStripeCls = (index: number): string => stripeTable.value[index & 1]!
44
56
 
45
57
  const tableRows = computed(() => {
46
58
  if (!virtualEnabled.value) {
@@ -53,7 +65,7 @@ const tableRows = computed(() => {
53
65
  })
54
66
  }
55
67
 
56
- // 虚拟列表
68
+ // 虚拟列表:仅渲染可视窗口内的行,位置由 table.vue 中的 before/after 占位 tbody 撑开
57
69
  return virtualList.value.map((item) => {
58
70
  return {
59
71
  row: rows.value[item.index]!,
@@ -62,21 +74,4 @@ const tableRows = computed(() => {
62
74
  }
63
75
  })
64
76
  })
65
-
66
- const bodyRef = shallowRef<HTMLElement>()
67
-
68
- function setBodyTransform(transformY: number) {
69
- bodyRef.value &&
70
- setStyles(bodyRef.value, {
71
- transform: `translate3d(0, ${transformY}px, 0)`
72
- })
73
- }
74
-
75
- watch(virtualList, (list) => {
76
- setBodyTransform(list[0]?.start ?? 0)
77
- })
78
-
79
- defineExpose({
80
- setBodyTransform
81
- })
82
77
  </script>