@xihan-ui/styles 3.0.0 → 3.2.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 (221) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +1 -1
  3. package/component-tokens.d.ts +29 -0
  4. package/components.tokens.json +683 -27
  5. package/css/alert.css +2 -2
  6. package/css/approval.css +4 -4
  7. package/css/button.css +9 -5
  8. package/css/calendar-picker.css +3 -3
  9. package/css/calendar-range-picker.css +7 -7
  10. package/css/carousel.css +45 -13
  11. package/css/cartesian-chart.css +11 -11
  12. package/css/cascader.css +10 -10
  13. package/css/citation.css +2 -2
  14. package/css/code-view.css +6 -6
  15. package/css/color-picker.css +81 -0
  16. package/css/color-swatch-picker.css +9 -4
  17. package/css/combobox.css +12 -4
  18. package/css/command.css +1 -1
  19. package/css/date-field.css +39 -0
  20. package/css/date-picker.css +86 -9
  21. package/css/date-range-picker.css +47 -7
  22. package/css/diff-view.css +8 -8
  23. package/css/field-array.css +1 -1
  24. package/css/field.css +4 -0
  25. package/css/file-upload.css +1 -1
  26. package/css/float-button.css +140 -27
  27. package/css/form.css +14 -6
  28. package/css/graph-chart.css +2 -2
  29. package/css/highlight.css +1 -1
  30. package/css/image.css +1 -1
  31. package/css/mention.css +1 -1
  32. package/css/message-feed.css +1 -1
  33. package/css/notification.css +26 -20
  34. package/css/number-field.css +18 -18
  35. package/css/page-header.css +2 -2
  36. package/css/password-input.css +2 -2
  37. package/css/popconfirm.css +3 -3
  38. package/css/question-flow.css +8 -8
  39. package/css/radar-chart.css +6 -6
  40. package/css/rating.css +1 -1
  41. package/css/select.css +2 -2
  42. package/css/separator.css +2 -2
  43. package/css/side-nav.css +13 -13
  44. package/css/skeleton.css +5 -5
  45. package/css/slider.css +6 -6
  46. package/css/sortable.css +2 -2
  47. package/css/table.css +19 -2
  48. package/css/tags-input.css +1 -1
  49. package/css/time-picker.css +59 -2
  50. package/css/tool-call.css +7 -7
  51. package/css/tooltip.css +1 -1
  52. package/css/tree-select.css +2 -2
  53. package/css/tree.css +81 -11
  54. package/dist/css/accordion.css +269 -0
  55. package/dist/css/affix.css +47 -0
  56. package/dist/css/alert.css +247 -0
  57. package/dist/css/anchor.css +252 -0
  58. package/dist/css/approval.css +501 -0
  59. package/dist/css/avatar-group.css +99 -0
  60. package/dist/css/avatar.css +98 -0
  61. package/dist/css/back-top.css +161 -0
  62. package/dist/css/badge.css +205 -0
  63. package/dist/css/bar-code.css +62 -0
  64. package/dist/css/breadcrumb.css +230 -0
  65. package/dist/css/button-group.css +263 -0
  66. package/dist/css/button.css +219 -0
  67. package/dist/css/calendar-picker.css +467 -0
  68. package/dist/css/calendar-range-picker.css +554 -0
  69. package/dist/css/card.css +221 -0
  70. package/dist/css/carousel.css +710 -0
  71. package/dist/css/cartesian-chart.css +830 -0
  72. package/dist/css/cascader.css +961 -0
  73. package/dist/css/checkbox-group.css +358 -0
  74. package/dist/css/checkbox.css +257 -0
  75. package/dist/css/citation.css +470 -0
  76. package/dist/css/clipboard.css +315 -0
  77. package/dist/css/code-view.css +374 -0
  78. package/dist/css/collapsible.css +185 -0
  79. package/dist/css/color-field.css +176 -0
  80. package/dist/css/color-picker.css +595 -0
  81. package/dist/css/color-slider.css +281 -0
  82. package/dist/css/color-swatch-picker.css +250 -0
  83. package/dist/css/color-swatch.css +35 -0
  84. package/dist/css/combobox.css +574 -0
  85. package/dist/css/command.css +399 -0
  86. package/dist/css/context-menu.css +420 -0
  87. package/dist/css/date-field.css +317 -0
  88. package/dist/css/date-picker.css +868 -0
  89. package/dist/css/date-range-picker.css +886 -0
  90. package/dist/css/description.css +67 -0
  91. package/dist/css/descriptions.css +299 -0
  92. package/dist/css/dialog.css +455 -0
  93. package/dist/css/diff-view.css +513 -0
  94. package/dist/css/download-trigger.css +151 -0
  95. package/dist/css/drawer.css +552 -0
  96. package/dist/css/editable.css +295 -0
  97. package/dist/css/empty-state.css +163 -0
  98. package/dist/css/field-array.css +226 -0
  99. package/dist/css/field.css +166 -0
  100. package/dist/css/fieldset.css +102 -0
  101. package/dist/css/file-upload.css +429 -0
  102. package/dist/css/flex.css +441 -0
  103. package/dist/css/float-button.css +569 -0
  104. package/dist/css/floating-panel.css +429 -0
  105. package/dist/css/focus.css +46 -0
  106. package/dist/css/forced-colors.css +93 -0
  107. package/dist/css/form.css +393 -0
  108. package/dist/css/funnel-chart.css +106 -0
  109. package/dist/css/graph-chart.css +205 -0
  110. package/dist/css/grid-list.css +235 -0
  111. package/dist/css/grid.css +1201 -0
  112. package/dist/css/heatmap.css +552 -0
  113. package/dist/css/hierarchy-chart.css +298 -0
  114. package/dist/css/highlight.css +41 -0
  115. package/dist/css/hover-card.css +226 -0
  116. package/dist/css/icon.css +225 -0
  117. package/dist/css/image-cropper.css +373 -0
  118. package/dist/css/image-viewer.css +538 -0
  119. package/dist/css/image.css +98 -0
  120. package/dist/css/infinite-scroll.css +77 -0
  121. package/dist/css/input-group.css +275 -0
  122. package/dist/css/json-viewer.css +379 -0
  123. package/dist/css/kbd.css +72 -0
  124. package/dist/css/label.css +78 -0
  125. package/dist/css/layers.css +7 -0
  126. package/dist/css/layout.css +372 -0
  127. package/dist/css/liquid.css +106 -0
  128. package/dist/css/list.css +152 -0
  129. package/dist/css/listbox.css +390 -0
  130. package/dist/css/loading-bar.css +141 -0
  131. package/dist/css/log.css +306 -0
  132. package/dist/css/markdown-stream.css +149 -0
  133. package/dist/css/marquee.css +378 -0
  134. package/dist/css/masonry.css +70 -0
  135. package/dist/css/matrix-code.css +67 -0
  136. package/dist/css/mention.css +393 -0
  137. package/dist/css/menu.css +364 -0
  138. package/dist/css/menubar.css +456 -0
  139. package/dist/css/message-feed.css +318 -0
  140. package/dist/css/navigation-menu.css +513 -0
  141. package/dist/css/notification.css +782 -0
  142. package/dist/css/number-animation.css +44 -0
  143. package/dist/css/number-field.css +252 -0
  144. package/dist/css/overlay-arrow.css +56 -0
  145. package/dist/css/page-header.css +184 -0
  146. package/dist/css/pagination.css +450 -0
  147. package/dist/css/password-input.css +391 -0
  148. package/dist/css/pie-chart.css +247 -0
  149. package/dist/css/pin-input.css +199 -0
  150. package/dist/css/pointer.css +36 -0
  151. package/dist/css/popconfirm.css +320 -0
  152. package/dist/css/popover.css +279 -0
  153. package/dist/css/progress.css +501 -0
  154. package/dist/css/prompt-input.css +260 -0
  155. package/dist/css/question-flow.css +553 -0
  156. package/dist/css/radar-chart.css +233 -0
  157. package/dist/css/radio-group.css +598 -0
  158. package/dist/css/rating.css +294 -0
  159. package/dist/css/reasoning.css +343 -0
  160. package/dist/css/reset.css +117 -0
  161. package/dist/css/resizable.css +242 -0
  162. package/dist/css/sankey-chart.css +174 -0
  163. package/dist/css/scroll-area.css +240 -0
  164. package/dist/css/scrollbar.css +204 -0
  165. package/dist/css/select.css +612 -0
  166. package/dist/css/separator.css +122 -0
  167. package/dist/css/side-nav.css +476 -0
  168. package/dist/css/signature-pad.css +179 -0
  169. package/dist/css/skeleton.css +161 -0
  170. package/dist/css/slider.css +374 -0
  171. package/dist/css/sortable.css +228 -0
  172. package/dist/css/sparkline.css +164 -0
  173. package/dist/css/spinner.css +236 -0
  174. package/dist/css/splitter.css +159 -0
  175. package/dist/css/statistic.css +137 -0
  176. package/dist/css/steps.css +627 -0
  177. package/dist/css/switch.css +351 -0
  178. package/dist/css/table.css +1145 -0
  179. package/dist/css/tabs.css +944 -0
  180. package/dist/css/tag-group.css +247 -0
  181. package/dist/css/tag.css +310 -0
  182. package/dist/css/tags-input.css +322 -0
  183. package/dist/css/text-field.css +197 -0
  184. package/dist/css/time-field.css +277 -0
  185. package/dist/css/time-picker.css +707 -0
  186. package/dist/css/time-range-picker.css +746 -0
  187. package/dist/css/timeline.css +423 -0
  188. package/dist/css/timer.css +123 -0
  189. package/dist/css/timestamp.css +34 -0
  190. package/dist/css/toggle-group.css +424 -0
  191. package/dist/css/toggle.css +146 -0
  192. package/dist/css/tone.css +189 -0
  193. package/dist/css/tool-call.css +429 -0
  194. package/dist/css/toolbar.css +365 -0
  195. package/dist/css/tooltip.css +218 -0
  196. package/dist/css/tour.css +439 -0
  197. package/dist/css/transfer.css +638 -0
  198. package/dist/css/tree-select.css +878 -0
  199. package/dist/css/tree.css +733 -0
  200. package/dist/css/truncate.css +108 -0
  201. package/dist/css/typography.css +472 -0
  202. package/dist/css/undefined.css +58 -0
  203. package/dist/css/virtualizer.css +166 -0
  204. package/dist/css/visually-hidden.css +20 -0
  205. package/dist/css/watermark.css +82 -0
  206. package/dist/family/action-control.css +487 -0
  207. package/dist/family/chart.css +480 -0
  208. package/dist/family/check-mark.css +94 -0
  209. package/dist/family/choice-card.css +97 -0
  210. package/dist/family/collection-item.css +764 -0
  211. package/dist/family/field-chrome.css +287 -0
  212. package/dist/family/loading-ring.css +95 -0
  213. package/dist/family/material.css +72 -0
  214. package/dist/family/menu-choice.css +56 -0
  215. package/dist/family/motion.css +363 -0
  216. package/dist/family/swatch.css +59 -0
  217. package/dist/family/tag-list.css +59 -0
  218. package/family/action-control.css +3 -12
  219. package/index.css +7307 -6759
  220. package/index.unlayered.css +7309 -6761
  221. package/package.json +165 -164
@@ -0,0 +1,878 @@
1
+ /*
2
+ * Copyright (c) 2021-Present XiHanFun and contributors.
3
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
4
+ */
5
+
6
+ /* TreeSelect 独立皮肤同时传递引入字段视觉盒、字段内动作与浮层集合行;full bundle 递归去重。 */
7
+ @import '../family/field-chrome.css';
8
+ @import '../family/action-control.css';
9
+ @import '../family/collection-item.css';
10
+ @import '../family/loading-ring.css';
11
+
12
+ /* 共享关键帧由 family/motion.css 提供,本皮肤 @import 它,单独引入仍成立。 */
13
+ @import '../family/motion.css';
14
+ @import '../family/material.css';
15
+ @import '../family/tag-list.css';
16
+
17
+ @layer xihan.components {
18
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
19
+ .xh-scope-tree-select {
20
+ --xh-tree-select-skin: 1;
21
+ }
22
+
23
+ /* 坐标由定位引擎写进 style(inset-inline-start / inset-block-start),这里只定位模式与层级 */
24
+ .xh-scope-tree-select[data-part='positioner'] {
25
+ /* 落定那一侧的可用高度,由定位引擎经内联自定义属性写进来,内容层继承它限高;
26
+ 引擎没算(尚未落位 / 无引擎)时不额外限高 */
27
+ --xh-_tree-select-available-h: 100vh;
28
+ /* 落定那一侧的可用宽度,同样由定位引擎经内联自定义属性写进来,行内轴据此夹取;
29
+ 引擎没算(尚未落位 / 无引擎 / 贴边归零)时退到视口宽 */
30
+ --xh-_tree-select-available-w: 100vw;
31
+ /* 字段盒实测宽度,由定位引擎经内联自定义属性写进来,内容层与它等宽;
32
+ 引擎没算(尚未落位 / 无引擎)时为 0,面板取下界 */
33
+ --xh-_tree-select-anchor-w: 0px;
34
+ /* 独立浮层先截断祖先方向,再按自身 placement 开启一侧。 */
35
+ --xh-_overlay-enter-up: 0;
36
+ --xh-_overlay-enter-down: 0;
37
+ --xh-_overlay-enter-left: 0;
38
+ --xh-_overlay-enter-right: 0;
39
+
40
+ /* 树的自绘条浮在内容之上:轨道不上底色,实色轨道会沿内容边缘糊出一条灰带 */
41
+ --xh-scrollbar-track-bg: transparent;
42
+
43
+ position: fixed;
44
+ z-index: var(--xh-tree-select-layer, var(--xh-_layer, var(--xh-layer-popover)));
45
+ /* 空壳不吃指针,交互只发生在 content 里 */
46
+ pointer-events: none;
47
+ }
48
+
49
+ /* 锚点被滚出可视区:整个浮层随之收起 */
50
+ .xh-scope-tree-select[data-part='positioner'][data-hidden] {
51
+ visibility: hidden;
52
+ }
53
+
54
+ /* 位移按实际落位的物理方向给,不随书写方向翻转。 */
55
+ .xh-scope-tree-select[data-part='positioner'][data-placement^='top'] {
56
+ --xh-_overlay-enter-down: 1;
57
+ }
58
+
59
+ .xh-scope-tree-select[data-part='positioner'][data-placement^='bottom'] {
60
+ --xh-_overlay-enter-up: 1;
61
+ }
62
+
63
+ .xh-scope-tree-select[data-part='positioner'][data-placement^='left'] {
64
+ --xh-_overlay-enter-right: 1;
65
+ }
66
+
67
+ .xh-scope-tree-select[data-part='positioner'][data-placement^='right'] {
68
+ --xh-_overlay-enter-left: 1;
69
+ }
70
+
71
+ /* 私有槽同时声明在根与 positioner 上:浮层被搬到 portal 落点,不是根的后代,继承不过去 */
72
+ .xh-scope-tree-select:is([data-part='root'], [data-part='positioner']) {
73
+ /* 作者塞进触发器指示符槽 / 清除钮的图标跟着尺寸档走,与皮肤画的兜底字形同一把尺。这支只管作者放进
74
+ 盒与行里的图标:面板里自绘的状态字形(展开方向、行尾对号与半选杠)是指示符,各部件在自己身上
75
+ 把 --xh-icon-size 改接到 --xh-control-indicator-* 一族的盒尺 */
76
+ --xh-icon-size: var(--xh-tree-select-icon-size, var(--xh-glyph-size-md));
77
+
78
+ /* 尺寸档只换这几个私有槽,盒与树里的行都从这两处继承它们,换档不必给每个部件各写一条选择器;
79
+ 形态三档由家族按 control 上的 data-variant 生成,浮层与树不跟着变,皮肤不再声明 */
80
+ --xh-_tree-select-h: var(--xh-control-h-md);
81
+ --xh-_tree-select-px: var(--xh-control-px-md);
82
+ --xh-_tree-select-row-py: var(--xh-list-option-py-md);
83
+ --xh-_tree-select-row-px: var(--xh-control-px-md);
84
+ --xh-_tree-select-gap: var(--xh-control-gap-md);
85
+ --xh-_tree-select-font-size: var(--xh-control-font-md);
86
+
87
+ /* 强调色随语气走,只落在勾选标记上;没写 data-tone 时退回品牌色 */
88
+ --xh-_tree-select-accent: var(--xh-_tone, var(--xh-fg-brand));
89
+ }
90
+
91
+ /* 标签一行、盒一行的两行堆叠 */
92
+ .xh-scope-tree-select[data-part='root'] {
93
+ display: inline-flex;
94
+ flex-direction: column;
95
+ gap: var(--xh-tree-select-gap, var(--xh-space-1));
96
+
97
+ /* 不传尺寸时一律这么宽,宽度不随内容走;父容器给不出这么宽时整件跟着收,地板同步让步,不越出父容器。
98
+ 地板不高过缺省宽:使用者把缺省宽钉到底线以下时不必再放开底线 */
99
+ inline-size: var(--xh-tree-select-control-w, var(--xh-control-w));
100
+ min-inline-size: min(var(--xh-tree-select-control-w, var(--xh-control-w)), var(--xh-tree-select-control-min-w, var(--xh-control-min-w)), 100%);
101
+ max-inline-size: 100%;
102
+ }
103
+
104
+ /* 只要声明了 display 就盖掉了 UA 的 [hidden]{display:none},作者手动收起时要自己还回去 */
105
+ .xh-scope-tree-select[data-part='root'][hidden] {
106
+ display: none;
107
+ }
108
+
109
+ /* —— 尺寸 —— */
110
+ /* 缺省档写在上面的基础规则里 */
111
+ .xh-scope-tree-select:is([data-part='root'], [data-part='positioner'])[data-size='sm'] {
112
+ --xh-icon-size: var(--xh-tree-select-icon-size, var(--xh-glyph-size-sm));
113
+ --xh-_tree-select-h: var(--xh-control-h-sm);
114
+ --xh-_tree-select-px: var(--xh-control-px-sm);
115
+ --xh-_tree-select-row-py: var(--xh-list-option-py-sm);
116
+ --xh-_tree-select-row-px: var(--xh-control-px-sm);
117
+ --xh-_tree-select-gap: var(--xh-control-gap-sm);
118
+ --xh-_tree-select-font-size: var(--xh-control-font-sm);
119
+ }
120
+
121
+ .xh-scope-tree-select:is([data-part='root'], [data-part='positioner'])[data-size='lg'] {
122
+ --xh-icon-size: var(--xh-tree-select-icon-size, var(--xh-glyph-size-lg));
123
+ --xh-_tree-select-h: var(--xh-control-h-lg);
124
+ --xh-_tree-select-px: var(--xh-control-px-lg);
125
+ --xh-_tree-select-row-py: var(--xh-list-option-py-lg);
126
+ --xh-_tree-select-row-px: var(--xh-control-px-lg);
127
+ --xh-_tree-select-gap: var(--xh-control-gap-lg);
128
+ --xh-_tree-select-font-size: var(--xh-control-font-lg);
129
+ }
130
+
131
+ .xh-scope-tree-select[data-part='label'] {
132
+ color: var(--xh-tree-select-label-fg, var(--xh-fg-default));
133
+ font-size: var(--xh-tree-select-label-font-size, var(--xh-text-label-size));
134
+ font-weight: var(--xh-tree-select-label-font-weight, var(--xh-text-label-weight));
135
+ line-height: var(--xh-leading-none);
136
+ }
137
+
138
+ /* 整个控件禁用会把 data-disabled 一路打到 label / value-text / indicator 上,各处观感保持一致 */
139
+ .xh-scope-tree-select[data-part='label'][data-disabled] {
140
+ color: var(--xh-fg-subtle);
141
+ }
142
+
143
+ /* 盒:描边、底色、圆角、控件高度、行内内衬、聚焦环、五态与悬停由 Field Chrome 家族画在这一层,
144
+ 触发按钮与清空按钮在里面并排;Tab 停靠点是盒里的 trigger(展开后才移进树里),环由家族的
145
+ :focus-within 画在盒上。组件只映射既有公开槽(shadow 缺省 none:字段静息描边式、无影);盒里是按钮 */
146
+ .xh-scope-tree-select[data-part='control'] {
147
+ --xh-field-control-height: var(--xh-tree-select-control-h, var(--xh-_tree-select-h));
148
+ --xh-field-control-padding-inline: var(--xh-tree-select-control-px, var(--xh-_tree-select-px));
149
+ --xh-field-control-gap: var(--xh-tree-select-control-gap, var(--xh-_tree-select-gap));
150
+ --xh-field-control-min-inline-size: var(--xh-tree-select-control-min-w, var(--xh-control-min-w));
151
+ --xh-field-control-radius: var(--xh-tree-select-control-radius, var(--xh-shape-control));
152
+ --xh-field-bg-rest: var(--xh-tree-select-control-bg, var(--xh-_field-variant-bg-rest));
153
+ --xh-field-bg-hover: var(--xh-tree-select-control-bg-hover, var(--xh-_field-variant-bg-hover));
154
+ --xh-field-bg-read-only: var(--xh-tree-select-control-bg-readonly, var(--xh-_field-variant-bg-read-only));
155
+ --xh-field-bg-disabled: var(--xh-tree-select-control-bg-disabled, var(--xh-_field-variant-bg-disabled));
156
+ --xh-field-fg-rest: var(--xh-tree-select-control-fg, var(--xh-fg-default));
157
+ --xh-field-border-rest: var(--xh-tree-select-control-border, var(--xh-_field-variant-border-rest));
158
+ --xh-field-border-hover: var(--xh-tree-select-control-border-hover, var(--xh-_field-variant-border-hover));
159
+ --xh-field-border-focus: var(--xh-tree-select-control-border-focus, var(--xh-_field-variant-border-focus));
160
+ --xh-field-border-invalid: var(--xh-tree-select-control-border-invalid, var(--xh-_field-variant-border-invalid));
161
+ --xh-field-ring-focus: var(--xh-ring-focus);
162
+ --xh-field-ring-invalid: var(--xh-ring-invalid);
163
+ --xh-field-shadow-rest: var(--xh-tree-select-control-shadow, none);
164
+ --xh-field-cursor-rest: pointer;
165
+ /* 家族 chrome 会重写 --xh-icon-size,使用者图标槽必须经桥接槽下发才能在盒内生效 */
166
+ --xh-field-glyph-size: var(--xh-tree-select-icon-size, var(--xh-_field-size-glyph-size));
167
+ }
168
+
169
+ .xh-scope-tree-select[data-part='control'][hidden] {
170
+ display: none;
171
+ }
172
+
173
+ /* 盒内那颗可聚焦的按钮:不画描边不铺底也不自带高度,只占满剩余宽度、排布回显与箭头 */
174
+ .xh-scope-tree-select[data-part='trigger'] {
175
+ display: inline-flex;
176
+ flex: 1 1 auto;
177
+ align-items: center;
178
+ justify-content: space-between;
179
+ gap: var(--xh-tree-select-trigger-gap, var(--xh-_tree-select-gap));
180
+ min-inline-size: 0;
181
+ padding: 0;
182
+ border: 0;
183
+ background: transparent;
184
+ color: var(--xh-tree-select-trigger-fg, var(--xh-fg-default));
185
+ font-family: inherit;
186
+ font-size: var(--xh-tree-select-trigger-font-size, var(--xh-_tree-select-font-size));
187
+ line-height: var(--xh-leading-none);
188
+ text-align: start;
189
+ cursor: pointer;
190
+ }
191
+
192
+ .xh-scope-tree-select[data-part='trigger'][hidden] {
193
+ display: none;
194
+ }
195
+
196
+ /* trigger 是单体控件,用原生 disabled(树里的集合条目一律 aria-disabled,写 :disabled 永不命中) */
197
+ .xh-scope-tree-select[data-part='trigger']:disabled {
198
+ color: var(--xh-fg-disabled);
199
+ }
200
+
201
+ /* 多选时值会连成很长一串,必须能截断;框宽由盒定,这里得允许自己被压缩 */
202
+ .xh-scope-tree-select[data-part='value-text'] {
203
+ flex: 1 1 auto;
204
+ min-inline-size: 0;
205
+ overflow: hidden;
206
+ /* 行高留出文字的上下伸展空间,本行那层 overflow:hidden 才不会把字削掉;
207
+ 触发框自带固定高度,抬行高不改变几何 */
208
+ line-height: var(--xh-tree-select-value-leading, var(--xh-leading-normal));
209
+ white-space: nowrap;
210
+ text-overflow: ellipsis;
211
+ }
212
+
213
+ /* 无选中:显示的是 placeholder,画淡一档 */
214
+ .xh-scope-tree-select[data-part='value-text'][data-placeholder] {
215
+ color: var(--xh-tree-select-placeholder-fg, var(--xh-fg-subtle));
216
+ }
217
+
218
+ .xh-scope-tree-select[data-part='value-text'][data-disabled] {
219
+ color: var(--xh-fg-disabled);
220
+ }
221
+
222
+ /* 标签行:触发器里收着可见标签与 +N 那一枚的一行,行里每一枚都是 tag(data-scope="tag"),样子归 tag.css;
223
+ 行怎么排、标签怎么进出归标签行家族配方(family/tag-list.css),这里只把使用者的间距槽接进去 */
224
+ .xh-scope-tree-select[data-part='tag-list'] {
225
+ --xh-tag-list-gap: var(--xh-tree-select-tag-list-gap, var(--xh-space-1));
226
+ }
227
+
228
+ /* 标签行露面时 value-text 让位:两者是触发器里的同一格,占位文字与标签不同屏。
229
+ value-text 留在 DOM 里,trigger 的可及名仍从它取到完整的选中项文本 */
230
+ .xh-scope-tree-select[data-part='trigger']:has([data-part='tag-list']:not([hidden])) [data-part='value-text']:where(.xh-scope-tree-select) {
231
+ display: none;
232
+ }
233
+
234
+ /* 有值时清空钮顶上来,箭头让位:两个图标并排堆着,用户分不清点哪个。
235
+ 判据查的是盒里此刻真有一颗没收起的清空钮,不是「有没有值」——
236
+ 作者没摆清空钮时箭头照常留着,不然让了位没人接,指示符整个消失 */
237
+ .xh-scope-tree-select[data-part='control']:has([data-part='clear-trigger']:not([hidden])) [data-part='indicator']:where(.xh-scope-tree-select) {
238
+ display: none;
239
+ }
240
+
241
+ .xh-scope-tree-select[data-part='indicator'] {
242
+ display: inline-flex;
243
+ flex: none;
244
+ align-items: center;
245
+ justify-content: center;
246
+ color: var(--xh-tree-select-indicator-fg, var(--xh-fg-muted));
247
+ transition: rotate var(--xh-motion-duration-nudge) var(--xh-motion-ease-enter-strong);
248
+ }
249
+
250
+ .xh-scope-tree-select[data-part='indicator'][hidden] {
251
+ display: none;
252
+ }
253
+
254
+ .xh-scope-tree-select[data-part='indicator'][data-state='open'] {
255
+ rotate: 180deg;
256
+ }
257
+
258
+ .xh-scope-tree-select[data-part='indicator'][data-disabled] {
259
+ color: var(--xh-fg-disabled);
260
+ }
261
+
262
+ /* 盒内靠右的小方钮,不撑高那一行:正方视觉盒、inset 圆角、悬停 100 / 按下 200 与 0.97 按压、粗指针热区与
263
+ :focus-visible 关环(盒的 :focus-within 已画了一圈)全由 Action Control 的 field-inset ghost 档给,
264
+ 组件只映射既有覆盖槽 */
265
+ .xh-scope-tree-select[data-part='clear-trigger'] {
266
+ --xh-action-visual-size: var(--xh-tree-select-action-size, var(--xh-_action-profile-visual-size));
267
+ --xh-action-min-inline-size: var(--xh-tree-select-action-size, var(--xh-_action-profile-visual-size));
268
+ --xh-action-radius: var(--xh-tree-select-action-radius, var(--xh-shape-inset));
269
+ /* 底色阶梯由 ghost 档给(透明 → 100 → 200),使用者槽只作覆盖入口 */
270
+ --xh-action-bg-rest: var(--xh-tree-select-action-bg, var(--xh-_action-variant-bg-rest));
271
+ --xh-action-bg-hover: var(--xh-tree-select-action-bg-hover, var(--xh-_action-variant-bg-hover));
272
+ --xh-action-bg-pressed: var(--xh-tree-select-action-bg-active, var(--xh-_action-variant-bg-pressed));
273
+ --xh-action-fg-rest: var(--xh-tree-select-action-fg, var(--xh-fg-muted));
274
+ --xh-action-fg-hover: var(--xh-tree-select-action-fg-hover, var(--xh-fg-default));
275
+ --xh-action-border-rest: transparent;
276
+ --xh-action-highlight-rest: transparent;
277
+ --xh-action-shadow-rest: none;
278
+ --xh-action-shadow-hover: none;
279
+ --xh-action-shadow-pressed: none;
280
+ --xh-action-font-size: var(--xh-tree-select-action-font-size, var(--xh-text-secondary-size));
281
+ /* 配方尚未把 profile 字形档灌进 --xh-icon-size,钮内字形先按 field-inset 档逐钮取值 */
282
+ --xh-icon-size: var(--xh-_action-profile-glyph-size);
283
+
284
+ border-width: 0;
285
+ }
286
+
287
+ /* 没值时连接层给的是 hidden 属性;家族那条 display 会把 UA 规则盖掉 */
288
+ .xh-scope-tree-select[data-part='clear-trigger'][hidden] {
289
+ display: none;
290
+ }
291
+
292
+ .xh-scope-tree-select[data-part='content'] {
293
+ /* 材质由家族配方画(family/material.css 的 frosted 面:描边、底、1px 顶光、前景、投影与背景滤镜),
294
+ 这里只把使用者槽接进来 */
295
+ --xh-frosted-bg: var(--xh-tree-select-content-bg, var(--xh-_material-bg));
296
+ --xh-frosted-border: var(--xh-tree-select-content-border, var(--xh-_material-border));
297
+ --xh-frosted-fg: var(--xh-tree-select-content-fg, var(--xh-_material-fg));
298
+ --xh-frosted-shadow: var(--xh-tree-select-content-shadow, var(--xh-_material-shadow));
299
+ --xh-frosted-backdrop: var(--xh-tree-select-content-backdrop, var(--xh-_material-backdrop));
300
+ --xh-frosted-highlight: var(--xh-tree-select-content-highlight, var(--xh-_material-highlight));
301
+
302
+ position: relative;
303
+ display: flex;
304
+ flex-direction: column;
305
+ /* 列表型浮层与字段盒等宽:长选项在条目里截断,面板不随最长的一条变宽。锚点比下界还窄时取下界,
306
+ 比可用区还宽时收成可用宽度;要封顶由作者另写上界槽 */
307
+ inline-size: min(
308
+ max(var(--xh-tree-select-content-min-w, var(--xh-overlay-menu-min-w)), var(--xh-_tree-select-anchor-w)),
309
+ var(--xh-_tree-select-available-w)
310
+ );
311
+ max-inline-size: var(--xh-tree-select-content-max-w, none);
312
+ max-block-size: min(var(--xh-tree-select-content-max-h, var(--xh-overlay-menu-max-h)), var(--xh-_tree-select-available-h));
313
+ padding-block: var(--xh-tree-select-content-py, var(--xh-space-1));
314
+ padding-inline: var(--xh-tree-select-content-px, var(--xh-space-1));
315
+ border-radius: var(--xh-tree-select-content-radius, var(--xh-shape-overlay));
316
+ /* 面板只是外壳,滚动归树:搜索框与底部操作区因此钉在树的上下沿,不随行滚走。
317
+ 行的悬停底色是方角,滚到两端时会探出外壳的圆角 */
318
+ overflow: hidden;
319
+ pointer-events: auto;
320
+ }
321
+
322
+ /* 这里刻意没有 [data-part='content'][hidden] { display: none },与 dialog 一致:
323
+ 收起态连接层会给 content 打 hidden,而上面那条 display 正是要盖掉 UA 的
324
+ [hidden]{display:none}——退场动画得先能播。presence 读的是 content 的 animationName,
325
+ 真正的收起由宿主在退场结束后落成内联 display:none(Vue 那边直接不渲染)。
326
+ 其余声明了 display 的角色节点仍补 [hidden],那几处没有退场动画。 */
327
+
328
+ /* 容器只是焦点域的兜底落点,落焦不画环:高亮永远长在行上 */
329
+ .xh-scope-tree-select[data-part='content']:focus-visible {
330
+ outline: none;
331
+ }
332
+
333
+ /* 挂载时就开着的那一段(data-instant)属于首帧,直接呈现 */
334
+ .xh-scope-tree-select[data-part='content'][data-state='open']:not([data-instant]) {
335
+ animation: xh-overlay-slide-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong);
336
+ }
337
+
338
+ /* 退场:收起那一帧 hidden 由退场闸门押后,这里才播得出来。forwards 把末态钉住,
339
+ 免得动画结束到真收起之间闪一下原样 */
340
+ .xh-scope-tree-select[data-part='content'][data-state='closed'] {
341
+ animation: xh-overlay-slide-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
342
+ }
343
+
344
+ /* 边框与底色归 content,树只管滚动并把行竖着排开。
345
+ 两轴都滚:深层节点靠缩进往行末推,横向溢出是常态,得够得着。
346
+ min-block-size: 0 是弹性子项能真正滚动的前提——不给的话它按内容撑高,
347
+ 外壳的 max-block-size 就只会把溢出的部分裁掉而不是交给它滚 */
348
+ .xh-scope-tree-select[data-part='tree'] {
349
+ display: flex;
350
+ flex: 1 1 auto;
351
+ flex-direction: column;
352
+ gap: var(--xh-tree-select-tree-gap, var(--xh-list-option-gap));
353
+ min-block-size: 0;
354
+ overflow: auto;
355
+ /* 浮层滚动面:滚到头不把页面一起带走 */
356
+ overscroll-behavior: contain;
357
+ transition: opacity var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
358
+ }
359
+
360
+ /* 刷新:已有节点时后台在取,保留上一帧,树按 micro 淡下,数据到了再淡回;在途占位此时让位 */
361
+ .xh-scope-tree-select[data-part='tree'][aria-busy='true'] {
362
+ opacity: var(--xh-state-disabled-opacity);
363
+ }
364
+
365
+ .xh-scope-tree-select[data-part='tree'][hidden] {
366
+ display: none;
367
+ }
368
+
369
+ /* 浮层内搜索框:排在树上方,框自己不画边不画底,只在底下画一道分隔线把它与树分开;边界归面板 */
370
+ /* 面板内嵌的搜索框:通栏一行,控件高与字号随尺寸档,只画一道面内分隔的下划线(取面材质的分隔令牌);
371
+ 重置与占位前景由字段家族按 data-xh-field-input 给,占位与值文本的占位同一支组件槽 */
372
+ .xh-scope-tree-select[data-part='input'] {
373
+ --xh-field-placeholder-fg: var(--xh-tree-select-placeholder-fg, var(--xh-fg-subtle));
374
+
375
+ flex: none;
376
+ min-inline-size: 0;
377
+ block-size: var(--xh-tree-select-input-h, var(--xh-_tree-select-h));
378
+ margin-block-end: var(--xh-tree-select-input-gap, var(--xh-space-1));
379
+ padding-block: 0;
380
+ padding-inline: var(--xh-tree-select-input-px, var(--xh-_tree-select-px));
381
+ border: none;
382
+ border-block-end: var(--xh-stroke-thin) solid var(--xh-tree-select-search-divider, var(--xh-material-frosted-separator));
383
+ background: none;
384
+ color: inherit;
385
+ font-family: inherit;
386
+ font-size: var(--xh-tree-select-input-font-size, var(--xh-_tree-select-font-size));
387
+ line-height: var(--xh-leading-normal);
388
+ }
389
+
390
+ /* 聚焦不画环:插入符就是焦点指示。框没有外壳,全局那圈键盘焦点环只会压在通栏一行上 */
391
+ .xh-scope-tree-select[data-part='input']:focus-visible {
392
+ outline: none;
393
+ }
394
+
395
+ .xh-scope-tree-select[data-part='input'][hidden] {
396
+ display: none;
397
+ }
398
+
399
+ /* 自动填充:引擎给填过的框强加一套系统色,盖得过 background 与 color。
400
+ 底改用 inset 阴影铺回来,字改用 -webkit-text-fill-color 接回来;
401
+ 两个选择器名分写两条,一条列表里只要有一个名字不被认识整条就被丢弃。
402
+ 搜索框排在浮层面里,铺的底取浮起面而不是页面底 */
403
+ .xh-scope-tree-select[data-part='input']:autofill {
404
+ box-shadow: inset 0 0 0 100vmax var(--xh-tree-select-input-autofill-bg, var(--xh-bg-surface));
405
+ -webkit-text-fill-color: var(--xh-tree-select-input-autofill-fg, var(--xh-fg-default));
406
+ }
407
+
408
+ .xh-scope-tree-select[data-part='input']:-webkit-autofill {
409
+ box-shadow: inset 0 0 0 100vmax var(--xh-tree-select-input-autofill-bg, var(--xh-bg-surface));
410
+ -webkit-text-fill-color: var(--xh-tree-select-input-autofill-fg, var(--xh-fg-default));
411
+ }
412
+
413
+ /* 空态占位:待在 content 里、tree 的兄弟(role=tree 只许拥有 treeitem 与 group)。
414
+ 盒与阴影归 content,这里只画一句居中的次要文字 */
415
+ .xh-scope-tree-select[data-part='empty'] {
416
+ display: block;
417
+ flex: none;
418
+ padding-block: var(--xh-tree-select-empty-py, var(--xh-space-3));
419
+ padding-inline: var(--xh-tree-select-empty-px, var(--xh-_tree-select-row-px));
420
+ color: var(--xh-tree-select-empty-fg, var(--xh-material-frosted-fg-muted));
421
+ font-size: var(--xh-tree-select-empty-font-size, var(--xh-_tree-select-font-size));
422
+ line-height: var(--xh-leading-none);
423
+ text-align: center;
424
+ }
425
+
426
+ /* 上面给了 display,UA 的 [hidden]{display:none} 已被盖掉,这里补回来 */
427
+ .xh-scope-tree-select[data-part='empty'][hidden] {
428
+ display: none;
429
+ }
430
+
431
+ /* 在途占位:与空态占位同一个位置、同一副观感,两者不同屏 */
432
+ .xh-scope-tree-select[data-part='loading'] {
433
+ display: flex;
434
+ align-items: center;
435
+ justify-content: center;
436
+ gap: var(--xh-_tree-select-gap);
437
+ flex: none;
438
+ padding-block: var(--xh-tree-select-loading-py, var(--xh-space-3));
439
+ padding-inline: var(--xh-tree-select-loading-px, var(--xh-_tree-select-row-px));
440
+ color: var(--xh-tree-select-loading-fg, var(--xh-material-frosted-fg-muted));
441
+ font-size: var(--xh-tree-select-loading-font-size, var(--xh-_tree-select-font-size));
442
+ line-height: var(--xh-leading-none);
443
+ text-align: center;
444
+ }
445
+
446
+ .xh-scope-tree-select[data-part='loading'][hidden] {
447
+ display: none;
448
+ }
449
+
450
+ /* 首次加载:文案前一枚加载环,由加载环配方画(连接层投影 data-xh-loading-ring 与 data-loading),
451
+ 直径取所在尺寸档的图标档 */
452
+ .xh-scope-tree-select[data-part='loading']::before {
453
+ content: '';
454
+ flex: none;
455
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-md));
456
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-md));
457
+ }
458
+
459
+ /* 浮层底部的操作区:排在树下面,与树之间用一条分隔线断开;不参与收缩,行再多也压不扁它 */
460
+ .xh-scope-tree-select[data-part='footer'] {
461
+ display: flex;
462
+ flex: none;
463
+ align-items: center;
464
+ gap: var(--xh-tree-select-footer-gap, var(--xh-space-2));
465
+ padding-block: var(--xh-tree-select-footer-py, var(--xh-space-2));
466
+ padding-inline: var(--xh-tree-select-footer-px, var(--xh-space-2));
467
+ border-block-start: var(--xh-stroke-thin) solid var(--xh-tree-select-footer-border, var(--xh-material-frosted-separator));
468
+ color: var(--xh-tree-select-footer-fg, var(--xh-material-frosted-fg-muted));
469
+ font-size: var(--xh-tree-select-footer-font-size, var(--xh-text-secondary-size));
470
+ }
471
+
472
+ /* 上面给了 display,UA 的 [hidden]{display:none} 已被盖掉,这里补回来 */
473
+ .xh-scope-tree-select[data-part='footer'][hidden] {
474
+ display: none;
475
+ }
476
+
477
+ .xh-scope-tree-select[data-part='tree']:not([tabindex='0']):focus-visible {
478
+ outline: none;
479
+ }
480
+
481
+ /* 分支是"这一行 + 它的子层"的外壳,不自带内边距:真正长成一行的是 branch-control,
482
+ 子层缩进归 branch-content。行距由这里出:分支自己那一行与它展开的子层之间,
483
+ 同样按条目间距断开 */
484
+ .xh-scope-tree-select[data-part='branch'] {
485
+ display: flex;
486
+ flex-direction: column;
487
+ gap: var(--xh-tree-select-branch-gap, var(--xh-list-option-gap));
488
+ }
489
+
490
+ /* display 盖掉了 UA 的 [hidden]{display:none},收起时要显式让位 */
491
+ .xh-scope-tree-select[data-part='branch'][hidden] {
492
+ display: none;
493
+ }
494
+
495
+ /* 焦点落在 branch 上(它才是 treeitem),但环画在它自己那一行上:
496
+ 整棵子树套一圈描边会把展开的层级全框进去 */
497
+ .xh-scope-tree-select[data-part='branch']:focus-visible {
498
+ outline: none;
499
+ }
500
+
501
+ /* 行:叶子与分支共用同一套盒子,两种行在视觉上必须齐平。网格、尺寸档、悬停 / 高亮 100、按下 200 与
502
+ 选中标记由 Collection Item 家族按 overlay 语境给(选中 = 透明底 + 行尾对号,正文保持 rest 色与常规
503
+ 字重),公开 TreeSelect 槽只映射到家族合同。data-highlighted 跟的是连接层记的焦点行(指针与键盘共用),
504
+ 环只在真正的键盘焦点上接回,见下 */
505
+ .xh-scope-tree-select[data-part='item'],
506
+ .xh-scope-tree-select[data-part='branch-control'] {
507
+ --xh-collection-block-padding: var(--xh-tree-select-item-py, var(--xh-_tree-select-row-py));
508
+ --xh-collection-inline-padding: var(--xh-tree-select-item-px, var(--xh-_tree-select-row-px));
509
+ --xh-collection-gap: var(--xh-tree-select-item-gap, var(--xh-_tree-select-gap));
510
+ --xh-collection-font-size: var(--xh-tree-select-item-font-size, var(--xh-_tree-select-font-size));
511
+ --xh-collection-radius: var(--xh-tree-select-item-radius, var(--xh-shape-inset));
512
+ --xh-collection-glyph-size: var(--xh-tree-select-icon-size, var(--xh-_collection-glyph-size));
513
+ --xh-collection-fg-rest: var(--xh-tree-select-item-fg, var(--xh-material-frosted-fg));
514
+ --xh-collection-fg-hover: var(--xh-tree-select-item-fg, var(--xh-material-frosted-fg));
515
+ --xh-collection-fg-keyboard-highlight: var(--xh-tree-select-item-fg, var(--xh-material-frosted-fg));
516
+ --xh-collection-fg-selected: var(--xh-tree-select-item-fg-selected, var(--xh-tree-select-item-fg, var(--xh-material-frosted-fg)));
517
+ --xh-collection-fg-selected-highlight: var(--xh-tree-select-item-fg-selected, var(--xh-tree-select-item-fg, var(--xh-material-frosted-fg)));
518
+ --xh-collection-fg-selected-hover: var(--xh-tree-select-item-fg-selected, var(--xh-tree-select-item-fg, var(--xh-material-frosted-fg)));
519
+ --xh-collection-fg-selected-pressed: var(--xh-tree-select-item-fg-selected, var(--xh-tree-select-item-fg, var(--xh-material-frosted-fg)));
520
+ --xh-collection-fg-pressed: var(--xh-tree-select-item-fg, var(--xh-material-frosted-fg));
521
+ --xh-collection-font-weight-selected: var(--xh-tree-select-item-font-weight-selected, var(--xh-font-weight-regular));
522
+ --xh-collection-font-weight-selected-highlight: var(--xh-tree-select-item-font-weight-selected, var(--xh-font-weight-regular));
523
+ --xh-collection-font-weight-selected-hover: var(--xh-tree-select-item-font-weight-selected, var(--xh-font-weight-regular));
524
+ --xh-collection-font-weight-selected-pressed: var(--xh-tree-select-item-font-weight-selected, var(--xh-font-weight-regular));
525
+ --xh-collection-bg-hover: var(--xh-tree-select-item-bg-hover, var(--xh-bg-subtle));
526
+ --xh-collection-bg-keyboard-highlight: var(--xh-tree-select-item-bg-hover, var(--xh-bg-subtle));
527
+ --xh-collection-bg-selected-highlight: var(--xh-tree-select-item-bg-hover, var(--xh-bg-subtle));
528
+ --xh-collection-bg-selected-hover: var(--xh-tree-select-item-bg-hover, var(--xh-bg-subtle));
529
+ --xh-collection-bg-pressed: var(--xh-tree-select-item-bg-pressed, var(--xh-bg-subtle-hover));
530
+ --xh-collection-bg-selected-pressed: var(--xh-tree-select-item-bg-pressed, var(--xh-bg-subtle-hover));
531
+ --xh-collection-outline-keyboard-highlight: transparent;
532
+ --xh-collection-outline-selected-highlight: transparent;
533
+ --xh-collection-indicator-fg-rest: var(--xh-tree-select-item-check-fg, var(--xh-tree-select-item-indicator-fg, var(--xh-_tree-select-accent)));
534
+ --xh-collection-indicator-fg-checked: var(--xh-tree-select-item-check-fg, var(--xh-tree-select-item-indicator-fg, var(--xh-_tree-select-accent)));
535
+ --xh-collection-indicator-fg-selected: var(--xh-tree-select-item-check-fg, var(--xh-tree-select-item-indicator-fg, var(--xh-_tree-select-accent)));
536
+ --xh-collection-indicator-fg-selected-hover: var(--xh-tree-select-item-check-fg, var(--xh-tree-select-item-indicator-fg, var(--xh-_tree-select-accent)));
537
+ --xh-collection-indicator-fg-selected-highlight: var(--xh-tree-select-item-check-fg, var(--xh-tree-select-item-indicator-fg, var(--xh-_tree-select-accent)));
538
+ --xh-collection-indicator-fg-selected-pressed: var(--xh-tree-select-item-check-fg, var(--xh-tree-select-item-indicator-fg, var(--xh-_tree-select-accent)));
539
+
540
+ /* 行高留出文字的上下伸展空间,行内那层 overflow:hidden 才不会把字削掉 */
541
+ line-height: var(--xh-tree-select-item-leading, var(--xh-leading-normal));
542
+ white-space: nowrap;
543
+ user-select: none;
544
+ }
545
+
546
+ /* 家族给了 display,UA 的 [hidden]{display:none} 已被盖掉,这里补回来 */
547
+ .xh-scope-tree-select[data-part='item'][hidden],
548
+ .xh-scope-tree-select[data-part='branch-control'][hidden] {
549
+ display: none;
550
+ }
551
+
552
+ /* 叶子在家族网格的首列放一格与分支箭头等宽的占位:两种行的文字起点才对得齐;
553
+ 选中标记独立固定在行尾(indicator 列),不再同时承担层级缩进 */
554
+ .xh-scope-tree-select[data-part='item']::before {
555
+ content: '';
556
+ grid-column: prefix;
557
+ grid-row: 1 / span 2;
558
+ inline-size: var(--xh-tree-select-branch-indicator-size, var(--xh-control-indicator-size));
559
+ margin-inline-end: var(--xh-tree-select-item-gap, var(--xh-_tree-select-gap));
560
+ }
561
+
562
+ /* 键盘焦点出现时环才接回并立即到位,不压在背景过渡的中间帧上:叶子自己承载焦点,
563
+ 分支的焦点在 branch 上、环画在它那一行 */
564
+ .xh-scope-tree-select[data-part='item']:focus-visible:not(:hover),
565
+ .xh-scope-tree-select[data-part='branch']:focus-visible > .xh-scope-tree-select[data-part='branch-control'] {
566
+ --xh-collection-outline-keyboard-highlight: var(--xh-ring-focus);
567
+ --xh-collection-outline-selected-highlight: var(--xh-ring-focus);
568
+
569
+ transition: none;
570
+ }
571
+
572
+ /* 分支行不是 treeitem 本体(aria-disabled 在 branch 上),禁用面按连接层的 data-disabled 映射到家族槽:
573
+ 字色降级、悬停 / 高亮 / 按下不换面、光标 not-allowed */
574
+ .xh-scope-tree-select[data-part='branch-control'][data-disabled] {
575
+ --xh-collection-fg-rest: var(--xh-fg-disabled);
576
+ --xh-collection-fg-hover: var(--xh-fg-disabled);
577
+ --xh-collection-fg-keyboard-highlight: var(--xh-fg-disabled);
578
+ --xh-collection-fg-pressed: var(--xh-fg-disabled);
579
+ --xh-collection-bg-hover: transparent;
580
+ --xh-collection-bg-keyboard-highlight: transparent;
581
+ --xh-collection-bg-pressed: transparent;
582
+ --xh-collection-cursor-rest: not-allowed;
583
+ --xh-collection-cursor-hover: not-allowed;
584
+ --xh-collection-cursor-keyboard-highlight: not-allowed;
585
+ --xh-collection-cursor-pressed: not-allowed;
586
+ }
587
+
588
+ /* 懒分支取数失败不预设错误面(文案与重试归作者结构接线):家族按 data-error 给的告警面在这里映射回常态 */
589
+ .xh-scope-tree-select[data-part='branch-control'][data-error] {
590
+ --xh-collection-bg-error: transparent;
591
+ --xh-collection-fg-error: var(--xh-material-frosted-fg);
592
+ --xh-collection-description-fg-error: var(--xh-material-frosted-fg-muted);
593
+ --xh-collection-indicator-fg-error: var(--xh-_tree-select-accent);
594
+ --xh-collection-outline-error: transparent;
595
+ }
596
+
597
+ /* 取数失败的行仍可激活(Enter / 点行触发重试),而家族的悬停、高亮与按下三段都排除了 [data-error]:
598
+ 这里在家族解算点上把同一阶梯接回(行槽以 item 取名、叶子与分支行共用,登记见 check-spacing-slots):
599
+ 悬停与键盘高亮 100 档、按下 200 档并走按下时长,
600
+ 键盘焦点环随 branch 的 :focus-visible 画在这一行;禁用分支不进这三段 */
601
+ .xh-scope-tree-select[data-part='branch-control'][data-error]:not([data-disabled]):is(:hover, [data-highlighted]) {
602
+ --xh-_collection-bg: var(--xh-tree-select-item-bg-hover, var(--xh-bg-subtle));
603
+ }
604
+
605
+ .xh-scope-tree-select[data-part='branch']:focus-visible > .xh-scope-tree-select[data-part='branch-control'][data-error]:not([data-disabled]) {
606
+ --xh-_collection-bg: var(--xh-tree-select-item-bg-hover, var(--xh-bg-subtle));
607
+ --xh-_collection-outline: var(--xh-ring-focus);
608
+ }
609
+
610
+ .xh-scope-tree-select[data-part='branch-control'][data-error]:not([data-disabled]):is(:active, [data-pressed]) {
611
+ --xh-_collection-bg: var(--xh-tree-select-item-bg-pressed, var(--xh-bg-subtle-hover));
612
+
613
+ transition-duration: var(--xh-motion-duration-press);
614
+ transition-timing-function: var(--xh-motion-ease-press);
615
+ }
616
+
617
+ /* 正文落在家族网格的 text 列;网格项默认最小尺寸是内容尺寸,不归零则长文本把行撑破、省略号轮不上 */
618
+ .xh-scope-tree-select[data-part='item-text'],
619
+ .xh-scope-tree-select[data-part='branch-text'] {
620
+ min-inline-size: 0;
621
+ overflow: hidden;
622
+ white-space: nowrap;
623
+ text-overflow: ellipsis;
624
+ }
625
+
626
+ /* 勾选标记落在家族网格的 indicator 列;未选中时占位不塌,切换选中不引起行宽抖动。
627
+ 尺寸槽按各自部件取名:行内的勾与展开箭头分别是 item- 与 branch- 段,
628
+ 触发器上那枚箭头是 --xh-tree-select-indicator-*,三处各调各的。
629
+ 盒里的对号 / 半选杠是指示符:在自己身上把 --xh-icon-size 改接到盒的尺,兜底字形与作者
630
+ 塞进盒里的 XhIcon 读同一把尺、与盒同边长;不读家族按档下发到行的 --xh-icon-size——那支只管
631
+ 作者放进行里的图标,按图标档取的 20px 会比 16 / 14 的盒还大 */
632
+ .xh-scope-tree-select[data-part='item-indicator'] {
633
+ --xh-icon-size: var(--xh-tree-select-item-indicator-size, var(--xh-control-indicator-size));
634
+
635
+ display: inline-flex;
636
+ align-items: center;
637
+ justify-content: center;
638
+ inline-size: var(--xh-tree-select-item-indicator-size, var(--xh-control-indicator-size));
639
+ block-size: var(--xh-tree-select-item-indicator-size, var(--xh-control-indicator-size));
640
+ }
641
+
642
+ .xh-scope-tree-select[data-part='item-indicator'][hidden] {
643
+ display: none;
644
+ }
645
+
646
+ /* 家族只按行的 aria-selected 显示对号:分支行的 aria-selected 在 branch 上、半选没有选中语义,
647
+ 这两档按标记自身的 data-selected / data-indeterminate 显形 */
648
+ .xh-scope-tree-select[data-part='item-indicator']:is([data-selected], [data-indeterminate]) {
649
+ opacity: 1;
650
+ }
651
+
652
+ /* 分支行的禁用不在行的 aria-disabled 上(那在 branch 上),标记按自身的 data-disabled 降级 */
653
+ .xh-scope-tree-select[data-part='item-indicator'][data-disabled] {
654
+ color: var(--xh-fg-disabled);
655
+ }
656
+
657
+ /* 展开箭头与方向指示符:两者都可能被作者用作「点这里展开」的把手,
658
+ 所以尺寸与叶子的勾选标记一致,两种行的文字起点才对得齐。
659
+ 盒里的 chevron 是指示符:与盒同边长,--xh-icon-size 在自己身上改接到盒的尺 */
660
+ .xh-scope-tree-select[data-part='branch-trigger'],
661
+ .xh-scope-tree-select[data-part='branch-indicator'] {
662
+ --xh-icon-size: var(--xh-tree-select-branch-indicator-size, var(--xh-control-indicator-size));
663
+
664
+ display: inline-flex;
665
+ flex: none;
666
+ align-items: center;
667
+ justify-content: center;
668
+ inline-size: var(--xh-tree-select-branch-indicator-size, var(--xh-control-indicator-size));
669
+ color: var(--xh-tree-select-branch-indicator-fg, var(--xh-fg-subtle));
670
+ transition: rotate var(--xh-motion-duration-nudge) var(--xh-motion-ease-enter-strong);
671
+ }
672
+
673
+ .xh-scope-tree-select[data-part='branch-trigger'][hidden],
674
+ .xh-scope-tree-select[data-part='branch-indicator'][hidden] {
675
+ display: none;
676
+ }
677
+
678
+ /* 收起时指向行尾、展开时转向下方,与逻辑书写方向一致:rtl 下行尾在左侧,收起的箭头转半圈;
679
+ 旋转角乘书写方向的符号(ltr 0deg、rtl 180deg),按就近的 dir 走 */
680
+ .xh-scope-tree-select[data-part='branch-trigger'],
681
+ .xh-scope-tree-select[data-part='branch-indicator'] {
682
+ rotate: calc(90deg - 90deg * var(--xh-direction-sign));
683
+ }
684
+
685
+ .xh-scope-tree-select[data-part='branch-trigger'][data-state='open'],
686
+ .xh-scope-tree-select[data-part='branch-indicator'][data-state='open'] {
687
+ rotate: 90deg;
688
+ }
689
+
690
+ .xh-scope-tree-select[data-part='branch-trigger'][data-disabled],
691
+ .xh-scope-tree-select[data-part='branch-indicator'][data-disabled] {
692
+ color: var(--xh-fg-disabled);
693
+ }
694
+
695
+ /* 层级缩进靠子层容器自己顶:分支物理嵌套着子层,每深一层就多缩一格,
696
+ 无需把层级号写进内联样式,也就不必在两个适配器里各写一遍 */
697
+ .xh-scope-tree-select[data-part='branch-content'] {
698
+ display: flex;
699
+ flex-direction: column;
700
+ gap: var(--xh-tree-select-branch-content-gap, var(--xh-list-option-gap));
701
+ padding-inline-start: var(--xh-tree-select-indent, var(--xh-space-4));
702
+ }
703
+
704
+ /* 分支首次展开取子项时的三种占位落在子层的位置(与子层同一缩进),与整树的占位同一副样子:
705
+ 在途一枚加载环 + 文案、成功为空一句文案、失败一枚警示字形 + 说明。它们不是 treeitem,不接悬停与按下 */
706
+ .xh-scope-tree-select:is([data-part='branch-loading'], [data-part='branch-empty'], [data-part='branch-error']) {
707
+ display: flex;
708
+ align-items: center;
709
+ gap: var(--xh-_tree-select-gap);
710
+ padding-block: var(--xh-tree-select-branch-status-py, var(--xh-_tree-select-row-py));
711
+ padding-inline: calc(var(--xh-tree-select-indent, var(--xh-space-4)) + var(--xh-_tree-select-row-px)) var(--xh-_tree-select-row-px);
712
+ color: var(--xh-tree-select-branch-status-fg, var(--xh-material-frosted-fg-muted));
713
+ font-size: var(--xh-tree-select-branch-status-font-size, var(--xh-_tree-select-font-size));
714
+ line-height: var(--xh-leading-none);
715
+ user-select: none;
716
+ }
717
+
718
+ .xh-scope-tree-select[data-part='branch-loading']::before {
719
+ content: '';
720
+ flex: none;
721
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-md));
722
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-md));
723
+ }
724
+
725
+ /* 失败的非颜色通道:一枚警示字形,取危险色 */
726
+ .xh-scope-tree-select[data-part='branch-error']::before {
727
+ content: '';
728
+ flex: none;
729
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-md));
730
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-md));
731
+ background-color: var(--xh-tree-select-branch-error-fg, var(--xh-fg-danger));
732
+ -webkit-mask: var(--xh-glyph-mark-warning) center / contain no-repeat;
733
+ mask: var(--xh-glyph-mark-warning) center / contain no-repeat;
734
+ }
735
+
736
+ /* 重试钮排在失败说明之下、与说明同一缩进;指针入口,键盘在出错的分支行上按 Enter / Space 重试 */
737
+ .xh-scope-tree-select[data-part='branch-retry-trigger'] {
738
+ align-self: flex-start;
739
+ margin-inline-start: calc(var(--xh-tree-select-indent, var(--xh-space-4)) + var(--xh-_tree-select-row-px));
740
+ padding: 0;
741
+ border: 0;
742
+ background: none;
743
+ color: var(--xh-tree-select-branch-retry-fg, var(--xh-fg-brand));
744
+ font: inherit;
745
+ font-size: var(--xh-tree-select-branch-status-font-size, var(--xh-_tree-select-font-size));
746
+ line-height: var(--xh-leading-normal);
747
+ text-decoration-line: underline;
748
+ text-decoration-color: transparent;
749
+ text-underline-offset: var(--xh-space-0_5);
750
+ cursor: pointer;
751
+ transition: text-decoration-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
752
+ }
753
+
754
+ .xh-scope-tree-select[data-part='branch-retry-trigger']:hover {
755
+ text-decoration-color: currentColor;
756
+ }
757
+
758
+ .xh-scope-tree-select[data-part='branch-retry-trigger']:disabled {
759
+ color: var(--xh-fg-disabled);
760
+ cursor: not-allowed;
761
+ }
762
+
763
+ .xh-scope-tree-select:is([data-part='branch-loading'], [data-part='branch-empty'], [data-part='branch-error'], [data-part='branch-retry-trigger'])[hidden] {
764
+ display: none;
765
+ }
766
+
767
+ /* 收起态的唯一开关:display 盖掉了 UA 的 [hidden]{display:none},漏了这条整棵子树就收不起来 */
768
+ .xh-scope-tree-select[data-part='branch-content'][hidden],
769
+ .xh-scope-tree-select[data-part='branch-content'][data-state='closed'] {
770
+ display: none;
771
+ }
772
+
773
+ /* 没写内容就由皮肤画兜底字形;作者往部件里塞了自己的图形,这几条即不命中。
774
+ 尺寸读各部件的 --xh-icon-size:触发器箭头与清除钮的叉按图标档,行尾对号 / 半选杠与展开 chevron
775
+ 读部件自己改接过的盒尺、与盒同边长(见上面两块) */
776
+ .xh-scope-tree-select[data-part='indicator']:empty::before {
777
+ content: '';
778
+ display: inline-block;
779
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
780
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
781
+ vertical-align: var(--xh-glyph-baseline-shift);
782
+ background-color: currentColor;
783
+ -webkit-mask: var(--xh-glyph-mark-chevron-down) center / contain no-repeat;
784
+ mask: var(--xh-glyph-mark-chevron-down) center / contain no-repeat;
785
+ }
786
+
787
+ /* 勾与半选杠叠成两层遮罩,按状态只换两层的尺寸:离开半选淡出的那一段里横杠留着,
788
+ 淡出播完才换回勾——不在淡出途中闪出一枚勾 */
789
+ .xh-scope-tree-select[data-part='item-indicator']:empty::before {
790
+ content: '';
791
+ display: inline-block;
792
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
793
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
794
+ vertical-align: var(--xh-glyph-baseline-shift);
795
+ background-color: currentColor;
796
+ -webkit-mask: var(--xh-glyph-mark-check) center / 100% 100% no-repeat, var(--xh-glyph-mark-minus) center / 0 0 no-repeat;
797
+ mask: var(--xh-glyph-mark-check) center / 100% 100% no-repeat, var(--xh-glyph-mark-minus) center / 0 0 no-repeat;
798
+ transition:
799
+ -webkit-mask-size 0s var(--xh-motion-duration-micro),
800
+ mask-size 0s var(--xh-motion-duration-micro);
801
+ }
802
+
803
+ .xh-scope-tree-select[data-part='item-indicator'][data-selected]:empty::before {
804
+ transition-delay: 0s;
805
+ }
806
+
807
+ .xh-scope-tree-select[data-part='item-indicator'][data-indeterminate]:not([data-selected]):empty::before {
808
+ -webkit-mask-size: 0 0, 100% 100%;
809
+ mask-size: 0 0, 100% 100%;
810
+ transition-delay: 0s;
811
+ }
812
+
813
+ .xh-scope-tree-select[data-part='branch-trigger']:empty::before,
814
+ .xh-scope-tree-select[data-part='branch-indicator']:empty::before {
815
+ content: '';
816
+ display: inline-block;
817
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
818
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
819
+ vertical-align: var(--xh-glyph-baseline-shift);
820
+ background-color: currentColor;
821
+ -webkit-mask: var(--xh-glyph-mark-chevron-right) center / contain no-repeat;
822
+ mask: var(--xh-glyph-mark-chevron-right) center / contain no-repeat;
823
+ }
824
+
825
+ .xh-scope-tree-select[data-part='clear-trigger']:empty::before {
826
+ content: '';
827
+ display: inline-block;
828
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
829
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
830
+ vertical-align: var(--xh-glyph-baseline-shift);
831
+ background-color: currentColor;
832
+ -webkit-mask: var(--xh-glyph-mark-close) center / contain no-repeat;
833
+ mask: var(--xh-glyph-mark-close) center / contain no-repeat;
834
+ }
835
+
836
+ @media print {
837
+ /* 打印:定位层与遮罩是交互期才存在的东西,落到纸上只会盖住底下的正文。
838
+ 收起写在这份皮肤里而不是 reset:reset 层排在组件层之前,组件层里任何一条 display 都压得住它。 */
839
+ .xh-scope-tree-select[data-part='positioner'] {
840
+ display: none;
841
+ }
842
+ }
843
+
844
+ @media (forced-colors: active) {
845
+ /* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
846
+ 字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
847
+ 按钮面上取 ButtonText,悬停与按下时家族把按钮涂成 Highlight、字形换 HighlightText;
848
+ 条目面上取 CanvasText;按下与没被高亮时的悬停,家族把条目涂成 Highlight,字形换 HighlightText;
849
+ 字段面上取 CanvasText;
850
+ 落在 Canvas 面上的取 CanvasText;
851
+ 禁用取 GrayText */
852
+ .xh-scope-tree-select[data-part='branch-error']::before,
853
+ .xh-scope-tree-select[data-part='indicator']:empty::before,
854
+ .xh-scope-tree-select[data-part='item-indicator']:empty::before,
855
+ .xh-scope-tree-select:is([data-part='branch-trigger'], [data-part='branch-indicator']):empty::before {
856
+ forced-color-adjust: none;
857
+ background-color: CanvasText;
858
+ }
859
+
860
+ .xh-scope-tree-select[data-part='clear-trigger']:empty::before {
861
+ forced-color-adjust: none;
862
+ background-color: ButtonText;
863
+ }
864
+
865
+ .xh-scope-tree-select[data-part='item']:not([aria-disabled='true'], [data-disabled], [aria-busy='true'], [data-error]):is(:active, [data-pressed], :hover:not(:focus-visible, [data-highlighted])) .xh-scope-tree-select[data-part='item-indicator']:empty::before,
866
+ .xh-scope-tree-select[data-part='branch-control']:not([aria-disabled='true'], [data-disabled], [aria-busy='true'], [data-error]):is(:active, [data-pressed], :hover:not(:focus-visible, [data-highlighted])) .xh-scope-tree-select:is([data-part='branch-trigger'], [data-part='branch-indicator']):empty::before,
867
+ .xh-scope-tree-select[data-part='clear-trigger']:not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]):empty::before {
868
+ background-color: HighlightText;
869
+ }
870
+
871
+ .xh-scope-tree-select[data-part='control'][data-disabled] .xh-scope-tree-select[data-part='indicator']:empty::before,
872
+ .xh-scope-tree-select[data-part='item']:is([aria-disabled='true'], [data-disabled]) .xh-scope-tree-select[data-part='item-indicator']:empty::before,
873
+ .xh-scope-tree-select[data-part='branch-control']:is([aria-disabled='true'], [data-disabled]) .xh-scope-tree-select:is([data-part='branch-trigger'], [data-part='branch-indicator']):empty::before,
874
+ .xh-scope-tree-select[data-part='clear-trigger'][data-disabled]:empty::before {
875
+ background-color: GrayText;
876
+ }
877
+ }
878
+ }