@veltra/desktop 1.7.19 → 1.8.1

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 (114) hide show
  1. package/dist/components/batch-edit/batch-edit-form.js +40 -26
  2. package/dist/components/batch-edit/batch-edit-form.js.map +1 -1
  3. package/dist/components/batch-edit/use-handlers.js +3 -3
  4. package/dist/components/batch-edit/use-handlers.js.map +1 -1
  5. package/dist/components/batch-edit/use-shortcut-key.js +4 -2
  6. package/dist/components/batch-edit/use-shortcut-key.js.map +1 -1
  7. package/dist/components/card/style2.css +0 -2
  8. package/dist/components/condition-editor/condition-editor.js +8 -2
  9. package/dist/components/condition-editor/condition-editor.js.map +1 -1
  10. package/dist/components/dropdown/dropdown.js +5 -3
  11. package/dist/components/dropdown/dropdown.js.map +1 -1
  12. package/dist/components/expression-editor/components/path-preview.js +3 -6
  13. package/dist/components/expression-editor/components/path-preview.js.map +1 -1
  14. package/dist/components/expression-editor/components/variable-picker.js +49 -12
  15. package/dist/components/expression-editor/components/variable-picker.js.map +1 -1
  16. package/dist/components/expression-editor/core/editor.js +42 -0
  17. package/dist/components/expression-editor/core/editor.js.map +1 -1
  18. package/dist/components/expression-editor/expression-editor.js +68 -22
  19. package/dist/components/expression-editor/expression-editor.js.map +1 -1
  20. package/dist/components/expression-editor/style2.css +135 -73
  21. package/dist/components/form/form.js.map +1 -1
  22. package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js +0 -1
  23. package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js.map +1 -1
  24. package/dist/components/form/style2.css +8 -3
  25. package/dist/components/form-item/style2.css +14 -0
  26. package/dist/components/index.d.ts +27 -26
  27. package/dist/components/index.js +54 -52
  28. package/dist/components/index.js.map +1 -1
  29. package/dist/components/kanban/di.js +7 -0
  30. package/dist/components/kanban/di.js.map +1 -0
  31. package/dist/components/kanban/kanban-column.js +67 -0
  32. package/dist/components/kanban/kanban-column.js.map +1 -0
  33. package/dist/components/kanban/kanban.js +89 -0
  34. package/dist/components/kanban/kanban.js.map +1 -0
  35. package/dist/components/kanban/style.d.ts +1 -0
  36. package/dist/components/kanban/style.js +1 -0
  37. package/dist/components/kanban/style2.css +128 -0
  38. package/dist/components/multi-select/multi-select.js +16 -12
  39. package/dist/components/multi-select/multi-select.js.map +1 -1
  40. package/dist/components/multi-select/style2.css +7 -0
  41. package/dist/components/multi-tree-select/multi-tree-select.js +82 -56
  42. package/dist/components/multi-tree-select/multi-tree-select.js.map +1 -1
  43. package/dist/components/multi-tree-select/style2.css +7 -0
  44. package/dist/components/rich-text-editor/image-node.js +154 -0
  45. package/dist/components/rich-text-editor/image-node.js.map +1 -0
  46. package/dist/components/rich-text-editor/rich-text-editor.js +80 -22
  47. package/dist/components/rich-text-editor/rich-text-editor.js.map +1 -1
  48. package/dist/components/rich-text-editor/style2.css +6 -0
  49. package/dist/components/rich-text-editor/toolbar.js +22 -2
  50. package/dist/components/rich-text-editor/toolbar.js.map +1 -1
  51. package/dist/components/select/select.js +7 -3
  52. package/dist/components/select/select.js.map +1 -1
  53. package/dist/components/select/style2.css +7 -0
  54. package/dist/components/select/use-options.js +14 -3
  55. package/dist/components/select/use-options.js.map +1 -1
  56. package/dist/components/tree-select/style2.css +7 -0
  57. package/dist/components/tree-select/tree-select.js +49 -17
  58. package/dist/components/tree-select/tree-select.js.map +1 -1
  59. package/dist/index.d.ts +48 -46
  60. package/dist/index.js +47 -46
  61. package/dist/types/dropdown.d.ts +10 -0
  62. package/dist/types/index.d.ts +3 -2
  63. package/dist/types/kanban.d.ts +69 -0
  64. package/dist/types/multi-tree-select.d.ts +7 -1
  65. package/dist/types/rich-text-editor.d.ts +13 -2
  66. package/dist/types/tree-select.d.ts +7 -1
  67. package/package.json +1 -1
  68. package/src/components/batch-edit/__test__/batch-edit.test.ts +112 -1
  69. package/src/components/batch-edit/batch-edit-form.vue +21 -2
  70. package/src/components/batch-edit/use-handlers.ts +6 -5
  71. package/src/components/batch-edit/use-shortcut-key.ts +5 -2
  72. package/src/components/card/style.scss +0 -2
  73. package/src/components/condition-editor/__test__/condition-editor.test.ts +61 -0
  74. package/src/components/condition-editor/condition-editor.vue +6 -1
  75. package/src/components/dropdown/dropdown.vue +9 -4
  76. package/src/components/expression-editor/__test__/editor.test.ts +66 -0
  77. package/src/components/expression-editor/__test__/expression-editor.test.ts +124 -0
  78. package/src/components/expression-editor/components/path-preview.vue +1 -2
  79. package/src/components/expression-editor/components/variable-picker.vue +54 -13
  80. package/src/components/expression-editor/core/editor.ts +61 -0
  81. package/src/components/expression-editor/expression-editor.vue +58 -20
  82. package/src/components/expression-editor/style.scss +160 -76
  83. package/src/components/form/form.vue +0 -1
  84. package/src/components/form/style.scss +11 -4
  85. package/src/components/form-item/style.scss +16 -1
  86. package/src/components/index.ts +2 -0
  87. package/src/components/kanban/__test__/kanban.test.ts +212 -0
  88. package/src/components/kanban/di.ts +19 -0
  89. package/src/components/kanban/index.ts +1 -0
  90. package/src/components/kanban/kanban-column.vue +77 -0
  91. package/src/components/kanban/kanban.vue +81 -0
  92. package/src/components/kanban/style.scss +124 -0
  93. package/src/components/kanban/style.ts +1 -0
  94. package/src/components/multi-select/multi-select.vue +11 -2
  95. package/src/components/multi-select/style.scss +6 -0
  96. package/src/components/multi-tree-select/multi-tree-select.vue +58 -9
  97. package/src/components/multi-tree-select/style.scss +6 -0
  98. package/src/components/rich-text-editor/image-node.ts +193 -0
  99. package/src/components/rich-text-editor/rich-text-editor.vue +131 -29
  100. package/src/components/rich-text-editor/style.scss +7 -0
  101. package/src/components/rich-text-editor/toolbar.vue +21 -1
  102. package/src/components/select/__test__/select.test.ts +78 -0
  103. package/src/components/select/select.vue +13 -3
  104. package/src/components/select/style.scss +6 -0
  105. package/src/components/select/use-options.ts +25 -4
  106. package/src/components/tree-select/__test__/tree-select.test.ts +116 -0
  107. package/src/components/tree-select/style.scss +6 -0
  108. package/src/components/tree-select/tree-select.vue +63 -13
  109. package/src/types/dropdown.ts +10 -0
  110. package/src/types/index.ts +1 -0
  111. package/src/types/kanban.ts +63 -0
  112. package/src/types/multi-tree-select.ts +12 -1
  113. package/src/types/rich-text-editor.ts +14 -1
  114. package/src/types/tree-select.ts +12 -1
@@ -1,17 +1,27 @@
1
1
  <template>
2
- <div :class="className">
3
- <div
4
- ref="container"
5
- :class="cls.e('container')"
6
- :contenteditable="!readonly && !disabled"
7
- :data-empty="isEmpty || undefined"
8
- :data-placeholder="props.placeholder"
9
- @keydown="onKeydown"
10
- @blur="onBlur"
11
- ></div>
12
-
13
- <div v-if="showPlaceholder" :class="cls.e('placeholder')">
14
- {{ props.placeholder }}
2
+ <div ref="rootEl" :class="cls.b">
3
+ <!-- 提示行独立在边框盒(shell)之外 -->
4
+ <div v-if="showHint" :class="cls.e('hint')">输入 <kbd>@</kbd> 唤起变量面板</div>
5
+
6
+ <div :class="shellClass">
7
+ <div :class="cls.e('body')">
8
+ <div
9
+ ref="container"
10
+ :class="cls.e('container')"
11
+ :contenteditable="!readonly && !disabled"
12
+ :data-empty="visualEmpty || undefined"
13
+ :data-placeholder="props.placeholder"
14
+ @keydown="onKeydown"
15
+ @blur="onBlur"
16
+ ></div>
17
+
18
+ <div v-if="showPlaceholder" :class="cls.e('placeholder')">
19
+ {{ props.placeholder }}
20
+ </div>
21
+ </div>
22
+
23
+ <!-- mention 面板的定位锚点:跟随 `@` 字符位置(见 positionMentionAnchor) -->
24
+ <span ref="mentionAnchor" :class="cls.e('mention-anchor')" aria-hidden="true"></span>
15
25
  </div>
16
26
 
17
27
  <VariablePicker
@@ -53,7 +63,10 @@ defineOptions({ name: 'UExpressionEditor' })
53
63
 
54
64
  const props = withDefaults(defineProps<ExpressionEditorProps>(), {
55
65
  placeholder: '请输入表达式,输入 @ 可插入变量',
56
- selectableLevels: 'leaf'
66
+ selectableLevels: 'leaf',
67
+ // Boolean prop 缺省会被 Vue 归一成 false,挡住 UForm 下发的 disabled / readonly,须显式留 undefined
68
+ disabled: undefined,
69
+ readonly: undefined
57
70
  })
58
71
 
59
72
  const emit = defineEmits<{ (e: 'update:modelValue', value: string): void }>()
@@ -63,11 +76,14 @@ const { formProps } = injectFormContext()
63
76
  const { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props])
64
77
 
65
78
  const containerRef = useTemplateRef<HTMLDivElement>('container')
79
+ const rootElRef = useTemplateRef<HTMLDivElement>('rootEl')
80
+ const mentionAnchorRef = useTemplateRef<HTMLSpanElement>('mentionAnchor')
66
81
  const pickerRef = useTemplateRef<{ handleKeydown: (e: KeyboardEvent) => boolean }>('pickerRef')
67
82
 
68
- const className = computed(() => [
69
- cls.b,
70
- cls.m(size.value),
83
+ /** 视觉盒(边框 / 背景 / 聚焦光晕 / 尺寸态)挂在 shell 上,根节点只做布局 */
84
+ const shellClass = computed(() => [
85
+ cls.e('shell'),
86
+ cls.em('shell', size.value),
71
87
  bem.is('disabled', disabled.value),
72
88
  bem.is('readonly', readonly.value)
73
89
  ])
@@ -78,8 +94,11 @@ const editorRef = shallowRef<EditorAPI | null>(null)
78
94
  const mention: MentionAPI = createMention()
79
95
 
80
96
  const currentDoc = shallowRef<Doc>([])
81
- const isEmpty = computed(() => currentDoc.value.length === 0)
82
- const showPlaceholder = computed(() => isEmpty.value && !disabled.value)
97
+ /** 框内视觉空态:与 IME 合成状态无关,由 editor 在 DOM 变化时上报 */
98
+ const visualEmpty = shallowRef(true)
99
+ const showPlaceholder = computed(() => visualEmpty.value && !disabled.value)
100
+ /** 上方 `@` 使用提示常驻:只跟可编辑状态走,不随内容增减隐藏 */
101
+ const showHint = computed(() => !disabled.value && !readonly.value)
83
102
 
84
103
  const pickerMode = shallowRef<'mention' | 'reselect' | null>(null)
85
104
  const pickerTriggerDom = shallowRef<HTMLElement | undefined>(undefined)
@@ -88,6 +107,18 @@ const pickerFilter = shallowRef('')
88
107
 
89
108
  const pickerVisible = computed(() => pickerMode.value !== null)
90
109
 
110
+ /** 把 mention 锚点移到 `@` 字符下方,面板据此定位 */
111
+ function positionMentionAnchor(anchorOffset: number) {
112
+ const rootEl = rootElRef.value
113
+ const anchor = mentionAnchorRef.value
114
+ const rect = editorRef.value?.getRectAtOffset(anchorOffset)
115
+ if (!rootEl || !anchor || !rect) return
116
+ // absolute 定位以 padding box 为基准,需扣除根节点边框宽度
117
+ const rootRect = rootEl.getBoundingClientRect()
118
+ anchor.style.left = `${rect.left - rootRect.left - rootEl.clientLeft}px`
119
+ anchor.style.top = `${rect.bottom - rootRect.top - rootEl.clientTop}px`
120
+ }
121
+
91
122
  function syncMention() {
92
123
  const editor = editorRef.value
93
124
  if (!editor) return
@@ -97,7 +128,8 @@ function syncMention() {
97
128
  if (state) {
98
129
  pickerMode.value = 'mention'
99
130
  pickerFilter.value = state.filter
100
- pickerTriggerDom.value = containerRef.value ?? undefined
131
+ positionMentionAnchor(state.anchorOffset)
132
+ pickerTriggerDom.value = mentionAnchorRef.value ?? containerRef.value ?? undefined
101
133
  } else if (pickerMode.value === 'mention') {
102
134
  closePicker()
103
135
  }
@@ -125,6 +157,9 @@ onMounted(() => {
125
157
  if (value !== (props.modelValue ?? '')) emit('update:modelValue', value)
126
158
  syncMention()
127
159
  },
160
+ onVisualEmptyChange: (empty) => {
161
+ visualEmpty.value = empty
162
+ },
128
163
  onSelectionChange: () => {
129
164
  syncMention()
130
165
  },
@@ -135,6 +170,9 @@ onMounted(() => {
135
170
  pickerFilter.value = ''
136
171
  pickerTriggerDom.value = chipEl
137
172
  reselectingSegIdx.value = segIndex
173
+ // chip 的 mousedown 被 preventDefault,编辑器没有焦点时点击 chip 焦点不会转移,
174
+ // 键盘导航依赖 container 的 keydown,这里主动把焦点拉回编辑器
175
+ containerRef.value?.focus()
138
176
  }
139
177
  })
140
178
  editorRef.value = editor
@@ -5,48 +5,70 @@
5
5
  $root-name: expression-editor;
6
6
 
7
7
  @include m.b($root-name) {
8
+ // 根节点只做布局(提示行在视觉盒之外),视觉盒由 __shell 承担
8
9
  position: relative;
9
- background-color: fn.use-var(bg-color, top);
10
- border-width: fn.use-var(border, width);
11
- border-style: fn.use-var(border, style);
12
- border-color: fn.use-var(border, muted-color);
13
- border-radius: fn.use-var(radius, default);
14
10
  width: 100%;
15
11
 
16
- @include m.is-not(disabled, readonly) {
12
+ @include m.e(shell) {
13
+ background-color: fn.use-var(bg-color, top);
14
+ border-width: fn.use-var(border, width);
15
+ border-style: fn.use-var(border, style);
16
+ border-color: fn.use-var(border, muted-color);
17
+ border-radius: fn.use-var(radius, default);
18
+ transition:
19
+ border-color fn.use-var(transition, fast) fn.use-var(transition, ease),
20
+ box-shadow fn.use-var(transition, fast) fn.use-var(transition, ease);
21
+
22
+ // 状态描边压在 0,3,0 以内(与 u-input 同档),表单项错误态才能用普通后代选择器直接压住
17
23
  &:hover {
18
24
  border-color: fn.use-var(color, primary);
19
25
  }
20
26
 
21
27
  &:focus-within {
22
28
  border-color: fn.use-var(color, primary);
29
+ box-shadow: fn.use-var(focus-ring);
23
30
  outline: none;
24
31
  }
25
- }
26
32
 
27
- @include m.is('disabled') {
28
- background-color: fn.use-var(color, disabled);
29
- cursor: not-allowed;
30
- border-color: fn.use-var(border, muted-color);
33
+ @include m.is('disabled') {
34
+ background-color: fn.use-var(color, disabled);
35
+ cursor: not-allowed;
36
+ border-color: fn.use-var(border, muted-color);
31
37
 
32
- &:hover {
38
+ &:hover {
39
+ border-color: fn.use-var(border, muted-color);
40
+ }
41
+ }
42
+
43
+ @include m.is('readonly') {
44
+ background-color: fn.use-var(bg-color, middle);
45
+ cursor: default;
33
46
  border-color: fn.use-var(border, muted-color);
47
+ user-select: text;
48
+
49
+ &:hover {
50
+ border-color: fn.use-var(border, muted-color);
51
+ }
34
52
  }
35
- }
36
53
 
37
- @include m.is('readonly') {
38
- background-color: fn.use-var(bg-color, middle);
39
- cursor: default;
40
- border-color: fn.use-var(border, muted-color);
41
- user-select: text;
54
+ @include m.size using ($size) {
55
+ min-height: fn.use-var(form-component-height, $size);
56
+ padding: fn.use-var(gap, $size);
42
57
 
43
- &:hover {
44
- border-color: fn.use-var(border, muted-color);
58
+ @include m.bem($root-name, placeholder) {
59
+ font-size: fn.use-var(font-size-main, $size);
60
+ }
61
+
62
+ @include m.bem($root-name, container) {
63
+ font-size: fn.use-var(font-size-main, $size);
64
+ }
45
65
  }
46
66
  }
47
67
 
48
68
  @include m.e(placeholder) {
49
69
  position: absolute;
70
+ top: 0;
71
+ left: 0;
50
72
  color: fn.use-var(text-color, placeholder);
51
73
  pointer-events: none;
52
74
  user-select: none;
@@ -54,6 +76,43 @@ $root-name: expression-editor;
54
76
  font-weight: 400;
55
77
  }
56
78
 
79
+ // 提示 + 输入区的定位层:placeholder 相对它对齐,hint 出现时不至于错位
80
+ @include m.e(body) {
81
+ position: relative;
82
+ }
83
+
84
+ // 编辑器上方的 `@` 使用提示(空内容时显示),位于边框盒之外
85
+ @include m.e(hint) {
86
+ font-size: fn.use-var(font-size-main, small);
87
+ color: fn.use-var(text-color, placeholder);
88
+ user-select: none;
89
+ margin-bottom: 4px;
90
+ }
91
+
92
+ // mention 面板定位锚点:跟随 `@` 字符,零尺寸不参与绘制
93
+ @include m.e(mention-anchor) {
94
+ position: absolute;
95
+ width: 0;
96
+ height: 0;
97
+ pointer-events: none;
98
+ }
99
+
100
+ // 键位提示(编辑器 hint 与面板 footer 共用)
101
+ @include m.e(hint, picker-hint) {
102
+ kbd {
103
+ display: inline-block;
104
+ min-width: 18px;
105
+ padding: 1px 4px;
106
+ border: fn.use-var(border);
107
+ border-radius: fn.use-var(radius, small);
108
+ font-size: 11px;
109
+ line-height: 1.4;
110
+ text-align: center;
111
+ color: fn.use-var(text-color, second);
112
+ background-color: fn.use-var(bg-color, top);
113
+ }
114
+ }
115
+
57
116
  @include m.e(container) {
58
117
  position: relative;
59
118
  outline: none;
@@ -117,70 +176,92 @@ $root-name: expression-editor;
117
176
  }
118
177
 
119
178
  // ─── 变量选择面板 ──────────────────────────────────────────
179
+ // 面板以 tip 为浮层载体,但按库内标准下拉面板形态渲染:
180
+ // 负 margin 抵消 tip 内容自带的 gap 内边距,由 picker 自绘边框卡片
120
181
  @include m.e(picker) {
121
- min-width: 220px;
182
+ margin: calc(#{fn.use-var(gap, default)} * -1);
183
+ min-width: 240px;
184
+ display: flex;
185
+ flex-direction: column;
186
+ overflow: hidden;
122
187
  background-color: fn.use-var(bg-color, top);
188
+ border: fn.use-var(border);
189
+ border-radius: fn.use-var(radius, default);
190
+ backdrop-filter: fn.use-var(bg-filter);
191
+ -webkit-backdrop-filter: fn.use-var(bg-filter);
123
192
  }
124
193
 
125
194
  @include m.e(picker-body) {
195
+ flex: 1 1 auto;
196
+ min-height: 0;
126
197
  display: flex;
127
198
  align-items: stretch;
128
- min-height: 200px;
129
199
  }
130
200
 
131
201
  @include m.e(panel) {
132
202
  flex: 1 1 auto;
133
203
  min-width: 0;
134
204
  max-height: 320px;
205
+ display: flex;
206
+ flex-direction: column;
135
207
  }
136
208
 
137
209
  @include m.e(panel-list) {
138
- height: 100%;
139
- min-height: 200px;
210
+ flex: 1 1 auto;
211
+ min-height: 0;
140
212
  }
141
213
 
142
214
  @include m.e(panel-content) {
143
- padding: 4px 0;
215
+ padding: 4px;
144
216
  }
145
217
 
146
218
  @include m.e(item) {
147
- padding: 6px 12px;
148
- cursor: pointer;
149
- user-select: none;
150
219
  display: flex;
151
220
  align-items: center;
152
221
  justify-content: space-between;
153
- gap: 8px;
154
- transition:
155
- background-color 0.12s ease,
156
- color 0.12s ease;
157
- color: fn.use-var(text-color, main);
158
- font-size: 13px;
159
- line-height: 1.4;
222
+ gap: fn.use-var(gap, default);
223
+ height: fn.use-var(form-component-height, default);
224
+ padding: 0 fn.use-var(gap, default);
160
225
  border-radius: fn.use-var(radius, small);
161
- margin: 1px 4px;
226
+ font-size: fn.use-var(font-size-main, default);
227
+ color: fn.use-var(text-color, main);
228
+ cursor: pointer;
229
+ user-select: none;
230
+ transition:
231
+ background-color 0.15s ease,
232
+ color 0.15s ease;
162
233
 
163
234
  @include m.is(active) {
164
- background-color: fn.use-var(color, primary);
165
- color: fn.use-var(text-color, white);
166
-
167
- @include m.bem($root-name, item-expand) {
168
- color: fn.use-var(text-color, white);
169
- }
235
+ background-color: fn.use-var(bg-color, hover);
236
+ color: fn.use-var(text-color, title);
170
237
  }
171
238
  }
172
239
 
173
240
  @include m.e(item-label) {
174
241
  flex: 1;
175
- overflow: hidden;
176
- text-overflow: ellipsis;
177
- white-space: nowrap;
242
+ min-width: 0;
243
+ @include m.ellipsis;
178
244
  }
179
245
 
180
246
  @include m.e(item-expand) {
181
247
  flex-shrink: 0;
182
248
  color: fn.use-var(text-color, placeholder);
183
249
  font-size: 12px;
250
+ // 扩大点击热区:u-icon 是固定 1em 盒(全局 border-box),padding 会把 svg 挤成 0 宽,
251
+ // 这里改回 content-box 让字形保持原尺寸,再用负 margin 抵消布局占位
252
+ box-sizing: content-box;
253
+ padding: 6px;
254
+ margin: -6px;
255
+ border-radius: fn.use-var(radius, small);
256
+ cursor: pointer;
257
+ transition:
258
+ color 0.15s ease,
259
+ background-color 0.15s ease;
260
+
261
+ &:hover {
262
+ color: fn.use-var(color, primary);
263
+ background-color: fn.use-var(bg-color, hover);
264
+ }
184
265
  }
185
266
 
186
267
  @include m.e(empty) {
@@ -189,30 +270,51 @@ $root-name: expression-editor;
189
270
  text-align: center;
190
271
  }
191
272
 
273
+ // 面板底部键盘操作提示
274
+ @include m.e(picker-hint) {
275
+ display: flex;
276
+ align-items: center;
277
+ flex-wrap: wrap;
278
+ gap: 4px 12px;
279
+ padding: 6px 10px;
280
+ border-top: fn.use-var(border);
281
+ font-size: fn.use-var(font-size-main, small);
282
+ color: fn.use-var(text-color, placeholder);
283
+ user-select: none;
284
+
285
+ span {
286
+ display: inline-flex;
287
+ align-items: center;
288
+ gap: 3px;
289
+ }
290
+ }
291
+
192
292
  // ─── 面包屑 ───────────────────────────────────────────────
193
293
  @include m.e(breadcrumbs) {
194
294
  display: flex;
195
295
  align-items: center;
196
296
  flex-wrap: wrap;
197
- padding: 6px 10px;
297
+ gap: 2px;
298
+ padding: 6px 8px;
299
+ background-color: fn.use-var(bg-color, middle);
198
300
  border-bottom: fn.use-var(border);
199
- font-size: 12px;
301
+ font-size: fn.use-var(font-size-main, small);
200
302
  color: fn.use-var(text-color, second);
201
303
  }
202
304
 
203
305
  @include m.e(breadcrumb-item) {
204
306
  display: inline-flex;
205
307
  align-items: center;
206
- gap: 4px;
308
+ gap: 2px;
207
309
  }
208
310
 
209
311
  @include m.e(breadcrumb-link) {
312
+ padding: 3px 6px;
313
+ border-radius: fn.use-var(radius, small);
210
314
  cursor: pointer;
211
315
  transition:
212
- color 0.12s ease,
213
- background-color 0.12s ease;
214
- padding: 2px 6px;
215
- border-radius: fn.use-var(radius, small);
316
+ color 0.15s ease,
317
+ background-color 0.15s ease;
216
318
 
217
319
  &:hover {
218
320
  color: fn.use-var(color, primary);
@@ -226,7 +328,7 @@ $root-name: expression-editor;
226
328
  }
227
329
 
228
330
  @include m.e(breadcrumb-separator) {
229
- font-size: 10px;
331
+ font-size: 12px;
230
332
  color: fn.use-var(text-color, placeholder);
231
333
  }
232
334
 
@@ -236,7 +338,7 @@ $root-name: expression-editor;
236
338
  border-left: fn.use-var(border);
237
339
  padding: 8px 12px;
238
340
  background-color: fn.use-var(bg-color, middle);
239
- font-size: 12px;
341
+ font-size: fn.use-var(font-size-main, small);
240
342
  }
241
343
 
242
344
  @include m.e(path-preview-title) {
@@ -257,6 +359,8 @@ $root-name: expression-editor;
257
359
  gap: 4px;
258
360
  line-height: 1.6;
259
361
  color: fn.use-var(text-color, main);
362
+ // 层级缩进由模板传入的 --depth 驱动
363
+ padding-left: calc(var(--depth, 0) * 12px);
260
364
 
261
365
  @include m.is(active) {
262
366
  color: fn.use-var(color, primary);
@@ -264,28 +368,8 @@ $root-name: expression-editor;
264
368
  }
265
369
  }
266
370
 
267
- @include m.e(path-tree-branch) {
268
- color: fn.use-var(text-color, placeholder);
269
- }
270
-
271
371
  @include m.e(path-tree-label) {
272
- overflow: hidden;
273
- text-overflow: ellipsis;
274
- white-space: nowrap;
275
- }
276
-
277
- @include m.size using ($size) {
278
- min-height: fn.use-var(form-component-height, $size);
279
- padding: fn.use-var(gap, $size);
280
-
281
- @include m.bem($root-name, placeholder) {
282
- top: fn.use-var(gap, $size);
283
- left: fn.use-var(gap, $size);
284
- font-size: fn.use-var(font-size-main, $size);
285
- }
286
-
287
- @include m.bem($root-name, container) {
288
- font-size: fn.use-var(font-size-main, $size);
289
- }
372
+ min-width: 0;
373
+ @include m.ellipsis;
290
374
  }
291
375
  }
@@ -3,7 +3,6 @@
3
3
  tag="form"
4
4
  ref="grid"
5
5
  @submit.prevent
6
- gap="0 12px"
7
6
  :cols="cols || breakpointCols"
8
7
  :class="[cls.b, bem.is('readonly', readonly)]"
9
8
  >
@@ -3,15 +3,22 @@
3
3
  @use 'pkg:@veltra/styles/vars';
4
4
 
5
5
  @include m.b(form) {
6
+ // gap 走 CSS 而非 u-grid 内联样式,只读态才能覆盖行距
7
+ gap: 0 12px;
8
+
9
+ // 只读态:label 退为次级文本,值收进浅色圆角条;行距拉开让各项独立成块,避免粘连
6
10
  @include m.is(readonly) {
7
- gap: 6px;
11
+ gap: 10px 12px;
8
12
 
9
13
  @include m.bem(form-item, label) {
10
- background-color: fn.use-var(bg-color, top); // #fbfcfe;
14
+ color: fn.use-var(text-color, second);
11
15
  }
16
+
12
17
  @include m.bem(form-item, content) {
13
- background-color: fn.use-var(bg-color, middle); // #f5f8fb;
14
- padding: 0 8px;
18
+ padding: 4px 12px;
19
+ color: fn.use-var(text-color, main);
20
+ background-color: fn.use-var(bg-color, middle);
21
+ border-radius: fn.use-var(radius, default);
15
22
  }
16
23
  }
17
24
 
@@ -47,12 +47,12 @@ $root-name: form-item;
47
47
  }
48
48
 
49
49
  @include m.is(error) {
50
+ // is-focus 类驱动聚焦态的控件:hover / is-focus 与错误态同权重,按源序分胜负,故显式列出
50
51
  #{fn.bem(input)},
51
52
  #{fn.bem(multi-select)},
52
53
  #{fn.bem(multi-tree-select)},
53
54
  #{fn.bem(auto-complete)},
54
55
  #{fn.bem(textarea--more)} {
55
- // hover 的 primary 描边与错误态同权重,按源序分胜负:错误态显式压住,避免悬浮时描边回蓝
56
56
  &,
57
57
  &:hover,
58
58
  &.is-focus {
@@ -64,6 +64,21 @@ $root-name: form-item;
64
64
  box-shadow: fn.use-var(focus-ring, danger);
65
65
  }
66
66
  }
67
+
68
+ // :focus-within 驱动聚焦态的编辑器类控件;描红目标是各自的视觉盒(表达式编辑器在 __shell 上)
69
+ #{fn.bem(expression-editor, shell)},
70
+ #{fn.bem(code-editor)},
71
+ #{fn.bem(rich-text-editor)} {
72
+ &,
73
+ &:hover,
74
+ &:focus-within {
75
+ border-color: fn.use-var(color, danger);
76
+ }
77
+
78
+ &:focus-within {
79
+ box-shadow: fn.use-var(focus-ring, danger);
80
+ }
81
+ }
67
82
  }
68
83
 
69
84
  @include m.e(content) {
@@ -153,3 +153,5 @@ export * from './badge'
153
153
  export * from './segment'
154
154
 
155
155
  export * from './image-cropper'
156
+
157
+ export * from './kanban'