@xihan-ui/styles 1.0.0-alpha.3 → 1.1.0

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 (99) hide show
  1. package/CHANGELOG.md +1922 -0
  2. package/README.md +1 -1
  3. package/css/accordion.css +25 -2
  4. package/css/alert.css +13 -9
  5. package/css/anchor.css +1 -1
  6. package/css/avatar-group.css +5 -1
  7. package/css/avatar.css +6 -0
  8. package/css/back-top.css +6 -0
  9. package/css/badge.css +94 -36
  10. package/css/breadcrumb.css +1 -1
  11. package/css/button-group.css +4 -0
  12. package/css/button.css +6 -0
  13. package/css/calendar.css +39 -13
  14. package/css/card.css +15 -6
  15. package/css/cascader.css +29 -23
  16. package/css/checkbox-group.css +38 -10
  17. package/css/checkbox.css +21 -10
  18. package/css/collapsible.css +7 -1
  19. package/css/color-picker.css +22 -2
  20. package/css/combobox.css +18 -7
  21. package/css/context-menu.css +17 -6
  22. package/css/date-field.css +2 -2
  23. package/css/date-picker.css +27 -17
  24. package/css/descriptions.css +9 -3
  25. package/css/dialog.css +7 -1
  26. package/css/drawer.css +15 -5
  27. package/css/dynamic-input.css +7 -0
  28. package/css/ellipsis.css +6 -0
  29. package/css/empty-state.css +16 -6
  30. package/css/field.css +7 -0
  31. package/css/file-upload.css +1 -1
  32. package/css/flex.css +13 -7
  33. package/css/float-button.css +7 -0
  34. package/css/floating-panel.css +6 -0
  35. package/css/grid.css +11 -5
  36. package/css/heatmap.css +3 -2
  37. package/css/highlight.css +1 -1
  38. package/css/hotkeys.css +1 -1
  39. package/css/hover-card.css +3 -0
  40. package/css/image-cropper.css +4 -2
  41. package/css/image-viewer.css +18 -5
  42. package/css/json-viewer.css +34 -1
  43. package/css/layout.css +15 -7
  44. package/css/list.css +14 -5
  45. package/css/listbox.css +4 -2
  46. package/css/loading-bar.css +5 -4
  47. package/css/log.css +6 -2
  48. package/css/masonry.css +5 -5
  49. package/css/mention.css +13 -3
  50. package/css/menu.css +16 -5
  51. package/css/menubar.css +14 -6
  52. package/css/navigation-menu.css +2 -2
  53. package/css/notification.css +377 -0
  54. package/css/number-field.css +9 -3
  55. package/css/page-header.css +7 -0
  56. package/css/pagination.css +158 -1
  57. package/css/password-input.css +4 -4
  58. package/css/pin-input.css +2 -2
  59. package/css/popconfirm.css +9 -2
  60. package/css/popover.css +3 -0
  61. package/css/popselect.css +24 -4
  62. package/css/progress.css +8 -2
  63. package/css/radio-group.css +17 -6
  64. package/css/rating.css +2 -2
  65. package/css/resizable.css +113 -0
  66. package/css/result.css +15 -5
  67. package/css/scrollbar.css +3 -0
  68. package/css/segmented.css +1 -1
  69. package/css/select.css +25 -7
  70. package/css/side-nav.css +16 -5
  71. package/css/slider.css +4 -2
  72. package/css/sortable.css +103 -0
  73. package/css/space.css +6 -6
  74. package/css/steps.css +6 -6
  75. package/css/switch.css +9 -2
  76. package/css/table.css +309 -10
  77. package/css/tabs.css +148 -1
  78. package/css/tag.css +3 -1
  79. package/css/tags-input.css +3 -3
  80. package/css/text-field.css +3 -3
  81. package/css/thread.css +10 -2
  82. package/css/time-field.css +2 -2
  83. package/css/time-picker.css +6 -6
  84. package/css/timeline.css +7 -7
  85. package/css/toast.css +103 -53
  86. package/css/toggle-group.css +30 -4
  87. package/css/toggle.css +6 -0
  88. package/css/tone.css +47 -17
  89. package/css/tooltip.css +7 -1
  90. package/css/tour.css +9 -3
  91. package/css/transfer.css +38 -12
  92. package/css/tree-select.css +30 -5
  93. package/css/tree.css +175 -4
  94. package/css/typography.css +1 -1
  95. package/css/undefined.css +1 -0
  96. package/index.css +3 -1
  97. package/index.unlayered.css +2650 -634
  98. package/package.json +5 -3
  99. package/css/toaster.css +0 -74
package/css/transfer.css CHANGED
@@ -130,6 +130,7 @@
130
130
  display: flex;
131
131
  flex: 1 1 auto;
132
132
  flex-direction: column;
133
+ gap: var(--xh-transfer-list-gap, var(--xh-list-option-gap));
133
134
  block-size: var(--xh-transfer-list-h, var(--xh-viewport-h-md));
134
135
  padding-block: var(--xh-transfer-list-py, var(--xh-space-1));
135
136
  padding-inline: var(--xh-transfer-list-px, var(--xh-space-1));
@@ -222,8 +223,7 @@
222
223
  }
223
224
 
224
225
  /* 没写内容就由皮肤画勾;作者往格子里塞了自己的图形,这条规则即不命中。
225
- 底下两处(全选格的两态)不带这条守卫:那里的 ::before 是方框本身,
226
- 而触发器里装的是全选那行文字,:empty 恒不命中,加了勾号会整个消失 */
226
+ 底下两处(全选格的两态)不带这条守卫:触发器里装的是全选那行文字,:empty 恒不命中 */
227
227
  [data-scope='transfer'][data-part='item-checkbox'][data-state='checked']:empty::before {
228
228
  content: '';
229
229
  display: inline-block;
@@ -236,25 +236,47 @@
236
236
  }
237
237
 
238
238
  /* 全选格的三态:all 打勾、some 打横杠、none 留空。
239
- some 就是读屏听到的 aria-checked=mixed,两者同源,样式只认 data-state */
240
- [data-scope='transfer'][data-part='select-all-trigger'][data-state='checked']::before {
239
+ some 就是读屏听到的 aria-checked=mixed,两者同源,样式只认 data-state
240
+
241
+ 字形走 ::after 而不是画方框的那颗 ::before:mask 会把所在元素的描边与底色一并裁成
242
+ 字形的轮廓,写在 ::before 上就等于把方框本身裁没了,只剩一枚白勾。条目那一侧是
243
+ 真实节点当方框、它的 ::before 当字形的两层结构,这里没有第二个节点,只能用
244
+ 第二个伪元素补上那一层。
245
+ 方框是行首那颗 ::before、宽度即勾选格尺寸,所以字形按「盒与字形的宽度差之半」
246
+ 内推即落在圆心;纵向靠 inset-block: 0 + margin-block: auto 居中。
247
+ font-size 与 ::before 同值,--xh-icon-size 的 1em 兜底才和条目那侧量得一样大 */
248
+ [data-scope='transfer'][data-part='select-all-trigger'][data-state='checked']::after {
241
249
  content: '';
242
- display: inline-block;
250
+ position: absolute;
251
+ inset-block: 0;
252
+ inset-inline-start: 0;
253
+ margin-block: auto;
254
+ margin-inline-start: calc(
255
+ (var(--xh-transfer-checkbox-size, var(--xh-control-indicator-size)) - var(--xh-icon-size, var(--xh-glyph-size-text))) /
256
+ 2
257
+ );
243
258
  inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
244
259
  block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
245
- vertical-align: var(--xh-glyph-baseline-shift);
246
- background-color: currentColor;
260
+ background-color: var(--xh-transfer-checkbox-fg, var(--xh-fg-on-brand));
261
+ font-size: var(--xh-transfer-checkbox-font-size, calc(var(--xh-control-indicator-size) * 0.75));
247
262
  -webkit-mask: var(--xh-glyph-mark-check) center / contain no-repeat;
248
263
  mask: var(--xh-glyph-mark-check) center / contain no-repeat;
249
264
  }
250
265
 
251
- [data-scope='transfer'][data-part='select-all-trigger'][data-state='indeterminate']::before {
266
+ [data-scope='transfer'][data-part='select-all-trigger'][data-state='indeterminate']::after {
252
267
  content: '';
253
- display: inline-block;
268
+ position: absolute;
269
+ inset-block: 0;
270
+ inset-inline-start: 0;
271
+ margin-block: auto;
272
+ margin-inline-start: calc(
273
+ (var(--xh-transfer-checkbox-size, var(--xh-control-indicator-size)) - var(--xh-icon-size, var(--xh-glyph-size-text))) /
274
+ 2
275
+ );
254
276
  inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
255
277
  block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
256
- vertical-align: var(--xh-glyph-baseline-shift);
257
- background-color: currentColor;
278
+ background-color: var(--xh-transfer-checkbox-fg, var(--xh-fg-on-brand));
279
+ font-size: var(--xh-transfer-checkbox-font-size, calc(var(--xh-control-indicator-size) * 0.75));
258
280
  -webkit-mask: var(--xh-glyph-mark-minus) center / contain no-repeat;
259
281
  mask: var(--xh-glyph-mark-minus) center / contain no-repeat;
260
282
  }
@@ -266,7 +288,9 @@
266
288
 
267
289
  /* 全选格是原生按钮(三态经 aria-checked 上报,激活由平台负责),
268
290
  禁用因此写 :disabled,不写 data-disabled */
291
+ /* position 是给叠在方框上的那颗字形 ::after 当定位基准 */
269
292
  [data-scope='transfer'][data-part='select-all-trigger'] {
293
+ position: relative;
270
294
  display: inline-flex;
271
295
  flex: none;
272
296
  gap: var(--xh-transfer-select-all-gap, var(--xh-control-gap-sm));
@@ -282,9 +306,11 @@
282
306
  cursor: pointer;
283
307
  }
284
308
 
309
+ /* 往内收,与搜索框、条目同一口径:全选格长在面板里,面板收 overflow,
310
+ 环画在外沿会被裁掉 */
285
311
  [data-scope='transfer'][data-part='select-all-trigger']:focus-visible {
286
312
  outline: var(--xh-ring-width) solid var(--xh-ring-focus);
287
- outline-offset: var(--xh-ring-offset);
313
+ outline-offset: calc(-1 * var(--xh-ring-width));
288
314
  }
289
315
 
290
316
  [data-scope='transfer'][data-part='select-all-trigger']:disabled {
@@ -37,6 +37,9 @@
37
37
  引擎没算(尚未落位 / 无引擎)时不额外限高 */
38
38
  --xh-_tree-select-available-h: 100vh;
39
39
 
40
+ /* 树的自绘条浮在内容之上:轨道不上底色,实色轨道会沿内容边缘糊出一条灰带 */
41
+ --xh-scrollbar-track-bg: transparent;
42
+
40
43
  position: fixed;
41
44
  z-index: var(--xh-tree-select-layer, var(--xh-layer-popover));
42
45
  /* 空壳不吃指针,交互只发生在 content 里 */
@@ -56,9 +59,11 @@
56
59
  /* 尺寸档只换这几个私有槽,盒与树里的行都从这两处继承它们,换档不必给每个部件各写一条选择器 */
57
60
  --xh-_tree-select-h: var(--xh-control-h-md);
58
61
  --xh-_tree-select-px: var(--xh-control-px-md);
62
+ --xh-_tree-select-row-py: var(--xh-list-option-py-md);
63
+ --xh-_tree-select-row-px: var(--xh-control-px-md);
59
64
  --xh-_tree-select-gap: var(--xh-control-gap-md);
60
- --xh-_tree-select-font-size: var(--xh-text-body-size);
61
- --xh-_tree-select-label-font-size: var(--xh-text-label-size);
65
+ --xh-_tree-select-font-size: var(--xh-control-font-md);
66
+ --xh-_tree-select-label-font-size: var(--xh-control-font-md);
62
67
 
63
68
  /* 形态档只换触发框的描边与底色这三个槽,浮层与树不跟着变:
64
69
  变的是「这是个输入位」的表达方式,不是弹出内容的表达方式 */
@@ -114,6 +119,8 @@
114
119
  --xh-icon-size: var(--xh-tree-select-icon-size, var(--xh-glyph-size-sm));
115
120
  --xh-_tree-select-h: var(--xh-control-h-sm);
116
121
  --xh-_tree-select-px: var(--xh-control-px-sm);
122
+ --xh-_tree-select-row-py: var(--xh-list-option-py-sm);
123
+ --xh-_tree-select-row-px: var(--xh-control-px-sm);
117
124
  --xh-_tree-select-gap: var(--xh-control-gap-sm);
118
125
  --xh-_tree-select-font-size: var(--xh-control-font-sm);
119
126
  --xh-_tree-select-label-font-size: var(--xh-control-font-sm);
@@ -123,6 +130,8 @@
123
130
  --xh-icon-size: var(--xh-tree-select-icon-size, var(--xh-glyph-size-lg));
124
131
  --xh-_tree-select-h: var(--xh-control-h-lg);
125
132
  --xh-_tree-select-px: var(--xh-control-px-lg);
133
+ --xh-_tree-select-row-py: var(--xh-list-option-py-lg);
134
+ --xh-_tree-select-row-px: var(--xh-control-px-lg);
126
135
  --xh-_tree-select-gap: var(--xh-control-gap-lg);
127
136
  --xh-_tree-select-font-size: var(--xh-control-font-lg);
128
137
  --xh-_tree-select-label-font-size: var(--xh-control-font-lg);
@@ -352,6 +361,7 @@
352
361
  [data-scope='tree-select'][data-part='tree'] {
353
362
  display: flex;
354
363
  flex-direction: column;
364
+ gap: var(--xh-tree-select-tree-gap, var(--xh-list-option-gap));
355
365
  }
356
366
 
357
367
  [data-scope='tree-select'][data-part='tree'][hidden] {
@@ -369,6 +379,20 @@
369
379
  outline: none;
370
380
  }
371
381
 
382
+ /* 分支是"这一行 + 它的子层"的外壳,不自带内边距:真正长成一行的是 branch-control,
383
+ 子层缩进归 branch-content。行距由这里出:分支自己那一行与它展开的子层之间,
384
+ 同样按条目间距断开 */
385
+ [data-scope='tree-select'][data-part='branch'] {
386
+ display: flex;
387
+ flex-direction: column;
388
+ gap: var(--xh-tree-select-branch-gap, var(--xh-list-option-gap));
389
+ }
390
+
391
+ /* display 盖掉了 UA 的 [hidden]{display:none},收起时要显式让位 */
392
+ [data-scope='tree-select'][data-part='branch'][hidden] {
393
+ display: none;
394
+ }
395
+
372
396
  /* 焦点落在 branch 上(它才是 treeitem),但环画在它自己那一行上:
373
397
  整棵子树套一圈描边会把展开的层级全框进去 */
374
398
  [data-scope='tree-select'][data-part='branch']:focus-visible {
@@ -387,8 +411,8 @@
387
411
  display: flex;
388
412
  align-items: center;
389
413
  gap: var(--xh-tree-select-row-gap, var(--xh-_tree-select-gap));
390
- padding-block: var(--xh-tree-select-row-py, var(--xh-space-1_5));
391
- padding-inline: var(--xh-tree-select-row-px, var(--xh-control-px-md));
414
+ padding-block: var(--xh-tree-select-row-py, var(--xh-_tree-select-row-py));
415
+ padding-inline: var(--xh-tree-select-row-px, var(--xh-_tree-select-row-px));
392
416
  border-radius: var(--xh-tree-select-row-radius, var(--xh-shape-control));
393
417
  color: var(--xh-tree-select-row-fg, var(--xh-fg-default));
394
418
  font-size: var(--xh-tree-select-row-font-size, var(--xh-_tree-select-font-size));
@@ -452,7 +476,7 @@
452
476
  align-items: center;
453
477
  justify-content: center;
454
478
  inline-size: var(--xh-tree-select-indicator-size, var(--xh-control-indicator-size));
455
- color: var(--xh-tree-select-item-indicator-fg, var(--xh-_tone, var(--xh-bg-brand)));
479
+ color: var(--xh-tree-select-item-indicator-fg, var(--xh-_tone, var(--xh-fg-brand)));
456
480
  visibility: hidden;
457
481
  }
458
482
 
@@ -513,6 +537,7 @@
513
537
  [data-scope='tree-select'][data-part='branch-content'] {
514
538
  display: flex;
515
539
  flex-direction: column;
540
+ gap: var(--xh-tree-select-branch-content-gap, var(--xh-list-option-gap));
516
541
  padding-inline-start: var(--xh-tree-select-indent, var(--xh-space-4));
517
542
  }
518
543
 
package/css/tree.css CHANGED
@@ -33,6 +33,7 @@
33
33
  [data-scope='tree'][data-part='tree'] {
34
34
  display: flex;
35
35
  flex-direction: column;
36
+ gap: var(--xh-tree-tree-gap, var(--xh-list-option-gap));
36
37
  max-block-size: var(--xh-tree-max-h, var(--xh-viewport-h-lg));
37
38
  padding-block: var(--xh-tree-py, var(--xh-space-1));
38
39
  padding-inline: var(--xh-tree-px, var(--xh-space-1));
@@ -54,8 +55,15 @@
54
55
  outline: none;
55
56
  }
56
57
 
57
- /* 分支只是"这一行 + 它的子层"的外壳,不自带行距与内边距:
58
- 真正长成一行的是 branch-control,子层缩进归 branch-content */
58
+ /* 分支只是"这一行 + 它的子层"的外壳,不自带内边距:
59
+ 真正长成一行的是 branch-control,子层缩进归 branch-content
60
+ 行距由这里出:分支自己那一行与它展开的子层之间,同样按条目间距断开 */
61
+ [data-scope='tree'][data-part='branch'] {
62
+ display: flex;
63
+ flex-direction: column;
64
+ gap: var(--xh-tree-branch-gap, var(--xh-list-option-gap));
65
+ }
66
+
59
67
  [data-scope='tree'][data-part='branch'][hidden] {
60
68
  display: none;
61
69
  }
@@ -78,7 +86,7 @@
78
86
  display: flex;
79
87
  align-items: center;
80
88
  gap: var(--xh-tree-row-gap, var(--xh-control-gap-md));
81
- padding-block: var(--xh-tree-row-py, var(--xh-space-1_5));
89
+ padding-block: var(--xh-tree-row-py, var(--xh-list-option-py-md));
82
90
  padding-inline: var(--xh-tree-row-px, var(--xh-control-px-md));
83
91
  border-radius: var(--xh-tree-row-radius, var(--xh-shape-control));
84
92
  color: var(--xh-tree-row-fg, var(--xh-fg-default));
@@ -93,6 +101,19 @@
93
101
  color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
94
102
  }
95
103
 
104
+ /* 分支行的首格是展开箭头,叶子行没有这一格。作者摆了 item-indicator 时由它顶着,
105
+ 没摆(如勾选档首位直接是 item-checkbox)就由行盒自己补出来,
106
+ 否则叶子会比同级分支往行首缩一格,层级关系读不出来 */
107
+ [data-orientation='vertical'] > [data-scope='tree'][data-part='item']:not(
108
+ :has(> [data-scope='tree'][data-part='item-indicator'])
109
+ ) {
110
+ padding-inline-start: calc(
111
+ var(--xh-tree-row-px, var(--xh-control-px-md)) +
112
+ var(--xh-tree-indicator-size, var(--xh-control-indicator-size)) +
113
+ var(--xh-tree-row-gap, var(--xh-control-gap-md))
114
+ );
115
+ }
116
+
96
117
  [data-scope='tree'][data-part='item'][hidden],
97
118
  [data-scope='tree'][data-part='branch-control'][hidden] {
98
119
  display: none;
@@ -201,7 +222,7 @@
201
222
  align-items: center;
202
223
  justify-content: center;
203
224
  inline-size: var(--xh-tree-indicator-size, var(--xh-control-indicator-size));
204
- color: var(--xh-tree-indicator-fg, var(--xh-bg-brand));
225
+ color: var(--xh-tree-indicator-fg, var(--xh-fg-brand));
205
226
  visibility: hidden;
206
227
  }
207
228
 
@@ -262,9 +283,24 @@
262
283
  [data-scope='tree'][data-part='branch-content'] {
263
284
  display: flex;
264
285
  flex-direction: column;
286
+ gap: var(--xh-tree-branch-content-gap, var(--xh-list-option-gap));
265
287
  padding-inline-start: var(--xh-tree-indent, var(--xh-space-4));
266
288
  }
267
289
 
290
+ /* 末端那一层横排:子节点并排铺开、必要时折行。缩进照旧由子层容器自己顶——
291
+ 那是这一层相对上一层的位置,与层内怎么排无关 */
292
+ [data-scope='tree'][data-part='branch-content'][data-orientation='horizontal'] {
293
+ flex-flow: row wrap;
294
+ align-items: center;
295
+ column-gap: var(--xh-tree-leaf-row-gap, var(--xh-space-3));
296
+ row-gap: var(--xh-tree-branch-content-gap, var(--xh-list-option-gap));
297
+ }
298
+
299
+ /* 横排的一层里节点并排,行盒不能再各自吃满一行 */
300
+ [data-orientation='horizontal'] > [data-scope='tree'][data-part='item'] {
301
+ flex: none;
302
+ }
303
+
268
304
  /* 收起态的唯一开关:display 会盖掉 hidden 属性的 UA 规则,漏了这条整棵子树就收不起来 */
269
305
  [data-scope='tree'][data-part='branch-content'][hidden] {
270
306
  display: none;
@@ -293,4 +329,139 @@
293
329
  -webkit-mask: var(--xh-glyph-mark-check) center / contain no-repeat;
294
330
  mask: var(--xh-glyph-mark-check) center / contain no-repeat;
295
331
  }
332
+
333
+ /* —— 节点拖拽搬家 —— */
334
+ /* 整行都是拖动源,光标换成抓手告诉人这一行按得动。
335
+ 这条不写 touch-action:整行关掉纵向手势,树容器自己就滚不动了;
336
+ 触屏那一路交给下面那块专属把手 */
337
+ [data-scope='tree'][data-part='item'][data-draggable],
338
+ [data-scope='tree'][data-part='branch-control'][data-draggable] {
339
+ cursor: grab;
340
+ }
341
+
342
+ /* 节点拖拽把手:行里的一小块专属拖动区,按下即拖。触屏靠它起手,
343
+ 代价只是这一小块地方不再跟着树滚。整行起手那一路原样保留,把手是叠加的第二个入口。
344
+ touch-action 不在这儿写:连接层按「拖不动就不写」把它写进了内联 style,
345
+ 皮肤再写一遍会盖掉那份条件判断,让不可拖的节点也白白让出滚动 */
346
+ [data-scope='tree'][data-part='node-drag-trigger'] {
347
+ display: inline-flex;
348
+ flex: none;
349
+ align-items: center;
350
+ justify-content: center;
351
+ inline-size: var(--xh-tree-drag-size, var(--xh-control-indicator-size));
352
+ block-size: var(--xh-tree-drag-size, var(--xh-control-indicator-size));
353
+ border-radius: var(--xh-tree-drag-radius, var(--xh-shape-control));
354
+ color: var(--xh-tree-drag-fg, var(--xh-fg-subtle));
355
+ cursor: grab;
356
+ }
357
+
358
+ [data-scope='tree'][data-part='node-drag-trigger'][hidden] {
359
+ display: none;
360
+ }
361
+
362
+ /* 抓手是两条横线:盒子取边框盒,块向两侧的描边就是那两条线,宽高与线宽都走令牌。
363
+ 线的走向与能拖的方向垂直——节点沿块向上下排,画的就是横线。
364
+ 用逻辑属性写,书写模式一换,线跟着排列轴自己转过去。
365
+ :empty 守卫让作者塞进来的图标整个顶掉它,而不是两份叠在一起 */
366
+ [data-scope='tree'][data-part='node-drag-trigger']:empty::after {
367
+ content: '';
368
+ display: block;
369
+ inline-size: var(--xh-tree-drag-grip-long, var(--xh-space-2));
370
+ block-size: var(--xh-tree-drag-grip-short, var(--xh-space-1));
371
+ border-block: var(--xh-stroke-thin) solid currentColor;
372
+ }
373
+
374
+ [data-scope='tree'][data-part='node-drag-trigger']:not([data-disabled]):hover,
375
+ [data-scope='tree'][data-part='node-drag-trigger'][data-dragging] {
376
+ color: var(--xh-tree-drag-fg-active, var(--xh-fg-default));
377
+ }
378
+
379
+ [data-scope='tree'][data-part='node-drag-trigger'][data-dragging] {
380
+ cursor: grabbing;
381
+ }
382
+
383
+ /* 不可拖的节点照样带一个把手,这里保住它的位置、只把它压到禁用色。
384
+ 收成 display: none 是不行的:把手占着行首那一格,藏掉之后同一层里能拖与不能拖的两个节点,
385
+ 文字起点会错开一格,层级关系跟着读歪 */
386
+ [data-scope='tree'][data-part='node-drag-trigger'][data-disabled] {
387
+ color: var(--xh-tree-drag-fg-disabled, var(--xh-fg-disabled));
388
+ cursor: not-allowed;
389
+ }
390
+
391
+ [data-scope='tree'][data-part='node-drag-trigger']:focus-visible {
392
+ outline: var(--xh-ring-width) solid var(--xh-ring-focus);
393
+ outline-offset: var(--xh-ring-offset);
394
+ }
395
+
396
+ /* 被拖的那一行压暗,让人看得出正在搬的是它。这里只动 opacity、cursor 与 user-select,
397
+ 一个 transform 都不写:行原地不动,要落到哪儿全交给落点指示 */
398
+ [data-scope='tree'][data-part='item'][data-dragging],
399
+ [data-scope='tree'][data-part='branch-control'][data-dragging] {
400
+ opacity: var(--xh-tree-dragging-opacity, var(--xh-state-dragging-opacity));
401
+ cursor: grabbing;
402
+ user-select: none;
403
+ }
404
+
405
+ /* 落点指示线:插到哪一行的哪一侧,横线就画在那一行的那条边上。
406
+ 定位上下文只给要画线的那一行:行平时都不定位,缺了它伪元素会一路上溯到最近的定位祖先,
407
+ 线就画到树外面去;写到所有行上则是给每一行都多担一份,而落点同一时刻只有一个。
408
+ 整块高亮那一档不在此列:它不靠伪元素,用不着这层上下文 */
409
+ [data-scope='tree'][data-part='item']:is([data-drop='before'], [data-drop='after']),
410
+ [data-scope='tree'][data-part='branch-control']:is([data-drop='before'], [data-drop='after']) {
411
+ position: relative;
412
+ }
413
+
414
+ /* 线贯穿整行宽度。行自身不收 overflow,线不会被行裁掉;
415
+ 但仍整条画在行内不压着边——压着边画的话,首行那条上沿线会被树容器的圆角与滚动裁掉半条 */
416
+ [data-scope='tree'][data-part='item']:is([data-drop='before'], [data-drop='after'])::after,
417
+ [data-scope='tree'][data-part='branch-control']:is([data-drop='before'], [data-drop='after'])::after {
418
+ content: '';
419
+ position: absolute;
420
+ inset-inline: 0;
421
+ block-size: var(--xh-tree-drop-line, var(--xh-stroke-thick));
422
+ background: var(--xh-tree-drop-fg, var(--xh-border-control-focus));
423
+ }
424
+
425
+ /* 落在上沿还是下沿走逻辑属性,块向跟着书写模式走。
426
+ 换成 box-shadow 的偏移量则是物理的,写不出逻辑方向 */
427
+ [data-scope='tree'][data-part='item'][data-drop='before']::after,
428
+ [data-scope='tree'][data-part='branch-control'][data-drop='before']::after {
429
+ inset-block-start: 0;
430
+ }
431
+
432
+ [data-scope='tree'][data-part='item'][data-drop='after']::after,
433
+ [data-scope='tree'][data-part='branch-control'][data-drop='after']::after {
434
+ inset-block-end: 0;
435
+ }
436
+
437
+ /* 放进这个节点里面:整行淡底加一圈内描边,与上下沿那条横线一眼分得开。
438
+ 描边走零偏移的内投影,四边同时着色、不涉及方向,也跟着行的圆角走。
439
+ 选择器里那条 :not([data-disabled]) 是把特指度补到与悬停那条齐平,再靠排在它之后压过它:
440
+ 指针本来就停在落点这一行上,少了这一段,落点底色会被悬停那档灰盖掉。
441
+ 禁用的节点从来不做落点,这一段因此不会漏画任何一处高亮 */
442
+ [data-scope='tree'][data-part='item'][data-drop='inside']:not([data-disabled]),
443
+ [data-scope='tree'][data-part='branch-control'][data-drop='inside']:not([data-disabled]) {
444
+ background: var(--xh-tree-drop-inside-bg, var(--xh-bg-brand-subtle));
445
+ box-shadow: inset 0 0 0 var(--xh-tree-drop-line, var(--xh-stroke-thick))
446
+ var(--xh-tree-drop-fg, var(--xh-border-control-focus));
447
+ }
448
+
449
+ /* 活动区域只说给读屏听,不占版面。声明与 shared/visually-hidden.ts 逐条同值。 */
450
+ [data-scope='tree'][data-part='live-region'] {
451
+ position: absolute;
452
+ inline-size: 1px;
453
+ block-size: 1px;
454
+ padding: 0;
455
+ margin: -1px;
456
+ overflow: hidden;
457
+ clip-path: inset(50%);
458
+ white-space: nowrap;
459
+ border: 0;
460
+ }
461
+
462
+ /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
463
+ 写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
464
+ [data-scope='tree'][data-part='branch-checkbox'][hidden] {
465
+ display: none;
466
+ }
296
467
  }
@@ -125,7 +125,7 @@
125
125
  padding-inline: var(--xh-typography-code-px, var(--xh-space-1));
126
126
  border-radius: var(--xh-typography-code-radius, var(--xh-shape-inset));
127
127
  background: var(--xh-typography-code-bg, var(--xh-bg-subtle));
128
- font-family: var(--xh-font-family-mono);
128
+ font-family: var(--xh-typography-code-font, var(--xh-font-family-mono));
129
129
  font-size: var(--xh-typography-code-font-size, var(--xh-_typography-code-size));
130
130
  }
131
131
 
package/css/undefined.css CHANGED
@@ -26,6 +26,7 @@
26
26
  xh-menu,
27
27
  xh-menubar,
28
28
  xh-navigation-menu,
29
+ xh-pagination,
29
30
  xh-popconfirm,
30
31
  xh-popover,
31
32
  xh-popselect,
package/index.css CHANGED
@@ -41,6 +41,7 @@
41
41
  @import './css/popselect.css';
42
42
  @import './css/qr-code.css';
43
43
  @import './css/reset.css';
44
+ @import './css/resizable.css';
44
45
  @import './css/result.css';
45
46
  @import './css/segmented.css';
46
47
  @import './css/signature-pad.css';
@@ -94,6 +95,7 @@
94
95
  @import './css/menu.css';
95
96
  @import './css/menubar.css';
96
97
  @import './css/navigation-menu.css';
98
+ @import './css/notification.css';
97
99
  @import './css/number-field.css';
98
100
  @import './css/pagination.css';
99
101
  @import './css/pin-input.css';
@@ -107,6 +109,7 @@
107
109
  @import './css/separator.css';
108
110
  @import './css/side-nav.css';
109
111
  @import './css/slider.css';
112
+ @import './css/sortable.css';
110
113
  @import './css/splitter.css';
111
114
  @import './css/steps.css';
112
115
  @import './css/switch.css';
@@ -118,7 +121,6 @@
118
121
  @import './css/time-field.css';
119
122
  @import './css/time-picker.css';
120
123
  @import './css/toast.css';
121
- @import './css/toaster.css';
122
124
  @import './css/toggle.css';
123
125
  @import './css/toggle-group.css';
124
126
  @import './css/toolbar.css';