@cyberpunk-vue/theme-chalk 1.14.0 → 1.14.2

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 (47) hide show
  1. package/dist/index.css +1 -1
  2. package/dist/index.css.map +1 -1
  3. package/package.json +1 -1
  4. package/src/common/var.scss +247 -247
  5. package/src/components/avatar-group.scss +113 -113
  6. package/src/components/avatar.scss +123 -123
  7. package/src/components/badge.scss +210 -210
  8. package/src/components/breadcrumb.scss +203 -203
  9. package/src/components/button.scss +975 -975
  10. package/src/components/card.scss +699 -696
  11. package/src/components/checkbox-group.scss +22 -22
  12. package/src/components/checkbox.scss +320 -320
  13. package/src/components/col.scss +43 -43
  14. package/src/components/dialog.scss +360 -360
  15. package/src/components/divider.scss +250 -250
  16. package/src/components/empty.scss +99 -99
  17. package/src/components/form-item.scss +189 -189
  18. package/src/components/form.scss +59 -59
  19. package/src/components/icon.scss +83 -83
  20. package/src/components/image-preview.scss +147 -147
  21. package/src/components/image.scss +351 -351
  22. package/src/components/input-number.scss +129 -129
  23. package/src/components/input.scss +362 -362
  24. package/src/components/loading.scss +64 -64
  25. package/src/components/notification.scss +348 -348
  26. package/src/components/pagination.scss +287 -280
  27. package/src/components/pattern-background.scss +18 -18
  28. package/src/components/popover.scss +438 -438
  29. package/src/components/progress.scss +438 -438
  30. package/src/components/radio-group.scss +22 -22
  31. package/src/components/radio.scss +286 -286
  32. package/src/components/row.scss +12 -12
  33. package/src/components/scrollbar.scss +40 -40
  34. package/src/components/segmented.scss +566 -566
  35. package/src/components/select.scss +15 -1
  36. package/src/components/slider.scss +421 -421
  37. package/src/components/status-indicator.scss +206 -206
  38. package/src/components/switch.scss +405 -405
  39. package/src/components/table.scss +474 -474
  40. package/src/components/tag.scss +416 -416
  41. package/src/components/text.scss +310 -271
  42. package/src/components/textarea.scss +106 -104
  43. package/src/components/timeline.scss +379 -379
  44. package/src/components/tree.scss +397 -397
  45. package/src/components/upload.scss +509 -509
  46. package/src/index.scss +60 -60
  47. package/src/mixins/mixins.scss +156 -156
@@ -1,397 +1,397 @@
1
- // CpTree 组件样式
2
- // 赛博朋克/机甲风格 — 电路连接线 + 霓虹发光
3
-
4
- @use 'sass:map';
5
- @use '../common/var' as *;
6
- @use '../mixins/mixins' as *;
7
-
8
- // ===== 颜色映射 =====
9
- $tree-type-colors: (
10
- primary: var(--cp-color-primary),
11
- success: var(--cp-color-success),
12
- warning: var(--cp-color-warning),
13
- error: var(--cp-color-error),
14
- info: var(--cp-color-info),
15
- );
16
-
17
- @include b(tree) {
18
- --cp-tree-active-color: var(--cp-color-primary);
19
- --cp-tree-active-color-light: var(--cp-color-primary-light);
20
- --cp-tree-connector-color: var(--cp-border);
21
- --cp-tree-connector-active-color: var(--cp-color-primary);
22
- --cp-tree-node-height: 32px;
23
- --cp-tree-indent: 16px;
24
- --cp-tree-font-weight: var(--cp-font-weight-medium);
25
- --cp-tree-active-font-weight: var(--cp-font-weight-semibold);
26
- --cp-tree-font-weight-transition: var(--cp-font-weight-transition-fast);
27
-
28
- position: relative;
29
- font-family: var(--cp-font-family-ui);
30
- color: var(--cp-text-secondary);
31
- font-size: 14px;
32
-
33
- // ===== 空状态 =====
34
- @include e(empty) {
35
- display: flex;
36
- align-items: center;
37
- justify-content: center;
38
- padding: 32px 16px;
39
- min-height: 100px;
40
- }
41
-
42
- @include e(empty-text) {
43
- font-family: var(--cp-font-family-mono);
44
- font-size: 13px;
45
- font-weight: var(--cp-font-weight-semibold);
46
- font-variation-settings: 'wght' var(--cp-font-weight-semibold);
47
- letter-spacing: 0.3em;
48
- text-transform: uppercase;
49
- color: var(--cp-text-muted);
50
- position: relative;
51
- padding: 4px 12px;
52
- border: 1px solid var(--cp-border);
53
- clip-path: polygon(
54
- 6px 0, 100% 0,
55
- 100% calc(100% - 6px),
56
- calc(100% - 6px) 100%,
57
- 0 100%, 0 6px
58
- );
59
- background: color-mix(in srgb, var(--cp-bg-deep) 40%, transparent);
60
-
61
- // 扫描线纹理
62
- &::after {
63
- content: '';
64
- position: absolute;
65
- inset: 0;
66
- background: repeating-linear-gradient(
67
- 0deg,
68
- transparent,
69
- transparent 2px,
70
- rgba(255, 255, 255, 0.015) 2px,
71
- rgba(255, 255, 255, 0.015) 4px
72
- );
73
- pointer-events: none;
74
- }
75
- }
76
-
77
- // ===== 节点 =====
78
- @include e(node) {
79
- position: relative;
80
- }
81
-
82
- // ===== 节点内容行 =====
83
- @include e(node-content) {
84
- --cp-tree-item-font-weight: var(--cp-tree-font-weight);
85
- display: flex;
86
- align-items: center;
87
- gap: 6px;
88
- min-height: var(--cp-tree-node-height);
89
- padding-right: 8px;
90
- cursor: pointer;
91
- transition: all 0.2s ease;
92
- position: relative;
93
- border-left: 2px solid transparent;
94
-
95
- &:hover:not(.is-disabled) {
96
- background: var(--cp-state-hover);
97
- color: var(--cp-text-primary);
98
- border-left-color: var(--cp-tree-active-color);
99
- }
100
-
101
- // 禁用状态
102
- &.is-disabled {
103
- opacity: 0.45;
104
- cursor: not-allowed;
105
- filter: grayscale(0.6);
106
- }
107
-
108
- // 当前高亮节点
109
- &.is-current {
110
- --cp-tree-item-font-weight: var(--cp-tree-active-font-weight);
111
- background: color-mix(in srgb, var(--cp-tree-active-color) 6%, transparent);
112
- color: var(--cp-text-primary);
113
- border-left-color: var(--cp-tree-active-color);
114
- box-shadow: inset 0 0 20px color-mix(in srgb, var(--cp-tree-active-color) 3%, transparent);
115
-
116
- // 左侧发光条
117
- &::before {
118
- content: '';
119
- position: absolute;
120
- left: -2px;
121
- top: 0;
122
- bottom: 0;
123
- width: 2px;
124
- background: var(--cp-tree-active-color);
125
- box-shadow: 0 0 6px var(--cp-tree-active-color),
126
- 0 0 12px var(--cp-tree-active-color-light);
127
- }
128
- }
129
- }
130
-
131
- // ===== 展开箭头 =====
132
- @include e(expand-icon) {
133
- display: flex;
134
- align-items: center;
135
- justify-content: center;
136
- width: 18px;
137
- height: 18px;
138
- flex-shrink: 0;
139
- color: var(--cp-text-muted);
140
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
141
-
142
- svg {
143
- width: 14px;
144
- height: 14px;
145
- transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
146
- }
147
-
148
- &.is-expanded svg {
149
- transform: rotate(90deg);
150
- }
151
-
152
- &:not(.is-leaf):hover {
153
- color: var(--cp-tree-active-color);
154
- }
155
-
156
- // 叶子节点箭头隐藏
157
- &.is-leaf {
158
- svg {
159
- display: none;
160
- }
161
- }
162
-
163
- // 自定义图标模式:调整容器
164
- &.is-custom-icon {
165
- svg {
166
- // 自定义图标不应用默认旋转
167
- transform: none;
168
- }
169
-
170
- // 只有 expandIcon 无 collapseIcon 时,展开态通过旋转实现
171
- &.is-rotate-expand {
172
- transform: rotate(90deg);
173
- }
174
- }
175
- }
176
-
177
- // 叶子节点小点
178
- @include e(leaf-dot) {
179
- display: block;
180
- width: 4px;
181
- height: 4px;
182
- background: var(--cp-border);
183
- clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
184
- transition: background 0.2s ease;
185
-
186
- .cp-tree__node-content:hover & {
187
- background: var(--cp-tree-active-color);
188
- }
189
- }
190
-
191
- // ===== 节点前缀图标 =====
192
- @include e(node-icon) {
193
- display: flex;
194
- align-items: center;
195
- justify-content: center;
196
- width: 18px;
197
- height: 18px;
198
- flex-shrink: 0;
199
- color: var(--cp-text-secondary);
200
- transition: color 0.2s ease;
201
-
202
- svg {
203
- width: 16px;
204
- height: 16px;
205
- }
206
-
207
- .cp-tree__node-content:hover & {
208
- color: var(--cp-tree-active-color);
209
- }
210
- }
211
-
212
- // ===== 复选框 =====
213
- @include e(checkbox) {
214
- position: relative;
215
- display: flex;
216
- align-items: center;
217
- justify-content: center;
218
- width: 16px;
219
- height: 16px;
220
- flex-shrink: 0;
221
- background: color-mix(in srgb, var(--cp-bg-deep) 80%, transparent);
222
- border: 1px solid var(--cp-border);
223
- cursor: pointer;
224
- transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
225
- clip-path: polygon(
226
- 3px 0, 100% 0,
227
- 100% calc(100% - 3px),
228
- calc(100% - 3px) 100%,
229
- 0 100%, 0 3px
230
- );
231
-
232
- &:hover:not(.is-disabled) {
233
- border-color: var(--cp-tree-active-color);
234
- box-shadow: 0 0 6px var(--cp-tree-active-color-light);
235
- }
236
-
237
- // 选中
238
- &.is-checked {
239
- background: var(--cp-tree-active-color);
240
- border-color: var(--cp-tree-active-color);
241
- box-shadow: 0 0 8px var(--cp-tree-active-color-light);
242
- }
243
-
244
- // 半选
245
- &.is-indeterminate {
246
- background: var(--cp-tree-active-color);
247
- border-color: var(--cp-tree-active-color);
248
- box-shadow: 0 0 8px var(--cp-tree-active-color-light);
249
- }
250
-
251
- // 禁用
252
- &.is-disabled {
253
- opacity: 0.45;
254
- cursor: not-allowed;
255
- filter: grayscale(0.6);
256
- }
257
- }
258
-
259
- @include e(checkbox-icon) {
260
- width: 70%;
261
- height: 70%;
262
- color: var(--cp-text-inverse);
263
- }
264
-
265
- // ===== 单选框(showRadio)=====
266
- @include e(radio) {
267
- position: relative;
268
- display: flex;
269
- align-items: center;
270
- justify-content: center;
271
- width: 16px;
272
- height: 16px;
273
- flex-shrink: 0;
274
- background: color-mix(in srgb, var(--cp-bg-deep) 80%, transparent);
275
- border: 1px solid var(--cp-border);
276
- cursor: pointer;
277
- transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
278
- // 八边形:与 CpRadio 视觉语言对齐
279
- clip-path: polygon(
280
- 30% 0%, 70% 0%,
281
- 100% 30%, 100% 70%,
282
- 70% 100%, 30% 100%,
283
- 0% 70%, 0% 30%
284
- );
285
-
286
- &:hover:not(.is-disabled) {
287
- border-color: var(--cp-tree-active-color);
288
- box-shadow: 0 0 6px var(--cp-tree-active-color-light);
289
- }
290
-
291
- &.is-checked {
292
- border-color: var(--cp-tree-active-color);
293
- box-shadow: 0 0 8px var(--cp-tree-active-color-light);
294
- }
295
-
296
- &.is-disabled {
297
- opacity: 0.45;
298
- cursor: not-allowed;
299
- filter: grayscale(0.6);
300
- }
301
- }
302
-
303
- @include e(radio-dot) {
304
- width: 60%;
305
- height: 60%;
306
- background: var(--cp-tree-active-color);
307
- box-shadow: 0 0 4px var(--cp-tree-active-color);
308
- // 内部菱形小点
309
- clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
310
- }
311
-
312
- // ===== 标签 =====
313
- @include e(label) {
314
- font-weight: var(--cp-tree-item-font-weight);
315
- font-variation-settings: 'wght' var(--cp-tree-item-font-weight);
316
- flex: 1;
317
- min-width: 0;
318
- overflow: hidden;
319
- text-overflow: ellipsis;
320
- white-space: nowrap;
321
- transition:
322
- color 0.2s ease,
323
- font-weight var(--cp-tree-font-weight-transition),
324
- font-variation-settings var(--cp-tree-font-weight-transition);
325
- letter-spacing: 0.01em;
326
- }
327
-
328
- // ===== 子节点容器 =====
329
- @include e(children) {
330
- position: relative;
331
- }
332
-
333
- // ===== 连接线模式 =====
334
- @include when(connector-line) {
335
- .cp-tree__children {
336
- position: relative;
337
-
338
- // 竖向连接线
339
- &::before {
340
- content: '';
341
- position: absolute;
342
- left: calc(var(--cp-tree-indent, 16px) * 0.5 + 9px);
343
- top: 0;
344
- bottom: 12px;
345
- width: 1px;
346
- background: linear-gradient(
347
- to bottom,
348
- var(--cp-tree-connector-color),
349
- var(--cp-tree-connector-color) 70%,
350
- transparent
351
- );
352
- opacity: 0.5;
353
- transition: opacity 0.3s ease;
354
- }
355
- }
356
-
357
- // 横向连接线由 padding-left 自然定位,无需额外伪元素
358
-
359
- // hover 时连接线高亮
360
- .cp-tree__node:hover > .cp-tree__children::before {
361
- opacity: 1;
362
- background: linear-gradient(
363
- to bottom,
364
- var(--cp-tree-active-color),
365
- var(--cp-tree-active-color) 70%,
366
- transparent
367
- );
368
- box-shadow: 0 0 4px var(--cp-tree-active-color-light);
369
- }
370
- }
371
-
372
- // ===== 颜色变体 =====
373
- @each $type, $color in $tree-type-colors {
374
- &.cp-tree--#{$type} { // 通过外部 class 控制
375
- --cp-tree-active-color: #{$color};
376
- --cp-tree-active-color-light: var(--cp-color-#{$type}-light);
377
- }
378
- }
379
- }
380
-
381
- // ===== 展开/收起动画 =====
382
- .cp-tree-expand-enter-active,
383
- .cp-tree-expand-leave-active {
384
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
385
- overflow: hidden;
386
- }
387
-
388
- .cp-tree-expand-enter-from,
389
- .cp-tree-expand-leave-to {
390
- opacity: 0;
391
- max-height: 0;
392
- }
393
-
394
- .cp-tree-expand-enter-to,
395
- .cp-tree-expand-leave-from {
396
- opacity: 1;
397
- }
1
+ // CpTree 组件样式
2
+ // 赛博朋克/机甲风格 — 电路连接线 + 霓虹发光
3
+
4
+ @use 'sass:map';
5
+ @use '../common/var' as *;
6
+ @use '../mixins/mixins' as *;
7
+
8
+ // ===== 颜色映射 =====
9
+ $tree-type-colors: (
10
+ primary: var(--cp-color-primary),
11
+ success: var(--cp-color-success),
12
+ warning: var(--cp-color-warning),
13
+ error: var(--cp-color-error),
14
+ info: var(--cp-color-info),
15
+ );
16
+
17
+ @include b(tree) {
18
+ --cp-tree-active-color: var(--cp-color-primary);
19
+ --cp-tree-active-color-light: var(--cp-color-primary-light);
20
+ --cp-tree-connector-color: var(--cp-border);
21
+ --cp-tree-connector-active-color: var(--cp-color-primary);
22
+ --cp-tree-node-height: 32px;
23
+ --cp-tree-indent: 16px;
24
+ --cp-tree-font-weight: var(--cp-font-weight-medium);
25
+ --cp-tree-active-font-weight: var(--cp-font-weight-semibold);
26
+ --cp-tree-font-weight-transition: var(--cp-font-weight-transition-fast);
27
+
28
+ position: relative;
29
+ font-family: var(--cp-font-family-ui);
30
+ color: var(--cp-text-secondary);
31
+ font-size: 14px;
32
+
33
+ // ===== 空状态 =====
34
+ @include e(empty) {
35
+ display: flex;
36
+ align-items: center;
37
+ justify-content: center;
38
+ padding: 32px 16px;
39
+ min-height: 100px;
40
+ }
41
+
42
+ @include e(empty-text) {
43
+ font-family: var(--cp-font-family-mono);
44
+ font-size: 13px;
45
+ font-weight: var(--cp-font-weight-semibold);
46
+ font-variation-settings: 'wght' var(--cp-font-weight-semibold);
47
+ letter-spacing: 0.3em;
48
+ text-transform: uppercase;
49
+ color: var(--cp-text-muted);
50
+ position: relative;
51
+ padding: 4px 12px;
52
+ border: 1px solid var(--cp-border);
53
+ clip-path: polygon(
54
+ 6px 0, 100% 0,
55
+ 100% calc(100% - 6px),
56
+ calc(100% - 6px) 100%,
57
+ 0 100%, 0 6px
58
+ );
59
+ background: color-mix(in srgb, var(--cp-bg-deep) 40%, transparent);
60
+
61
+ // 扫描线纹理
62
+ &::after {
63
+ content: '';
64
+ position: absolute;
65
+ inset: 0;
66
+ background: repeating-linear-gradient(
67
+ 0deg,
68
+ transparent,
69
+ transparent 2px,
70
+ rgba(255, 255, 255, 0.015) 2px,
71
+ rgba(255, 255, 255, 0.015) 4px
72
+ );
73
+ pointer-events: none;
74
+ }
75
+ }
76
+
77
+ // ===== 节点 =====
78
+ @include e(node) {
79
+ position: relative;
80
+ }
81
+
82
+ // ===== 节点内容行 =====
83
+ @include e(node-content) {
84
+ --cp-tree-item-font-weight: var(--cp-tree-font-weight);
85
+ display: flex;
86
+ align-items: center;
87
+ gap: 6px;
88
+ min-height: var(--cp-tree-node-height);
89
+ padding-right: 8px;
90
+ cursor: pointer;
91
+ transition: all 0.2s ease;
92
+ position: relative;
93
+ border-left: 2px solid transparent;
94
+
95
+ &:hover:not(.is-disabled) {
96
+ background: var(--cp-state-hover);
97
+ color: var(--cp-text-primary);
98
+ border-left-color: var(--cp-tree-active-color);
99
+ }
100
+
101
+ // 禁用状态
102
+ &.is-disabled {
103
+ opacity: 0.45;
104
+ cursor: not-allowed;
105
+ filter: grayscale(0.6);
106
+ }
107
+
108
+ // 当前高亮节点
109
+ &.is-current {
110
+ --cp-tree-item-font-weight: var(--cp-tree-active-font-weight);
111
+ background: color-mix(in srgb, var(--cp-tree-active-color) 6%, transparent);
112
+ color: var(--cp-text-primary);
113
+ border-left-color: var(--cp-tree-active-color);
114
+ box-shadow: inset 0 0 20px color-mix(in srgb, var(--cp-tree-active-color) 3%, transparent);
115
+
116
+ // 左侧发光条
117
+ &::before {
118
+ content: '';
119
+ position: absolute;
120
+ left: -2px;
121
+ top: 0;
122
+ bottom: 0;
123
+ width: 2px;
124
+ background: var(--cp-tree-active-color);
125
+ box-shadow: 0 0 6px var(--cp-tree-active-color),
126
+ 0 0 12px var(--cp-tree-active-color-light);
127
+ }
128
+ }
129
+ }
130
+
131
+ // ===== 展开箭头 =====
132
+ @include e(expand-icon) {
133
+ display: flex;
134
+ align-items: center;
135
+ justify-content: center;
136
+ width: 18px;
137
+ height: 18px;
138
+ flex-shrink: 0;
139
+ color: var(--cp-text-muted);
140
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
141
+
142
+ svg {
143
+ width: 14px;
144
+ height: 14px;
145
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
146
+ }
147
+
148
+ &.is-expanded svg {
149
+ transform: rotate(90deg);
150
+ }
151
+
152
+ &:not(.is-leaf):hover {
153
+ color: var(--cp-tree-active-color);
154
+ }
155
+
156
+ // 叶子节点箭头隐藏
157
+ &.is-leaf {
158
+ svg {
159
+ display: none;
160
+ }
161
+ }
162
+
163
+ // 自定义图标模式:调整容器
164
+ &.is-custom-icon {
165
+ svg {
166
+ // 自定义图标不应用默认旋转
167
+ transform: none;
168
+ }
169
+
170
+ // 只有 expandIcon 无 collapseIcon 时,展开态通过旋转实现
171
+ &.is-rotate-expand {
172
+ transform: rotate(90deg);
173
+ }
174
+ }
175
+ }
176
+
177
+ // 叶子节点小点
178
+ @include e(leaf-dot) {
179
+ display: block;
180
+ width: 4px;
181
+ height: 4px;
182
+ background: var(--cp-border);
183
+ clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
184
+ transition: background 0.2s ease;
185
+
186
+ .cp-tree__node-content:hover & {
187
+ background: var(--cp-tree-active-color);
188
+ }
189
+ }
190
+
191
+ // ===== 节点前缀图标 =====
192
+ @include e(node-icon) {
193
+ display: flex;
194
+ align-items: center;
195
+ justify-content: center;
196
+ width: 18px;
197
+ height: 18px;
198
+ flex-shrink: 0;
199
+ color: var(--cp-text-secondary);
200
+ transition: color 0.2s ease;
201
+
202
+ svg {
203
+ width: 16px;
204
+ height: 16px;
205
+ }
206
+
207
+ .cp-tree__node-content:hover & {
208
+ color: var(--cp-tree-active-color);
209
+ }
210
+ }
211
+
212
+ // ===== 复选框 =====
213
+ @include e(checkbox) {
214
+ position: relative;
215
+ display: flex;
216
+ align-items: center;
217
+ justify-content: center;
218
+ width: 16px;
219
+ height: 16px;
220
+ flex-shrink: 0;
221
+ background: color-mix(in srgb, var(--cp-bg-deep) 80%, transparent);
222
+ border: 1px solid var(--cp-border);
223
+ cursor: pointer;
224
+ transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
225
+ clip-path: polygon(
226
+ 3px 0, 100% 0,
227
+ 100% calc(100% - 3px),
228
+ calc(100% - 3px) 100%,
229
+ 0 100%, 0 3px
230
+ );
231
+
232
+ &:hover:not(.is-disabled) {
233
+ border-color: var(--cp-tree-active-color);
234
+ box-shadow: 0 0 6px var(--cp-tree-active-color-light);
235
+ }
236
+
237
+ // 选中
238
+ &.is-checked {
239
+ background: var(--cp-tree-active-color);
240
+ border-color: var(--cp-tree-active-color);
241
+ box-shadow: 0 0 8px var(--cp-tree-active-color-light);
242
+ }
243
+
244
+ // 半选
245
+ &.is-indeterminate {
246
+ background: var(--cp-tree-active-color);
247
+ border-color: var(--cp-tree-active-color);
248
+ box-shadow: 0 0 8px var(--cp-tree-active-color-light);
249
+ }
250
+
251
+ // 禁用
252
+ &.is-disabled {
253
+ opacity: 0.45;
254
+ cursor: not-allowed;
255
+ filter: grayscale(0.6);
256
+ }
257
+ }
258
+
259
+ @include e(checkbox-icon) {
260
+ width: 70%;
261
+ height: 70%;
262
+ color: var(--cp-text-inverse);
263
+ }
264
+
265
+ // ===== 单选框(showRadio)=====
266
+ @include e(radio) {
267
+ position: relative;
268
+ display: flex;
269
+ align-items: center;
270
+ justify-content: center;
271
+ width: 16px;
272
+ height: 16px;
273
+ flex-shrink: 0;
274
+ background: color-mix(in srgb, var(--cp-bg-deep) 80%, transparent);
275
+ border: 1px solid var(--cp-border);
276
+ cursor: pointer;
277
+ transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
278
+ // 八边形:与 CpRadio 视觉语言对齐
279
+ clip-path: polygon(
280
+ 30% 0%, 70% 0%,
281
+ 100% 30%, 100% 70%,
282
+ 70% 100%, 30% 100%,
283
+ 0% 70%, 0% 30%
284
+ );
285
+
286
+ &:hover:not(.is-disabled) {
287
+ border-color: var(--cp-tree-active-color);
288
+ box-shadow: 0 0 6px var(--cp-tree-active-color-light);
289
+ }
290
+
291
+ &.is-checked {
292
+ border-color: var(--cp-tree-active-color);
293
+ box-shadow: 0 0 8px var(--cp-tree-active-color-light);
294
+ }
295
+
296
+ &.is-disabled {
297
+ opacity: 0.45;
298
+ cursor: not-allowed;
299
+ filter: grayscale(0.6);
300
+ }
301
+ }
302
+
303
+ @include e(radio-dot) {
304
+ width: 60%;
305
+ height: 60%;
306
+ background: var(--cp-tree-active-color);
307
+ box-shadow: 0 0 4px var(--cp-tree-active-color);
308
+ // 内部菱形小点
309
+ clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
310
+ }
311
+
312
+ // ===== 标签 =====
313
+ @include e(label) {
314
+ font-weight: var(--cp-tree-item-font-weight);
315
+ font-variation-settings: 'wght' var(--cp-tree-item-font-weight);
316
+ flex: 1;
317
+ min-width: 0;
318
+ overflow: hidden;
319
+ text-overflow: ellipsis;
320
+ white-space: nowrap;
321
+ transition:
322
+ color 0.2s ease,
323
+ font-weight var(--cp-tree-font-weight-transition),
324
+ font-variation-settings var(--cp-tree-font-weight-transition);
325
+ letter-spacing: 0.01em;
326
+ }
327
+
328
+ // ===== 子节点容器 =====
329
+ @include e(children) {
330
+ position: relative;
331
+ }
332
+
333
+ // ===== 连接线模式 =====
334
+ @include when(connector-line) {
335
+ .cp-tree__children {
336
+ position: relative;
337
+
338
+ // 竖向连接线
339
+ &::before {
340
+ content: '';
341
+ position: absolute;
342
+ left: calc(var(--cp-tree-indent, 16px) * 0.5 + 9px);
343
+ top: 0;
344
+ bottom: 12px;
345
+ width: 1px;
346
+ background: linear-gradient(
347
+ to bottom,
348
+ var(--cp-tree-connector-color),
349
+ var(--cp-tree-connector-color) 70%,
350
+ transparent
351
+ );
352
+ opacity: 0.5;
353
+ transition: opacity 0.3s ease;
354
+ }
355
+ }
356
+
357
+ // 横向连接线由 padding-left 自然定位,无需额外伪元素
358
+
359
+ // hover 时连接线高亮
360
+ .cp-tree__node:hover > .cp-tree__children::before {
361
+ opacity: 1;
362
+ background: linear-gradient(
363
+ to bottom,
364
+ var(--cp-tree-active-color),
365
+ var(--cp-tree-active-color) 70%,
366
+ transparent
367
+ );
368
+ box-shadow: 0 0 4px var(--cp-tree-active-color-light);
369
+ }
370
+ }
371
+
372
+ // ===== 颜色变体 =====
373
+ @each $type, $color in $tree-type-colors {
374
+ &.cp-tree--#{$type} { // 通过外部 class 控制
375
+ --cp-tree-active-color: #{$color};
376
+ --cp-tree-active-color-light: var(--cp-color-#{$type}-light);
377
+ }
378
+ }
379
+ }
380
+
381
+ // ===== 展开/收起动画 =====
382
+ .cp-tree-expand-enter-active,
383
+ .cp-tree-expand-leave-active {
384
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
385
+ overflow: hidden;
386
+ }
387
+
388
+ .cp-tree-expand-enter-from,
389
+ .cp-tree-expand-leave-to {
390
+ opacity: 0;
391
+ max-height: 0;
392
+ }
393
+
394
+ .cp-tree-expand-enter-to,
395
+ .cp-tree-expand-leave-from {
396
+ opacity: 1;
397
+ }