@xihan-ui/styles 3.1.0 → 4.0.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 (290) hide show
  1. package/CHANGELOG.md +470 -0
  2. package/component-tokens.d.ts +230 -60
  3. package/components.tokens.json +5156 -1557
  4. package/css/accordion.css +47 -20
  5. package/css/alert.css +16 -17
  6. package/css/anchor.css +2 -2
  7. package/css/approval.css +41 -17
  8. package/css/avatar-group.css +9 -12
  9. package/css/avatar.css +20 -18
  10. package/css/back-top.css +21 -7
  11. package/css/badge.css +5 -5
  12. package/css/breadcrumb.css +18 -16
  13. package/css/button-group.css +4 -6
  14. package/css/button.css +13 -12
  15. package/css/calendar-picker.css +178 -95
  16. package/css/calendar-range-picker.css +207 -122
  17. package/css/card.css +34 -6
  18. package/css/carousel.css +94 -46
  19. package/css/cartesian-chart.css +11 -11
  20. package/css/cascader.css +51 -39
  21. package/css/checkbox-group.css +9 -6
  22. package/css/checkbox.css +5 -4
  23. package/css/citation.css +9 -4
  24. package/css/clipboard.css +20 -4
  25. package/css/code-view.css +6 -6
  26. package/css/collapsible.css +29 -14
  27. package/css/color-field.css +4 -4
  28. package/css/color-picker.css +77 -23
  29. package/css/color-slider.css +10 -8
  30. package/css/color-swatch-picker.css +14 -9
  31. package/css/combobox.css +26 -14
  32. package/css/command.css +14 -9
  33. package/css/context-menu.css +10 -5
  34. package/css/date-field.css +12 -6
  35. package/css/date-picker.css +178 -109
  36. package/css/date-range-picker.css +199 -130
  37. package/css/description.css +10 -6
  38. package/css/descriptions.css +47 -19
  39. package/css/dialog.css +50 -35
  40. package/css/diff-view.css +8 -8
  41. package/css/drawer.css +75 -21
  42. package/css/editable.css +15 -41
  43. package/css/empty-state.css +21 -3
  44. package/css/field-array.css +5 -2
  45. package/css/field.css +17 -18
  46. package/css/fieldset.css +33 -13
  47. package/css/file-upload.css +66 -33
  48. package/css/float-button.css +60 -35
  49. package/css/floating-panel.css +1 -1
  50. package/css/form.css +30 -16
  51. package/css/graph-chart.css +2 -2
  52. package/css/grid-list.css +1 -1
  53. package/css/highlight.css +5 -5
  54. package/css/hover-card.css +19 -12
  55. package/css/image-viewer.css +77 -27
  56. package/css/image.css +13 -5
  57. package/css/infinite-scroll.css +8 -4
  58. package/css/input-group.css +74 -26
  59. package/css/kbd.css +1 -1
  60. package/css/label.css +27 -11
  61. package/css/layout.css +17 -10
  62. package/css/list.css +13 -9
  63. package/css/listbox.css +12 -7
  64. package/css/loading-bar.css +3 -0
  65. package/css/mention.css +11 -9
  66. package/css/menu.css +10 -5
  67. package/css/menubar.css +13 -8
  68. package/css/message-feed.css +1 -1
  69. package/css/navigation-menu.css +2 -2
  70. package/css/notification.css +132 -49
  71. package/css/number-animation.css +2 -2
  72. package/css/number-field.css +75 -52
  73. package/css/page-header.css +64 -27
  74. package/css/pagination.css +35 -38
  75. package/css/password-input.css +12 -68
  76. package/css/pin-input.css +18 -26
  77. package/css/popconfirm.css +23 -14
  78. package/css/popover.css +18 -12
  79. package/css/progress.css +14 -13
  80. package/css/prompt-input.css +3 -3
  81. package/css/question-flow.css +41 -15
  82. package/css/radar-chart.css +6 -6
  83. package/css/radio-group.css +120 -55
  84. package/css/rating.css +32 -15
  85. package/css/select.css +16 -12
  86. package/css/separator.css +24 -6
  87. package/css/side-nav.css +29 -24
  88. package/css/signature-pad.css +23 -9
  89. package/css/skeleton.css +12 -12
  90. package/css/slider.css +77 -48
  91. package/css/sortable.css +2 -2
  92. package/css/sparkline.css +8 -2
  93. package/css/spinner.css +40 -20
  94. package/css/statistic.css +14 -14
  95. package/css/steps.css +115 -84
  96. package/css/switch.css +9 -7
  97. package/css/table.css +29 -12
  98. package/css/tabs.css +35 -12
  99. package/css/tag-group.css +17 -6
  100. package/css/tag.css +54 -29
  101. package/css/tags-input.css +39 -20
  102. package/css/text-field.css +5 -5
  103. package/css/time-field.css +4 -4
  104. package/css/time-picker.css +150 -64
  105. package/css/time-range-picker.css +91 -62
  106. package/css/timeline.css +37 -20
  107. package/css/timer.css +3 -3
  108. package/css/toggle-group.css +4 -4
  109. package/css/tool-call.css +13 -11
  110. package/css/toolbar.css +6 -5
  111. package/css/tooltip.css +16 -17
  112. package/css/tour.css +14 -7
  113. package/css/transfer.css +22 -16
  114. package/css/tree-select.css +12 -12
  115. package/css/tree.css +26 -25
  116. package/css/typography.css +28 -25
  117. package/dist/css/accordion.css +296 -0
  118. package/dist/css/affix.css +47 -0
  119. package/dist/css/alert.css +246 -0
  120. package/dist/css/anchor.css +252 -0
  121. package/dist/css/approval.css +525 -0
  122. package/dist/css/avatar-group.css +96 -0
  123. package/dist/css/avatar.css +100 -0
  124. package/dist/css/back-top.css +175 -0
  125. package/dist/css/badge.css +205 -0
  126. package/dist/css/bar-code.css +62 -0
  127. package/dist/css/breadcrumb.css +232 -0
  128. package/dist/css/button-group.css +261 -0
  129. package/dist/css/button.css +216 -0
  130. package/dist/css/calendar-picker.css +550 -0
  131. package/dist/css/calendar-range-picker.css +639 -0
  132. package/dist/css/card.css +249 -0
  133. package/dist/css/carousel.css +726 -0
  134. package/dist/css/cartesian-chart.css +830 -0
  135. package/dist/css/cascader.css +973 -0
  136. package/dist/css/checkbox-group.css +361 -0
  137. package/dist/css/checkbox.css +258 -0
  138. package/dist/css/citation.css +475 -0
  139. package/dist/css/clipboard.css +331 -0
  140. package/dist/css/code-view.css +374 -0
  141. package/dist/css/collapsible.css +200 -0
  142. package/dist/css/color-field.css +176 -0
  143. package/dist/css/color-picker.css +649 -0
  144. package/dist/css/color-slider.css +283 -0
  145. package/dist/css/color-swatch-picker.css +250 -0
  146. package/dist/css/color-swatch.css +35 -0
  147. package/dist/css/combobox.css +578 -0
  148. package/dist/css/command.css +404 -0
  149. package/dist/css/context-menu.css +425 -0
  150. package/dist/css/date-field.css +317 -0
  151. package/dist/css/date-picker.css +931 -0
  152. package/dist/css/date-range-picker.css +949 -0
  153. package/dist/css/description.css +71 -0
  154. package/dist/css/descriptions.css +327 -0
  155. package/dist/css/dialog.css +470 -0
  156. package/dist/css/diff-view.css +513 -0
  157. package/dist/css/download-trigger.css +151 -0
  158. package/dist/css/drawer.css +606 -0
  159. package/dist/css/editable.css +269 -0
  160. package/dist/css/empty-state.css +181 -0
  161. package/dist/css/field-array.css +229 -0
  162. package/dist/css/field.css +165 -0
  163. package/dist/css/fieldset.css +122 -0
  164. package/dist/css/file-upload.css +462 -0
  165. package/dist/css/flex.css +441 -0
  166. package/dist/css/float-button.css +579 -0
  167. package/dist/css/floating-panel.css +429 -0
  168. package/dist/css/focus.css +46 -0
  169. package/dist/css/forced-colors.css +93 -0
  170. package/dist/css/form.css +407 -0
  171. package/dist/css/funnel-chart.css +106 -0
  172. package/dist/css/graph-chart.css +205 -0
  173. package/dist/css/grid-list.css +235 -0
  174. package/dist/css/grid.css +1201 -0
  175. package/dist/css/heatmap.css +552 -0
  176. package/dist/css/hierarchy-chart.css +298 -0
  177. package/dist/css/highlight.css +41 -0
  178. package/dist/css/hover-card.css +233 -0
  179. package/dist/css/icon.css +225 -0
  180. package/dist/css/image-cropper.css +373 -0
  181. package/dist/css/image-viewer.css +588 -0
  182. package/dist/css/image.css +106 -0
  183. package/dist/css/infinite-scroll.css +81 -0
  184. package/dist/css/input-group.css +323 -0
  185. package/dist/css/json-viewer.css +379 -0
  186. package/dist/css/kbd.css +72 -0
  187. package/dist/css/label.css +94 -0
  188. package/dist/css/layers.css +7 -0
  189. package/dist/css/layout.css +379 -0
  190. package/dist/css/liquid.css +106 -0
  191. package/dist/css/list.css +156 -0
  192. package/dist/css/listbox.css +395 -0
  193. package/dist/css/loading-bar.css +144 -0
  194. package/dist/css/log.css +306 -0
  195. package/dist/css/markdown-stream.css +149 -0
  196. package/dist/css/marquee.css +378 -0
  197. package/dist/css/masonry.css +70 -0
  198. package/dist/css/matrix-code.css +67 -0
  199. package/dist/css/mention.css +395 -0
  200. package/dist/css/menu.css +369 -0
  201. package/dist/css/menubar.css +461 -0
  202. package/dist/css/message-feed.css +318 -0
  203. package/dist/css/navigation-menu.css +513 -0
  204. package/dist/css/notification.css +865 -0
  205. package/dist/css/number-animation.css +44 -0
  206. package/dist/css/number-field.css +275 -0
  207. package/dist/css/overlay-arrow.css +56 -0
  208. package/dist/css/page-header.css +221 -0
  209. package/dist/css/pagination.css +447 -0
  210. package/dist/css/password-input.css +335 -0
  211. package/dist/css/pie-chart.css +247 -0
  212. package/dist/css/pin-input.css +191 -0
  213. package/dist/css/pointer.css +36 -0
  214. package/dist/css/popconfirm.css +329 -0
  215. package/dist/css/popover.css +285 -0
  216. package/dist/css/progress.css +502 -0
  217. package/dist/css/prompt-input.css +260 -0
  218. package/dist/css/question-flow.css +579 -0
  219. package/dist/css/radar-chart.css +233 -0
  220. package/dist/css/radio-group.css +663 -0
  221. package/dist/css/rating.css +311 -0
  222. package/dist/css/reasoning.css +343 -0
  223. package/dist/css/reset.css +117 -0
  224. package/dist/css/resizable.css +242 -0
  225. package/dist/css/sankey-chart.css +174 -0
  226. package/dist/css/scroll-area.css +240 -0
  227. package/dist/css/scrollbar.css +204 -0
  228. package/dist/css/select.css +616 -0
  229. package/dist/css/separator.css +140 -0
  230. package/dist/css/side-nav.css +481 -0
  231. package/dist/css/signature-pad.css +193 -0
  232. package/dist/css/skeleton.css +161 -0
  233. package/dist/css/slider.css +403 -0
  234. package/dist/css/sortable.css +228 -0
  235. package/dist/css/sparkline.css +170 -0
  236. package/dist/css/spinner.css +256 -0
  237. package/dist/css/splitter.css +159 -0
  238. package/dist/css/statistic.css +137 -0
  239. package/dist/css/steps.css +658 -0
  240. package/dist/css/switch.css +353 -0
  241. package/dist/css/table.css +1162 -0
  242. package/dist/css/tabs.css +967 -0
  243. package/dist/css/tag-group.css +258 -0
  244. package/dist/css/tag.css +335 -0
  245. package/dist/css/tags-input.css +341 -0
  246. package/dist/css/text-field.css +197 -0
  247. package/dist/css/time-field.css +277 -0
  248. package/dist/css/time-picker.css +793 -0
  249. package/dist/css/time-range-picker.css +775 -0
  250. package/dist/css/timeline.css +440 -0
  251. package/dist/css/timer.css +123 -0
  252. package/dist/css/timestamp.css +34 -0
  253. package/dist/css/toggle-group.css +424 -0
  254. package/dist/css/toggle.css +146 -0
  255. package/dist/css/tone.css +189 -0
  256. package/dist/css/tool-call.css +431 -0
  257. package/dist/css/toolbar.css +366 -0
  258. package/dist/css/tooltip.css +217 -0
  259. package/dist/css/tour.css +446 -0
  260. package/dist/css/transfer.css +644 -0
  261. package/dist/css/tree-select.css +878 -0
  262. package/dist/css/tree.css +734 -0
  263. package/dist/css/truncate.css +108 -0
  264. package/dist/css/typography.css +475 -0
  265. package/dist/css/undefined.css +58 -0
  266. package/dist/css/virtualizer.css +166 -0
  267. package/dist/css/visually-hidden.css +20 -0
  268. package/dist/css/watermark.css +82 -0
  269. package/dist/family/action-control.css +493 -0
  270. package/dist/family/chart.css +537 -0
  271. package/dist/family/check-mark.css +94 -0
  272. package/dist/family/choice-card.css +97 -0
  273. package/dist/family/collection-item.css +768 -0
  274. package/dist/family/field-chrome.css +296 -0
  275. package/dist/family/loading-ring.css +102 -0
  276. package/dist/family/material.css +72 -0
  277. package/dist/family/menu-choice.css +56 -0
  278. package/dist/family/motion.css +363 -0
  279. package/dist/family/swatch.css +59 -0
  280. package/dist/family/tag-list.css +65 -0
  281. package/family/action-control.css +33 -36
  282. package/family/chart.css +57 -0
  283. package/family/collection-item.css +12 -8
  284. package/family/field-chrome.css +28 -19
  285. package/family/loading-ring.css +20 -13
  286. package/family/swatch.css +4 -4
  287. package/family/tag-list.css +6 -0
  288. package/index.css +10349 -8756
  289. package/index.unlayered.css +10350 -8758
  290. package/package.json +165 -164
@@ -0,0 +1,170 @@
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
+ /* 定义 sparkline 样式。 */
7
+
8
+ /* 描线与淡入关键帧由 family/motion.css 提供;本皮肤 @import 它,单独引入仍成立。
9
+ 迷你图只消费色槽与线宽,不接 Chart 家族配方的标题、图例与提示框。 */
10
+ @import '../family/motion.css';
11
+
12
+ @layer xihan.components {
13
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
14
+ .xh-scope-sparkline {
15
+ --xh-sparkline-skin: 1;
16
+ }
17
+
18
+ /* 根就是 <svg>:随文排版,宽度缺省 6rem,高度缺省一行字高,放进表格单元格与指标卡都不撑高一行。
19
+ 几何要用的像素值以这里的私有槽为真源:机器挂载后从计算样式读它们,作者覆盖组件槽即改变几何 */
20
+ .xh-scope-sparkline[data-part='root'] {
21
+ --xh-_chart-metric-line-width: var(--xh-sparkline-line-width, var(--xh-chart-line-width));
22
+ --xh-_chart-metric-point-size: var(--xh-sparkline-marker-size, var(--xh-chart-point-size));
23
+ --xh-_chart-metric-gap: var(--xh-chart-gap);
24
+ --xh-_chart-metric-bar-max: var(--xh-sparkline-bar-max, var(--xh-chart-bar-max));
25
+ --xh-_chart-metric-radius: var(--xh-sparkline-bar-radius, var(--xh-shape-inset));
26
+ /* 迷你图不画轴、标签与命中区,这几项照样写全:度量槽登记成了长度,不写的那项读到的是初始值 0,不是缺省 */
27
+ --xh-_chart-metric-hit-min: var(--xh-chart-hit-min);
28
+ --xh-_chart-metric-tick-length: var(--xh-chart-tick-length);
29
+ --xh-_chart-metric-label-gap: var(--xh-chart-label-gap);
30
+ --xh-_chart-metric-font-size: var(--xh-text-caption-size);
31
+ --xh-_chart-metric-leading: var(--xh-leading-tight);
32
+
33
+ /* 缺省中性:线与柱退到弱化色,只让标记点取品牌色相的色槽 1,读者先看到「现在在哪」 */
34
+ --xh-_sparkline-color: var(--xh-sparkline-color, var(--xh-chart-deemphasis));
35
+ --xh-_sparkline-accent: var(--xh-sparkline-accent-color, var(--xh-chart-categorical-1));
36
+
37
+ display: inline-block;
38
+ inline-size: var(--xh-sparkline-width, 6rem);
39
+ /* 级联兜底:先写一行正文的行框令牌(正文字号 × 正文行距),再写 1lh。
40
+ 1lh 晚于本库声明的浏览器地板,取不到时旧引擎丢掉后一条、留下前一条。 */
41
+ block-size: var(--xh-sparkline-height, var(--xh-text-body-line-h));
42
+ block-size: var(--xh-sparkline-height, 1lh);
43
+ /* 高度正好是一个行盒:顶边贴行盒顶边,行高不被撑开;居中对齐会按字的 x 高度再挪半格,行盒就多出一截 */
44
+ vertical-align: top;
45
+ }
46
+
47
+ /* 写了语气就整条取语气色:颜色本身带好坏含义,线、柱与标记点同色 */
48
+ .xh-scope-sparkline[data-part='root'][data-tone]:not([data-tone='neutral']) {
49
+ --xh-_sparkline-color: var(--xh-sparkline-color, var(--xh-_tone));
50
+ --xh-_sparkline-accent: var(--xh-sparkline-accent-color, var(--xh-_tone));
51
+ }
52
+
53
+ /* 参考带是注释:淡底画在数据之下 */
54
+ .xh-scope-sparkline[data-part='band'] {
55
+ fill: var(--xh-sparkline-band-bg, var(--xh-bg-subtle));
56
+ stroke: none;
57
+ }
58
+
59
+ /* 参考线:读数据的尺子,取标注色的细虚线,压在数据底下 */
60
+ .xh-scope-sparkline[data-part='reference-line'] {
61
+ fill: none;
62
+ stroke: var(--xh-sparkline-reference-color, var(--xh-chart-label));
63
+ stroke-width: var(--xh-stroke-thin);
64
+ stroke-dasharray: calc(var(--xh-stroke-thick) * 2) calc(var(--xh-stroke-thick) * 2);
65
+ }
66
+
67
+ .xh-scope-sparkline[data-part='line'] {
68
+ fill: none;
69
+ stroke: var(--xh-_sparkline-color);
70
+ stroke-width: var(--xh-_chart-metric-line-width);
71
+ stroke-linejoin: round;
72
+ stroke-linecap: round;
73
+ }
74
+
75
+ /* 面积:线色淡洗,上沿是同一条折线 */
76
+ .xh-scope-sparkline[data-part='area-fill'] {
77
+ fill: var(--xh-_sparkline-color);
78
+ fill-opacity: var(--xh-chart-area-alpha);
79
+ stroke: none;
80
+ }
81
+
82
+ /* 柱:相邻柱之间的间隙由几何留出,不画描边;标出的那几根换成强调色 */
83
+ .xh-scope-sparkline[data-part='bar'] {
84
+ fill: var(--xh-_sparkline-color);
85
+ stroke: none;
86
+ }
87
+
88
+ .xh-scope-sparkline[data-part='bar'][data-marker] {
89
+ fill: var(--xh-_sparkline-accent);
90
+ }
91
+
92
+ /* 盈亏:正负各取涨跌色,缺省绿涨红跌,主题覆盖令牌即可对调 */
93
+ .xh-scope-sparkline[data-part='bar'][data-trend='rise'] {
94
+ fill: var(--xh-chart-rise);
95
+ }
96
+
97
+ .xh-scope-sparkline[data-part='bar'][data-trend='fall'] {
98
+ fill: var(--xh-chart-fall);
99
+ }
100
+
101
+ /* 标记点带一圈承载面色的描边环,压在线上也分得开 */
102
+ .xh-scope-sparkline[data-part='dot'] {
103
+ fill: var(--xh-_sparkline-accent);
104
+ stroke: var(--xh-chart-surface);
105
+ stroke-width: var(--xh-chart-gap);
106
+ }
107
+
108
+ /* 首次出现:折线从头描到尾,连接层在它入场的这一轮写 data-drawing 与 pathLength="1",过渡结束即撤掉 */
109
+ .xh-scope-sparkline[data-part='line'][data-drawing] {
110
+ stroke-dasharray: 1;
111
+ animation: xh-draw var(--xh-motion-duration-reveal) var(--xh-motion-ease-continuous) both;
112
+ }
113
+
114
+ /* 标记点等描线的笔尖扫到才淡入:连接层写入它占入场时长的比例,乘上入场时长就是延迟 */
115
+ .xh-scope-sparkline[data-part='dot'][data-drawing] {
116
+ animation: xh-fade-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter) both;
117
+ animation-delay: calc(var(--xh-motion-duration-reveal) * var(--xh-_chart-reveal-at));
118
+ }
119
+
120
+ /* 减弱动效下折线直接在场,只随过渡淡入。两组规则是同一件事的两个触发条件:系统偏好与作者打的 data-motion */
121
+ @media (prefers-reduced-motion: reduce) {
122
+ .xh-scope-sparkline[data-part='line'][data-drawing] {
123
+ animation: none;
124
+ }
125
+ }
126
+
127
+ :where([data-motion='reduce']) .xh-scope-sparkline[data-part='line'][data-drawing] {
128
+ animation: none;
129
+ }
130
+
131
+ /* 强制色:线与柱取系统文字色,标出的点与柱取强调色;面积不铺,参考带只留轮廓;
132
+ 盈亏的正负靠在中线上方还是下方表达,不靠颜色 */
133
+ @media (forced-colors: active) {
134
+ .xh-scope-sparkline[data-part='band'] {
135
+ fill: none;
136
+ stroke: GrayText;
137
+ stroke-width: var(--xh-stroke-thin);
138
+ }
139
+
140
+ .xh-scope-sparkline[data-part='reference-line'] {
141
+ stroke: CanvasText;
142
+ }
143
+
144
+ .xh-scope-sparkline[data-part='line'] {
145
+ stroke: CanvasText;
146
+ }
147
+
148
+ .xh-scope-sparkline[data-part='area-fill'] {
149
+ fill: none;
150
+ }
151
+
152
+ .xh-scope-sparkline[data-part='bar'],
153
+ .xh-scope-sparkline[data-part='bar'][data-trend] {
154
+ fill: CanvasText;
155
+ }
156
+
157
+ .xh-scope-sparkline[data-part='bar'][data-marker],
158
+ .xh-scope-sparkline[data-part='dot'] {
159
+ fill: Highlight;
160
+ }
161
+
162
+ .xh-scope-sparkline[data-part='dot'] {
163
+ stroke: Canvas;
164
+ }
165
+ }
166
+
167
+ .xh-scope-sparkline[data-part='root'][hidden] {
168
+ display: none;
169
+ }
170
+ }
@@ -0,0 +1,256 @@
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
+ /* 定义 spinner 样式。 */
7
+
8
+ /* 共享关键帧由 family/motion.css 提供,本皮肤 @import 它,单独引入仍成立。 */
9
+ @import '../family/motion.css';
10
+
11
+ @layer xihan.motion {
12
+ /* 三点档的波:一条亮带沿行扫过三枚点,点依次亮起再暗回禁用档,不再整组同步明暗 */
13
+ @keyframes xh-spinner-dots {
14
+ from {
15
+ -webkit-mask-position: 100% 0;
16
+ mask-position: 100% 0;
17
+ }
18
+
19
+ to {
20
+ -webkit-mask-position: 0 0;
21
+ mask-position: 0 0;
22
+ }
23
+ }
24
+ }
25
+
26
+ @layer xihan.components {
27
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
28
+ .xh-scope-spinner {
29
+ --xh-spinner-skin: 1;
30
+ }
31
+
32
+
33
+ /* 圆环画在伪元素上,root 自身不转:转的只是图形,同一行里的文案要留在原地读得动 */
34
+ .xh-scope-spinner[data-part='root'] {
35
+ display: inline-flex;
36
+ align-items: center;
37
+ gap: var(--xh-spinner-gap, var(--xh-control-gap-md));
38
+ line-height: var(--xh-leading-none);
39
+ pointer-events: none;
40
+ vertical-align: middle;
41
+ }
42
+
43
+ /* 竖排:转圈在上、配文在下居中,整块区域的等待用它 */
44
+ .xh-scope-spinner[data-part='root'][data-orientation='vertical'] {
45
+ flex-direction: column;
46
+ gap: var(--xh-spinner-gap, var(--xh-space-1_5));
47
+ }
48
+
49
+ /* 露面前的等待:整块藏起、位置照留,露面那一刻布局不跳;visibility 同时把它从读屏里摘掉 */
50
+ .xh-scope-spinner[data-part='root'][data-state='hidden'] {
51
+ visibility: hidden;
52
+ }
53
+
54
+ .xh-scope-spinner[data-part='root']::before {
55
+ content: '';
56
+
57
+ /* 边框算进直径,换厚度不会把圆环撑大 */
58
+ box-sizing: border-box;
59
+ flex: none;
60
+ inline-size: var(--xh-spinner-size, var(--xh-glyph-size-md));
61
+ block-size: var(--xh-spinner-size, var(--xh-glyph-size-md));
62
+ border: var(--xh-spinner-thickness, var(--xh-stroke-thick)) solid var(--xh-spinner-fg, var(--xh-fg-brand));
63
+
64
+ /* 一段 270° 的品牌色弧:起始边那一段是缺口(不画轨道,缺省透明),缺口转起来就看得出方向 */
65
+ border-block-start-color: var(--xh-spinner-track, transparent);
66
+ border-radius: var(--xh-spinner-radius, var(--xh-shape-circle));
67
+ animation: xh-spin var(--xh-spinner-duration, var(--xh-motion-loop-spin)) var(--xh-motion-ease-loop) infinite;
68
+ }
69
+
70
+ /* 三档直径走字形尺寸那把尺,与控件内图标同档(sm 16 / md 20 / lg 24):圆环与同一行文字里的图标同级,
71
+ 三档同族才不会在 compact 下错位。缺省档写在上面的基础规则里 */
72
+ .xh-scope-spinner[data-part='root'][data-size='sm']::before {
73
+ inline-size: var(--xh-glyph-size-sm);
74
+ block-size: var(--xh-glyph-size-sm);
75
+ }
76
+
77
+ .xh-scope-spinner[data-part='root'][data-size='lg']::before {
78
+ inline-size: var(--xh-glyph-size-lg);
79
+ block-size: var(--xh-glyph-size-lg);
80
+ }
81
+
82
+ /* 语气只换弧那三段,缺口照旧:弧与缺口的反差就是转向的读法。
83
+ 选择器上带 [data-tone] 是必需的:语气槽会沿继承流下来,不限定在写了语气的
84
+ 那个节点上,放在语气容器里的转圈会跟着一起改色 */
85
+ .xh-scope-spinner[data-part='root'][data-tone]::before {
86
+ border-color: var(--xh-spinner-fg, var(--xh-_tone));
87
+ border-block-start-color: var(--xh-spinner-track, transparent);
88
+ }
89
+
90
+ /*
91
+ * 渐隐弧:一整圈的色相由角度扫过来,再用一圈环形遮罩把中心挖空,剩下的就是一段
92
+ * 由浓到无的弧。转的还是同一条 xh-spin——这一档只换画法,不换节拍。
93
+ * 遮罩只吃 alpha,用 currentColor 当不透明的那一端即可。
94
+ */
95
+ .xh-scope-spinner[data-part='root'][data-variant='arc']::before {
96
+ border: 0;
97
+ background: conic-gradient(transparent, var(--xh-spinner-fg, var(--xh-fg-brand)));
98
+ -webkit-mask: radial-gradient(
99
+ farthest-side,
100
+ transparent calc(100% - var(--xh-spinner-thickness, var(--xh-stroke-thick))),
101
+ currentColor 0
102
+ );
103
+ mask: radial-gradient(
104
+ farthest-side,
105
+ transparent calc(100% - var(--xh-spinner-thickness, var(--xh-stroke-thick))),
106
+ currentColor 0
107
+ );
108
+ }
109
+
110
+ .xh-scope-spinner[data-part='root'][data-variant='arc'][data-tone]::before {
111
+ background: conic-gradient(transparent, var(--xh-spinner-fg, var(--xh-_tone)));
112
+ }
113
+
114
+ /*
115
+ * 三点:一行三枚圆点,依次亮起成一道波。它不转,因此圆角与描边都撤掉,
116
+ * 图形改由三层径向渐变画;点取品牌色,语气档只换这一处。
117
+ * 明暗不靠整组的不透明度(那样三点同步明灭,读起来像整体在闪),而是一层三倍宽的遮罩:
118
+ * 两端压在禁用档的不透明度,正中一道满不透明度的亮带,遮罩位置从行首外扫到行尾外,
119
+ * 亮带依次掠过三枚点。
120
+ */
121
+ .xh-scope-spinner[data-part='root'][data-variant='dots']::before {
122
+ --xh-_spinner-dot-dim: color-mix(in srgb, currentColor calc(var(--xh-state-disabled-opacity) * 100%), transparent);
123
+
124
+ border: 0;
125
+ border-radius: 0;
126
+ background:
127
+ radial-gradient(circle closest-side, var(--xh-spinner-fg, var(--xh-fg-brand)) 100%, transparent) 0 50% / 25% 25% no-repeat,
128
+ radial-gradient(circle closest-side, var(--xh-spinner-fg, var(--xh-fg-brand)) 100%, transparent) 50% 50% / 25% 25% no-repeat,
129
+ radial-gradient(circle closest-side, var(--xh-spinner-fg, var(--xh-fg-brand)) 100%, transparent) 100% 50% / 25% 25% no-repeat;
130
+ -webkit-mask: linear-gradient(90deg, var(--xh-_spinner-dot-dim) 40%, currentColor 50%, var(--xh-_spinner-dot-dim) 60%) 100% 0 / 300% 100% no-repeat;
131
+ mask: linear-gradient(90deg, var(--xh-_spinner-dot-dim) 40%, currentColor 50%, var(--xh-_spinner-dot-dim) 60%) 100% 0 / 300% 100% no-repeat;
132
+ animation: xh-spinner-dots var(--xh-spinner-duration, var(--xh-motion-loop-spin)) var(--xh-motion-ease-loop) infinite;
133
+ /* 波跟着书写方向走:三枚点左右对称,按书写方向符号水平翻过来,RTL 下就从右往左依次亮起 */
134
+ scale: var(--xh-direction-sign) 1;
135
+ }
136
+
137
+ .xh-scope-spinner[data-part='root'][data-variant='dots'][data-tone]::before {
138
+ background:
139
+ radial-gradient(circle closest-side, var(--xh-spinner-fg, var(--xh-_tone)) 100%, transparent) 0 50% / 25% 25% no-repeat,
140
+ radial-gradient(circle closest-side, var(--xh-spinner-fg, var(--xh-_tone)) 100%, transparent) 50% 50% / 25% 25% no-repeat,
141
+ radial-gradient(circle closest-side, var(--xh-spinner-fg, var(--xh-_tone)) 100%, transparent) 100% 50% / 25% 25% no-repeat;
142
+ }
143
+
144
+ /* 三点档的波自带一条动画,压不住上面那两块基础降级里的 animation: none,
145
+ 因此这一档各自再写一份;遮罩一并撤掉,三点满不透明度静止。两组规则是同一件事的两个触发条件 */
146
+ @media (prefers-reduced-motion: reduce) {
147
+ .xh-scope-spinner[data-part='root'][data-variant='dots']::before {
148
+ -webkit-mask: none;
149
+ mask: none;
150
+ animation: none;
151
+ }
152
+ }
153
+
154
+ :where([data-motion='reduce']) .xh-scope-spinner[data-part='root'][data-variant='dots']::before {
155
+ -webkit-mask: none;
156
+ mask: none;
157
+ animation: none;
158
+ }
159
+
160
+ @media print {
161
+ .xh-scope-spinner[data-part='root'][data-variant='dots']::before {
162
+ -webkit-mask: none;
163
+ mask: none;
164
+ animation: none;
165
+ }
166
+ }
167
+
168
+ /* 配文与转圈同一族颜色:品牌色、正文字号、中等字重 */
169
+ .xh-scope-spinner[data-part='label'] {
170
+ color: var(--xh-spinner-label-fg, var(--xh-fg-brand));
171
+ font-size: var(--xh-spinner-label-size, var(--xh-text-body-size));
172
+ font-weight: var(--xh-spinner-label-weight, var(--xh-font-weight-medium));
173
+ line-height: var(--xh-leading-none);
174
+ }
175
+
176
+ /* 减少动效:圆环停下并整圈换成虚线,静止的形状仍然读得出"这里还没好";
177
+ "在等什么"由 role=status 上的名字与可见文案继续承担。
178
+ 两组规则是同一件事的两个触发条件:系统偏好与作者打的 data-motion */
179
+ @media (prefers-reduced-motion: reduce) {
180
+ .xh-scope-spinner[data-part='root']::before {
181
+ border-style: dotted;
182
+ border-color: var(--xh-spinner-fg, var(--xh-fg-brand));
183
+ animation: none;
184
+ }
185
+
186
+ /* 静止态整圈同色,语气跟着铺满整圈 */
187
+ .xh-scope-spinner[data-part='root'][data-tone]::before {
188
+ border-color: var(--xh-spinner-fg, var(--xh-_tone));
189
+ }
190
+ }
191
+
192
+ :where([data-motion='reduce']) .xh-scope-spinner[data-part='root']::before {
193
+ border-style: dotted;
194
+ border-color: var(--xh-spinner-fg, var(--xh-fg-brand));
195
+ animation: none;
196
+ }
197
+
198
+ :where([data-motion='reduce']) .xh-scope-spinner[data-part='root'][data-tone]::before {
199
+ border-color: var(--xh-spinner-fg, var(--xh-_tone));
200
+ }
201
+
202
+ /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
203
+ 写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
204
+ .xh-scope-spinner[data-part='root'][hidden] {
205
+ display: none;
206
+ }
207
+
208
+ @media print {
209
+ /* 打印:动画会被定格在任意一帧——转了一半的圈、扫到一半的微光。这里换成静止的表达,
210
+ 取值与减弱动效那一档相同。两档各写一块、不并进一条媒体查询列表:减弱动效另有一份
211
+ :where([data-motion='reduce']) 的钩子版本与它成对,打印没有对应的钩子可配,
212
+ 并成一条之后这层配对关系在文本上就断了。 */
213
+ .xh-scope-spinner[data-part='root']::before {
214
+ border-style: dotted;
215
+ border-color: var(--xh-spinner-fg, var(--xh-fg-brand));
216
+ animation: none;
217
+ }
218
+
219
+ .xh-scope-spinner[data-part='root'][data-tone]::before {
220
+ border-color: var(--xh-spinner-fg, var(--xh-_tone));
221
+ }
222
+ }
223
+
224
+ /*
225
+ * 高对比档:这一档把整层背景图丢掉,而渐隐弧与三点都画在背景上——屏幕上会一片空白。
226
+ * 三档一并退回环档的画法:高亮色的弧加一段画布色的缺口,转的还是同一条动画。
227
+ * 伪元素退出强制换色、直接写系统色,缺口不被换成别的颜色。
228
+ * 带语气的那几条([data-tone]、[data-variant][data-tone])特指度更高,这里逐条写上同样的限定:
229
+ * 退出了强制换色的伪元素不会再被系统改色,少一条语气色的弧或渐变就原样画出来
230
+ */
231
+ @media (forced-colors: active) {
232
+ .xh-scope-spinner[data-part='root']::before,
233
+ .xh-scope-spinner[data-part='root'][data-tone]::before {
234
+ forced-color-adjust: none;
235
+ border-color: Highlight;
236
+ border-block-start-color: Canvas;
237
+ }
238
+
239
+ .xh-scope-spinner[data-part='root'][data-variant='arc']::before,
240
+ .xh-scope-spinner[data-part='root'][data-variant='arc'][data-tone]::before,
241
+ .xh-scope-spinner[data-part='root'][data-variant='dots']::before,
242
+ .xh-scope-spinner[data-part='root'][data-variant='dots'][data-tone]::before {
243
+ border: var(--xh-spinner-thickness, var(--xh-stroke-thick)) solid Highlight;
244
+ border-block-start-color: Canvas;
245
+ border-radius: var(--xh-spinner-radius, var(--xh-shape-circle));
246
+ background-image: none;
247
+ }
248
+
249
+ /* 三点档退回描边后撤掉扫点的遮罩,改转圆环那一条 */
250
+ .xh-scope-spinner[data-part='root'][data-variant='dots']::before {
251
+ -webkit-mask: none;
252
+ mask: none;
253
+ animation-name: xh-spin;
254
+ }
255
+ }
256
+ }
@@ -0,0 +1,159 @@
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
+ /* 定义 splitter 样式。 */
7
+
8
+ @layer xihan.components {
9
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
10
+ .xh-scope-splitter {
11
+ --xh-splitter-skin: 1;
12
+ }
13
+
14
+ /* 分工:**面板在排布轴上的尺寸**由连接层每帧写进内联样式(flex-basis / flex-grow / flex-shrink)。
15
+ 这份皮肤一条都不碰——内联优先级高于样式表,写了不但是死声明,
16
+ 还会在切换 orientation 的那一帧跟连接层抢位置。皮肤只管排布方向、跨轴尺寸、
17
+ 配色、光标与状态表现。
18
+
19
+ 三个角色节点上的 data-orientation 说的都是**面板怎么排**(与 root 上那条同源);
20
+ 分隔条自身的横竖与它垂直,那件事写在 aria-orientation 上,样式不去读 ARIA。 */
21
+
22
+ .xh-scope-splitter[data-part='root'] {
23
+ display: flex;
24
+ /* 跨轴尺寸由作者给:竖排的分栏必须先有确定的高度,才谈得上把它分成几份 */
25
+ align-items: stretch;
26
+ overflow: hidden;
27
+ border-radius: var(--xh-splitter-radius, var(--xh-shape-surface));
28
+ }
29
+
30
+ .xh-scope-splitter[data-part='root'][data-orientation='horizontal'] {
31
+ flex-direction: row;
32
+ }
33
+
34
+ .xh-scope-splitter[data-part='root'][data-orientation='vertical'] {
35
+ flex-direction: column;
36
+ }
37
+
38
+ /* 纯容器,焦点长在分隔条上,这里画环只会闪一下 */
39
+ .xh-scope-splitter[data-part='root']:focus-visible {
40
+ outline: none;
41
+ }
42
+
43
+ /* 禁用的整体压暗只做一次,落在最外层:面板与分隔条各自再叠一层 opacity 会越叠越黑。
44
+ 这一档压的是宿主塞进面板里的正文,不是控件自己的图形,所以地板比 --xh-state-disabled-opacity
45
+ 高:那一档是 0.5,黑字白底压完只有 3.94:1,读不出字。压暗仍要表达「这块动不了」,
46
+ 所以留一个槽让使用者按自己的配色调,而不是直接不压。 */
47
+ .xh-scope-splitter[data-part='root'][data-disabled] {
48
+ opacity: var(--xh-splitter-disabled-opacity, 0.6);
49
+ }
50
+
51
+ /* 拖动期间整块不许选中文字:手在分隔条上来回蹭时会顺带把两侧的正文刷成高亮 */
52
+ .xh-scope-splitter[data-part='root'][data-dragging] {
53
+ user-select: none;
54
+ }
55
+
56
+ /* 拖动中的光标写在容器上而不是分隔条上:那条线只有几像素宽,
57
+ 手一快指针就跑到面板上去了,光标随即变回箭头,看着像拖拽断了 */
58
+ .xh-scope-splitter[data-part='root'][data-orientation='horizontal'][data-dragging] {
59
+ cursor: col-resize;
60
+ }
61
+
62
+ .xh-scope-splitter[data-part='root'][data-orientation='vertical'][data-dragging] {
63
+ cursor: row-resize;
64
+ }
65
+
66
+ /* 面板自己不许把容器撑破:内容再宽也只能溢出自己这一格,
67
+ 否则连接层算好的比例会被一段长文本顶开 */
68
+ .xh-scope-splitter[data-part='panel'] {
69
+ position: relative;
70
+ overflow: hidden;
71
+ }
72
+
73
+ /* flex 项目的自动最小尺寸默认是内容宽,比 flex-basis 更硬——
74
+ 不把它挪开,连接层内联写的 basis / shrink 在内容超宽时会被静默架空。
75
+ 这两条给的不是尺寸,是"允许收到多小"的地板,因此不与内联样式冲突 */
76
+ .xh-scope-splitter[data-part='panel'][data-orientation='horizontal'] {
77
+ min-inline-size: 0;
78
+ }
79
+
80
+ .xh-scope-splitter[data-part='panel'][data-orientation='vertical'] {
81
+ min-block-size: 0;
82
+ }
83
+
84
+ .xh-scope-splitter[data-part='panel']:focus-visible {
85
+ outline: none;
86
+ }
87
+
88
+ /* 折叠 / 展开(Enter、双击、命令式)时面板尺寸走过渡,与 Layout 侧栏折叠同一种节奏;
89
+ 拖拽与方向键步进跟手,连接层不投影 data-animating,照旧瞬时。尺寸仍由连接层写内联,这里只挂过渡 */
90
+ .xh-scope-splitter[data-part='root'][data-animating] > .xh-scope-splitter[data-part='panel'] {
91
+ transition: flex-basis var(--xh-motion-duration-move) var(--xh-motion-ease-continuous);
92
+ }
93
+
94
+ /* 折叠到 0 时连边框都不该露出来:留一条缝比留一块面板更像坏了 */
95
+ .xh-scope-splitter[data-part='panel'][data-collapsed] {
96
+ border: none;
97
+ }
98
+
99
+ /* 分隔条自己的粗细归皮肤(连接层不碰它这条轴)。
100
+ flex: none 是必须的:它若跟着一起伸缩,面板的百分比就再也对不上了 */
101
+ .xh-scope-splitter[data-part='resize-trigger'] {
102
+ display: flex;
103
+ flex: none;
104
+ align-items: center;
105
+ justify-content: center;
106
+ background: var(--xh-splitter-trigger-bg, var(--xh-border-default));
107
+ transition: background-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
108
+ }
109
+
110
+ .xh-scope-splitter[data-part='resize-trigger'][data-orientation='horizontal'] {
111
+ inline-size: var(--xh-splitter-trigger-thickness, var(--xh-space-1));
112
+ cursor: col-resize;
113
+ }
114
+
115
+ .xh-scope-splitter[data-part='resize-trigger'][data-orientation='vertical'] {
116
+ block-size: var(--xh-splitter-trigger-thickness, var(--xh-space-1));
117
+ cursor: row-resize;
118
+ }
119
+
120
+ /* 分隔条是一根线不是一块面:悬停不走面阶梯(300 只留给 pressed),
121
+ 按线取——与字段描边 rest → hover 同向加深一档 */
122
+ .xh-scope-splitter[data-part='resize-trigger']:hover {
123
+ background: var(--xh-splitter-trigger-bg-hover, var(--xh-border-control));
124
+ }
125
+
126
+ /* 只有正被拖的那条带 data-dragging:多条分隔条时全高亮就分不出手在哪一条上 */
127
+ .xh-scope-splitter[data-part='resize-trigger'][data-dragging] {
128
+ background: var(--xh-splitter-trigger-bg-dragging, var(--xh-bg-brand));
129
+ }
130
+
131
+ /* 常态灰面与公共品牌环已经过线;拖动态才改用品牌面配对前景,避免同色环。 */
132
+ .xh-scope-splitter[data-part='resize-trigger'][data-dragging]:focus-visible {
133
+ --xh-_ring-color: var(--xh-fg-on-brand);
134
+ }
135
+
136
+ /* 分隔条是 div、role=separator,原生 disabled 在它身上不生效,
137
+ 禁用只表达成 aria-disabled 与 data-disabled,写 :disabled 永远不命中。
138
+ 光标不交给公共层:上面两条按走向给的 col-resize / row-resize 特异性相同又排在后面,
139
+ 公共层那条压不过它们 */
140
+ .xh-scope-splitter[data-part='resize-trigger'][data-disabled] {
141
+ background: var(--xh-splitter-trigger-bg-disabled, var(--xh-border-subtle));
142
+ cursor: not-allowed;
143
+ }
144
+
145
+ /* 给了 display 的角色节点必须补这条:display 声明会盖掉 UA 的 [hidden]{display:none},
146
+ 不补的话作者给节点加 hidden 后它照样显示 */
147
+ .xh-scope-splitter[data-part='root'][hidden],
148
+ .xh-scope-splitter[data-part='resize-trigger'][hidden] {
149
+ display: none;
150
+ }
151
+
152
+ @media (forced-colors: active) {
153
+ /* 分隔条画的是一块纯底色,这一档里底色被统一换成 Canvas,那条线整根消失,
154
+ 两侧面板就糊成一块。换成前景色画回来 */
155
+ .xh-scope-splitter[data-part='resize-trigger'] {
156
+ background: CanvasText;
157
+ }
158
+ }
159
+ }