@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,374 @@
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
+ /* 定义 slider 样式。 */
7
+
8
+ @layer xihan.components {
9
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
10
+ .xh-scope-slider {
11
+ --xh-slider-skin: 1;
12
+ }
13
+
14
+ /* 定位分工:已选区间与拇指在**主轴**上的起点与长度,由连接层每帧写进内联样式——
15
+ 水平是 inset-inline-start / inline-size,竖直是 inset-block-end / block-size。
16
+ 这份皮肤一个都不碰:内联优先级高于样式表,写了不但是死声明,
17
+ 切换 orientation 的那一帧还会跟连接层清空另一轴的动作抢位置,把拇指钉在两轴都被约束的地方。
18
+ 皮肤只管另一条轴(交叉轴)的尺寸、颜色、圆角与状态表现。 */
19
+
20
+ /* 私有槽位:组件令牌 → 中档字面量两级回退。轨道厚度与拇指直径同时被 control / track / thumb
21
+ 三个角色节点用到,收成两个槽位挂在 root 上,尺寸档只改这两处,靠继承发到子部件。 */
22
+ .xh-scope-slider[data-part='root'] {
23
+ --xh-_thumb-size: var(--xh-slider-thumb-size, var(--xh-track-thumb-size));
24
+ --xh-_track-thickness: var(--xh-slider-track-thickness, var(--xh-track-thickness));
25
+
26
+ display: flex;
27
+ flex-direction: column;
28
+ /* 字段标签贴控件(复合单字段) */
29
+ gap: var(--xh-slider-gap, var(--xh-space-1));
30
+ }
31
+
32
+ /* 竖排时整条控件收成一块,不再撑满一行:宽度由拇指直径决定 */
33
+ .xh-scope-slider[data-part='root'][data-orientation='vertical'] {
34
+ display: inline-flex;
35
+ align-items: center;
36
+ }
37
+
38
+ /* 禁用不整体压暗:前景与表面各自降级——连接层把 data-disabled 发到每个角色节点上,
39
+ 轨道、区间、拇指、刻度与标签就近消费,写在各自的规则里 */
40
+
41
+ /* 字段标签:14 / 500 / fg-default,禁用换到 --xh-fg-subtle */
42
+ .xh-scope-slider[data-part='label'] {
43
+ color: var(--xh-slider-label-fg, var(--xh-fg-default));
44
+ font-size: var(--xh-slider-label-font-size, var(--xh-text-label-size));
45
+ font-weight: var(--xh-slider-label-font-weight, var(--xh-text-label-weight));
46
+ }
47
+
48
+ .xh-scope-slider[data-part='label'][data-disabled] {
49
+ color: var(--xh-slider-label-fg-disabled, var(--xh-fg-subtle));
50
+ }
51
+
52
+ /* 拇指以它为定位上下文(拇指常常浮出轨道,挂在 track 上会被轨道的盒子束住)。
53
+ 厚度取拇指直径:轨道只有几个像素,控件若按轨道高,浮出来的拇指会顶到上下相邻的元素。
54
+ touch-action 由连接层内联给(拖动要接管手势),这里不写。 */
55
+ .xh-scope-slider[data-part='control'] {
56
+ position: relative;
57
+ display: flex;
58
+ align-items: center;
59
+ block-size: var(--xh-_thumb-size);
60
+ cursor: pointer;
61
+ }
62
+
63
+ /* 刻度文案以刻度为圆心横向摊开,首末两档各有一半落在轨道之外,页面因此恒多出半个文案的宽度。
64
+ 排了刻度文案的横轨两侧各让出一段,那半个文案落进让出来的这一段里。
65
+ 让在控件上而不是根上:轨道、刻度、拇指的坐标都以控件为基准,一起让开才不会彼此错位。 */
66
+ .xh-scope-slider[data-part='root']:has([data-part='tick-label'])
67
+ [data-part='control'][data-orientation='horizontal']:where(.xh-scope-slider) {
68
+ margin-inline: var(--xh-slider-control-gutter, var(--xh-space-6));
69
+ }
70
+
71
+ .xh-scope-slider[data-part='control'][data-orientation='vertical'] {
72
+ flex-direction: column;
73
+ justify-content: center;
74
+ inline-size: var(--xh-_thumb-size);
75
+ block-size: var(--xh-slider-vertical-length, 10rem);
76
+ }
77
+
78
+ /* 按下轨道即跳,拖动中光标换成"抓着"的样子,手感与拇指一致 */
79
+ .xh-scope-slider[data-part='control'][data-dragging] {
80
+ cursor: grabbing;
81
+ }
82
+
83
+ .xh-scope-slider[data-part='control'][data-readonly]:not([data-disabled]) {
84
+ cursor: default;
85
+ }
86
+
87
+ .xh-scope-slider[data-part='control'][data-disabled] {
88
+ cursor: not-allowed;
89
+ }
90
+
91
+ /* 已选区间以它为定位上下文。不写 overflow: hidden:作者把拇指写进轨道里也是合法结构,
92
+ 一裁就把拇指切掉半个;区间的圆角由它自己那条 border-radius 兜住,本就不靠轨道来裁。 */
93
+ .xh-scope-slider[data-part='track'] {
94
+ position: relative;
95
+ border-radius: var(--xh-slider-track-radius, var(--xh-shape-pill));
96
+ background: var(--xh-slider-track-bg, var(--xh-bg-subtle-active));
97
+ }
98
+
99
+ .xh-scope-slider[data-part='track'][data-orientation='horizontal'] {
100
+ inline-size: 100%;
101
+ block-size: var(--xh-_track-thickness);
102
+ }
103
+
104
+ .xh-scope-slider[data-part='track'][data-orientation='vertical'] {
105
+ block-size: 100%;
106
+ inline-size: var(--xh-_track-thickness);
107
+ }
108
+
109
+ /* 禁用:底槽退到 100 档淡底,已选区间换成禁用前景——两者仍分得开,值还读得出,只是没了品牌色 */
110
+ .xh-scope-slider[data-part='track'][data-disabled] {
111
+ background: var(--xh-slider-track-bg-disabled, var(--xh-bg-subtle));
112
+ }
113
+
114
+ /* 主轴(起点 + 长度)来自内联样式,这里只给定位模式与配色。
115
+ 绝不给 inset / size 加过渡:拖拽时这两个值每帧都在变,一加过渡区间就永远追在指针后面。
116
+ 语气槽由 root 上的 data-tone 声明、经继承发下来;没写 data-tone 时退回原来的品牌色。
117
+ 轨道不跟着换族:区间与拇指换色即可读出语气,底槽保持中性才不会盖掉"已选/未选"的对比。 */
118
+ .xh-scope-slider[data-part='range'] {
119
+ position: absolute;
120
+ border-radius: var(--xh-slider-range-radius, var(--xh-shape-pill));
121
+ background: var(--xh-slider-range-bg, var(--xh-_tone, var(--xh-bg-brand)));
122
+ }
123
+
124
+ /* 交叉轴铺满轨道。这一侧的 inset 连接层每帧写成空串(即不设),样式表接手才有确定值;
125
+ 不写的话绝对定位会退回"静态位置",作者一给轨道加内边距就对不齐了。 */
126
+ .xh-scope-slider[data-part='range'][data-orientation='horizontal'] {
127
+ inset-block-start: 0;
128
+ block-size: 100%;
129
+ }
130
+
131
+ .xh-scope-slider[data-part='range'][data-orientation='vertical'] {
132
+ inset-inline-start: 0;
133
+ inline-size: 100%;
134
+ }
135
+
136
+ /* 两端拇指之间可以整段拖动:区间给出「抓得住」的光标,拖动中换成「抓着」 */
137
+ .xh-scope-slider[data-part='range'][data-draggable] {
138
+ cursor: grab;
139
+ }
140
+
141
+ .xh-scope-slider[data-part='range'][data-draggable][data-dragging] {
142
+ cursor: grabbing;
143
+ }
144
+
145
+ .xh-scope-slider[data-part='range'][data-invalid] {
146
+ background: var(--xh-slider-range-bg-invalid, var(--xh-border-invalid));
147
+ }
148
+
149
+ .xh-scope-slider[data-part='range'][data-disabled] {
150
+ background: var(--xh-slider-range-bg-disabled, var(--xh-fg-disabled));
151
+ }
152
+
153
+ /* 圆点浮在轨道之上:轨道是流内的,拇指是绝对定位的,天然后来居上,不必再堆 z-index。
154
+ box-sizing 必须显式写:描边要吃进直径里,否则实际盒子比 --xh-_thumb-size 宽两条边,
155
+ 下面按半个直径回拉的负外边距就对不上圆心。
156
+ 拇指是可拖起的 raised 面:描边取装饰边(不透明档),raised 影只是加成、不作边界 */
157
+ .xh-scope-slider[data-part='thumb'] {
158
+ position: absolute;
159
+ box-sizing: border-box;
160
+ inline-size: var(--xh-_thumb-size);
161
+ block-size: var(--xh-_thumb-size);
162
+ /* 描边取装饰边的不透明档:墨色描边半透明,压在圆点自己的底上只会是底色的深一档,框不住圆点,
163
+ 拇指就与同色的已选区间糊成一片 */
164
+ border: var(--xh-stroke-thick) solid var(--xh-slider-thumb-border, var(--xh-border-default-opaque));
165
+ border-radius: var(--xh-slider-thumb-radius, var(--xh-shape-circle));
166
+ background: var(--xh-slider-thumb-bg, var(--xh-_tone, var(--xh-bg-brand)));
167
+ /* 圆点上没有字,这一支是给环用的:环灌 currentColor 时取到的是与这块底配对的前景色,
168
+ 不写就取到从页面继承下来的正文色 */
169
+ color: var(--xh-_tone-on, var(--xh-fg-on-brand));
170
+ box-shadow: var(--xh-slider-thumb-shadow, var(--xh-elevation-raised));
171
+ cursor: grab;
172
+ transition:
173
+ scale var(--xh-motion-duration-nudge) var(--xh-motion-ease-enter-strong),
174
+ box-shadow var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
175
+ }
176
+
177
+ /* 面是实心的,环色与面同族,画在面里就看不出来;环改取面自己的前景色——
178
+ 那一族色本来就要在这块面上把字读清楚,与面的对比是按可读性定的。
179
+ 禁用的拇指退成白面,不在这一档里,吃库环 */
180
+ .xh-scope-slider[data-part='thumb']:not([data-disabled]):focus-visible {
181
+ --xh-_ring-color: currentColor;
182
+ }
183
+
184
+ /* 内联样式把 inset-inline-start 定在值所在的比例上,那是拇指的**起始边**不是圆心;
185
+ 用负的逻辑外边距回拉半个直径,圆心才落在比例点上。
186
+ 这里刻意不用 translate(-50%):rtl 下 inset-inline-start 映射到 right,
187
+ 位移量是物理方向的,会把拇指推向错误的一侧;负的逻辑外边距自己就跟着换向。
188
+ 交叉轴同理:inset-block-start 是连接层不写的那条轴,样式表接管即可。 */
189
+ .xh-scope-slider[data-part='thumb'][data-orientation='horizontal'] {
190
+ inset-block-start: 50%;
191
+ margin-block-start: calc(var(--xh-_thumb-size) / -2);
192
+ margin-inline-start: calc(var(--xh-_thumb-size) / -2);
193
+ }
194
+
195
+ /* 竖排的主轴是 inset-block-end(值向上增大),回拉也就换到 block-end 那侧 */
196
+ .xh-scope-slider[data-part='thumb'][data-orientation='vertical'] {
197
+ inset-inline-start: 50%;
198
+ margin-inline-start: calc(var(--xh-_thumb-size) / -2);
199
+ margin-block-end: calc(var(--xh-_thumb-size) / -2);
200
+ }
201
+
202
+ /* 多拇指时只有手真正推着的那一个带 data-dragging,放大与光标因此不会全组一起变。
203
+ 放大用 scale 而不是改尺寸:变换绕自身中心发生,圆心不动,负外边距的算式也不用跟着改。
204
+ 海拔从静态的 raised 换到 lifted:跟着手走的东西比贴在页面上的抬得高一档,
205
+ 又不到锚定浮层那一层——用 floating 会让拇指和下拉面板一样重。 */
206
+ .xh-scope-slider[data-part='thumb'][data-dragging] {
207
+ /* 放大比例落进私有槽:挂在拇指里的值气泡读同一支反向缩回原尺寸 */
208
+ --xh-_slider-thumb-scale: var(--xh-slider-thumb-scale-dragging, var(--xh-motion-scale-drag));
209
+
210
+ scale: var(--xh-_slider-thumb-scale);
211
+ cursor: grabbing;
212
+ box-shadow: var(--xh-slider-thumb-shadow-dragging, var(--xh-elevation-lifted));
213
+ }
214
+
215
+ .xh-scope-slider[data-part='thumb'][data-invalid] {
216
+ background: var(--xh-slider-thumb-bg-invalid, var(--xh-border-invalid));
217
+ }
218
+
219
+ .xh-scope-slider[data-part='thumb'][data-readonly]:not([data-disabled]) {
220
+ cursor: default;
221
+ }
222
+
223
+ /* 禁用:面退到实体白面、描边留着、影收掉——拖不起来的东西不该看着像浮在轨道上。
224
+ 不写 color:圆点上没有字,禁用拇指不进 Tab 序列也不会聚焦,环的前景在这里没有消费者 */
225
+ .xh-scope-slider[data-part='thumb'][data-disabled] {
226
+ background: var(--xh-slider-thumb-bg-disabled, var(--xh-bg-surface));
227
+ box-shadow: var(--xh-slider-thumb-shadow-disabled, none);
228
+ cursor: not-allowed;
229
+ }
230
+
231
+ /* 值气泡:挂在拇指里,跟着拇指一起走位。
232
+ 气泡宽度由文字撑出,只能靠平移回中。不能两侧 inset 都钉在 50% 再靠自动外边距回中:
233
+ 那样可用宽度是 0,气泡比它宽,自动外边距按规范取 0,气泡从拇指中线起排、偏出半个自身宽。
234
+ 起点是逻辑属性、平移是物理通道:平移乘书写方向的符号,rtl 下行内分量掉头,气泡才落回拇指正上方。
235
+ 拖动时拇指放大,气泡按同一比例反向缩回、与拇指同一段过渡:文字不跟着放大,缩放原点在贴着拇指那一边。
236
+ 默认只在推动那一刻露面,静止时留在 DOM 里但不占视线 */
237
+ .xh-scope-slider[data-part='value-text'] {
238
+ position: absolute;
239
+ inset-block-end: 100%;
240
+ inset-inline-start: 50%;
241
+ inline-size: max-content;
242
+ margin-block-end: var(--xh-slider-value-text-offset, var(--xh-space-2));
243
+ translate: calc(-50% * var(--xh-direction-sign)) 0;
244
+ transform-origin: 50% 100%;
245
+ padding-block: var(--xh-slider-value-text-py, var(--xh-space-0_5));
246
+ padding-inline: var(--xh-slider-value-text-px, var(--xh-space-2));
247
+ border-radius: var(--xh-slider-value-text-radius, var(--xh-shape-control));
248
+ background: var(--xh-slider-value-text-bg, var(--xh-_tone, var(--xh-bg-brand)));
249
+ color: var(--xh-slider-value-text-fg, var(--xh-_tone-on, var(--xh-fg-on-brand)));
250
+ font-size: var(--xh-slider-value-text-font-size, var(--xh-text-caption-size));
251
+ line-height: var(--xh-leading-normal);
252
+ white-space: nowrap;
253
+ /* 气泡贴在拇指上方,指针要落到拇指上,不能被它挡住 */
254
+ pointer-events: none;
255
+ opacity: 0;
256
+ transition:
257
+ opacity var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
258
+ scale var(--xh-motion-duration-nudge) var(--xh-motion-ease-enter-strong);
259
+ }
260
+
261
+ .xh-scope-slider[data-part='value-text'][hidden] {
262
+ display: none;
263
+ }
264
+
265
+ /* 只有手真正推着的那一个拇指带 data-dragging,多拇指时气泡不会全组一起冒出来 */
266
+ .xh-scope-slider[data-part='value-text'][data-dragging] {
267
+ opacity: 1;
268
+ scale: calc(1 / var(--xh-_slider-thumb-scale, 1));
269
+ }
270
+
271
+ /* 竖排轨道的气泡挪到行侧:压在拇指上方会挡住上一档的值;反向缩放的原点换到贴着拇指的行首那一侧 */
272
+ .xh-scope-slider[data-part='value-text'][data-orientation='vertical'] {
273
+ inset-block: 50%;
274
+ inset-inline: 100% auto;
275
+ block-size: max-content;
276
+ margin-block: auto;
277
+ margin-inline: var(--xh-slider-value-text-offset, var(--xh-space-2)) 0;
278
+ transform-origin: calc(50% - 50% * var(--xh-direction-sign)) 50%;
279
+ }
280
+
281
+ /* —— 尺寸 —— */
282
+ /* 尺寸只改 root 上那两个槽位,control / track / thumb 跟着一起走;中间档不写规则,缺省即中档。
283
+ 两档都保持"拇指是轨道的三倍厚"这个比例,换档时圆点与底槽的关系看着不变。 */
284
+ .xh-scope-slider[data-part='root'][data-size='sm'] {
285
+ --xh-_thumb-size: var(--xh-slider-thumb-size, var(--xh-space-3));
286
+ --xh-_track-thickness: var(--xh-slider-track-thickness, var(--xh-space-1));
287
+ }
288
+
289
+ .xh-scope-slider[data-part='root'][data-size='lg'] {
290
+ --xh-_thumb-size: var(--xh-slider-thumb-size, var(--xh-space-6));
291
+ --xh-_track-thickness: var(--xh-slider-track-thickness, var(--xh-space-2));
292
+ }
293
+
294
+ /* —— 刻度:圆点钉在轨道上、文案排在轨道外侧,坐标由连接层按百分比内联给出 —— */
295
+ .xh-scope-slider[data-part='tick-group'] {
296
+ position: absolute;
297
+ inset: 0;
298
+ pointer-events: none;
299
+ }
300
+
301
+ /* 刻度点是正方盒,取 circle(正方盒不得用 pill 冒充圆) */
302
+ .xh-scope-slider[data-part='tick'] {
303
+ position: absolute;
304
+ inset-block-start: 50%;
305
+ inline-size: var(--xh-slider-tick-size, var(--xh-space-1));
306
+ block-size: var(--xh-slider-tick-size, var(--xh-space-1));
307
+ border-radius: var(--xh-slider-tick-radius, var(--xh-shape-circle));
308
+ background: var(--xh-slider-tick-bg, var(--xh-border-strong));
309
+ /* 连接层把比例点写在 inset-inline-start 上:平移的行内分量乘书写方向的符号,rtl 下掉头,刻度点才以比例点为中心 */
310
+ translate: calc(-50% * var(--xh-direction-sign)) -50%;
311
+ }
312
+
313
+ /* 落进已选区间的刻度点跟 range 同色 */
314
+ .xh-scope-slider[data-part='tick'][data-passed] {
315
+ background: var(--xh-slider-tick-bg-active, var(--xh-_tone, var(--xh-bg-brand)));
316
+ }
317
+
318
+ .xh-scope-slider[data-part='tick-label'] {
319
+ position: absolute;
320
+ inset-block-start: 100%;
321
+ margin-block-start: var(--xh-slider-tick-label-gap, var(--xh-space-1));
322
+ color: var(--xh-slider-tick-label-fg, var(--xh-fg-subtle));
323
+ font-size: var(--xh-slider-tick-label-font-size, var(--xh-text-caption-size));
324
+ line-height: var(--xh-leading-none);
325
+ white-space: nowrap;
326
+ translate: calc(-50% * var(--xh-direction-sign)) 0;
327
+ cursor: pointer;
328
+ pointer-events: auto;
329
+ user-select: none;
330
+ }
331
+
332
+ .xh-scope-slider[data-part='tick-label'][data-passed] {
333
+ color: var(--xh-slider-tick-label-fg-active, var(--xh-fg-default));
334
+ }
335
+
336
+ /* 禁用:刻度点与文案由 tick-group 上的 data-disabled 下发(连接层不给每个刻度单发),
337
+ 已过的刻度点与区间同色,文案换禁用前景,点它跳档的手型收掉 */
338
+ .xh-scope-slider[data-part='tick-group'][data-disabled] [data-part='tick']:where(.xh-scope-slider) {
339
+ background: var(--xh-slider-tick-bg-disabled, var(--xh-border-default));
340
+ }
341
+
342
+ .xh-scope-slider[data-part='tick-group'][data-disabled] [data-part='tick'][data-passed]:where(.xh-scope-slider) {
343
+ background: var(--xh-slider-tick-bg-active-disabled, var(--xh-fg-disabled));
344
+ }
345
+
346
+ .xh-scope-slider[data-part='tick-group'][data-disabled] [data-part='tick-label']:where(.xh-scope-slider) {
347
+ color: var(--xh-slider-tick-label-fg-disabled, var(--xh-fg-disabled));
348
+ cursor: not-allowed;
349
+ }
350
+
351
+ /* 竖直轨道:点与文案换轴,坐标由连接层写在 block 轴上 */
352
+ .xh-scope-slider[data-part='root'][data-orientation='vertical'] [data-part='tick']:where(.xh-scope-slider) {
353
+ inset-block-start: auto;
354
+ inset-inline-start: 50%;
355
+ translate: calc(-50% * var(--xh-direction-sign)) 50%;
356
+ }
357
+
358
+ .xh-scope-slider[data-part='root'][data-orientation='vertical'] [data-part='tick-label']:where(.xh-scope-slider) {
359
+ inset-block-start: auto;
360
+ inset-inline-start: 100%;
361
+ margin-block-start: 0;
362
+ margin-inline-start: var(--xh-slider-tick-label-gap, var(--xh-space-1));
363
+ translate: 0 50%;
364
+ }
365
+
366
+ /* display 会盖掉 UA 的 [hidden]{display:none},凡是被赋了 display 的角色节点都要显式让位 */
367
+ .xh-scope-slider[data-part='root'][hidden],
368
+ .xh-scope-slider[data-part='control'][hidden] {
369
+ display: none;
370
+ }
371
+
372
+ /* hidden-input 是 type=hidden 的原生输入,浏览器本就不渲染它,
373
+ 这里一条声明都不给:给了 display / 尺寸反而会把它拽回布局里,在拇指内部撑出一块空白。 */
374
+ }
@@ -0,0 +1,228 @@
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
+ /* 定义 sortable 样式。 */
7
+
8
+ /* Sortable 独立皮肤同时传递引入把手的动作控件配方;full bundle 递归去重。 */
9
+ @import '../family/action-control.css';
10
+
11
+ @layer xihan.components {
12
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
13
+ .xh-scope-sortable {
14
+ --xh-sortable-skin: 1;
15
+ }
16
+
17
+ /* 分工:**每一项的位移**由连接层每帧写进内联 translate(让位与跟手都在那儿算)。
18
+ 这份皮肤一条都不碰 translate——内联优先级更高,写了不但是死声明,
19
+ 还会在拖动的每一帧跟连接层抢位置。皮肤只管排布方向、间距、光标与状态表现。 */
20
+
21
+ .xh-scope-sortable[data-part='root'] {
22
+ display: flex;
23
+ gap: var(--xh-sortable-gap, var(--xh-space-2));
24
+ }
25
+
26
+ /* 拖动期间关掉选中:整项可拖时按下不 preventDefault,不关这条会一路刷蓝 */
27
+ .xh-scope-sortable[data-part='root'][data-dragging] {
28
+ user-select: none;
29
+ }
30
+
31
+ .xh-scope-sortable[data-part='root'][data-orientation='vertical'] {
32
+ flex-direction: column;
33
+ }
34
+
35
+ .xh-scope-sortable[data-part='root'][data-orientation='horizontal'] {
36
+ flex-direction: row;
37
+ }
38
+
39
+ /* 换行网格:主轴横排、允许折行,落点按最近中心判,与单轴那两档是不同的判据 */
40
+ .xh-scope-sortable[data-part='root'][data-orientation='both'] {
41
+ flex-direction: row;
42
+ flex-wrap: wrap;
43
+ }
44
+
45
+ /* 项里面放什么、怎么排全是使用者的事:这里不给 display 也不给间距。
46
+ 给了会盖掉使用者自己的单元格布局——网格里的一格被压成 flex 行之后就不再撑满,
47
+ 看起来像是尺寸算错了。皮肤只管拖起来那一项的视觉反馈。 */
48
+
49
+ /* 让位期间关掉过渡,跟手的那一项才不会慢半拍粘在指针后面。
50
+ 其余项反过来要过渡:它们是被让开的,瞬移会看不出发生了什么。
51
+ 键盘拖动时被拖那一项不跟手、逐格挪,与让位的邻项同一段一起滑;抓起时的抬升照常淡变。
52
+ 同组别的列表的一项悬在这里(data-drop='inside')时,插入点及其后的项同样是被让开的 */
53
+ .xh-scope-sortable[data-part='root']:is([data-dragging], [data-drop='inside']) [data-part='item']:where(.xh-scope-sortable):not([data-dragging]) {
54
+ transition: translate var(--xh-motion-duration-nudge) var(--xh-motion-ease-continuous);
55
+ }
56
+
57
+ /* 让位把末项挪出了原来的末端:容器末尾垫出落进来那一格的大小(连接层写进 --xh-_sortable-incoming-size),
58
+ 容器随之长出一格,末项不会掉出容器的面。垫块是一个 flex 子项,沿主轴取那一格的尺寸、与各项之间同样隔一个 gap;
59
+ 列表为空时它是唯一的子项,不带 gap,正好是那一格 */
60
+ .xh-scope-sortable[data-part='root'][data-drop='inside']::after {
61
+ content: '';
62
+ flex: 0 0 var(--xh-_sortable-incoming-size);
63
+ }
64
+
65
+ .xh-scope-sortable[data-part='root'][data-drag-mode='keyboard'] [data-part='item'][data-dragging]:where(.xh-scope-sortable) {
66
+ transition:
67
+ translate var(--xh-motion-duration-nudge) var(--xh-motion-ease-continuous),
68
+ box-shadow var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
69
+ opacity var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
70
+ }
71
+
72
+ /* 抓起与放下时的抬升、压深都淡变。位移不进这条:它由连接层每帧写内联 translate */
73
+ .xh-scope-sortable[data-part='item'] {
74
+ transition:
75
+ box-shadow var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
76
+ opacity var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
77
+ }
78
+
79
+ /* 放下后那一项由弹簧带着松手速度逐帧收进新位置:只在这一档备好合成层,落定即撤 */
80
+ .xh-scope-sortable[data-part='item'][data-animating] {
81
+ will-change: translate;
82
+ }
83
+
84
+ .xh-scope-sortable[data-part='item'][data-dragging] {
85
+ /* 拖起来的那一项浮在上面。层级由连接层写内联,这里只管观感。
86
+ 海拔取 lifted:被指针拎起、正跟着手走的东西比贴在页面上的 raised 高一档,又不到锚定浮层那一层。
87
+ 拖起的面是作者自己的内容,皮肤不给它强加描边——描边归作者的项目布局 */
88
+ box-shadow: var(--xh-sortable-item-shadow-dragging, var(--xh-elevation-lifted));
89
+ opacity: var(--xh-sortable-item-opacity-dragging, 0.9);
90
+ }
91
+
92
+ /* 把手是只有字形的离散动作钮(定尺把手):盒几何、悬停 / 按下与 0.97 按压、粗指针热区、焦点环、
93
+ 禁用面全由 Action Control 的 icon ghost 档给(连接层投 xs:24px 正方盒,与此前 --xh-control-action-size
94
+ 同尺寸),组件只映射既有使用者槽。静息透明,白底承载 hover 100 → pressed 200(此前悬停落 200 是错档)。
95
+ 手型不是 pointer:抓起来拖的东西给 grab,按住拖动中给 grabbing;家族的手型槽逐态映射 */
96
+ .xh-scope-sortable[data-part='item-drag-trigger'] {
97
+ --xh-action-visual-size: var(--xh-sortable-drag-size, var(--xh-_action-profile-visual-size));
98
+ --xh-action-min-inline-size: var(--xh-sortable-drag-size, var(--xh-_action-profile-visual-size));
99
+ --xh-action-radius: var(--xh-sortable-drag-radius, var(--xh-shape-control));
100
+ --xh-action-bg-hover: var(--xh-sortable-drag-bg-hover, var(--xh-_action-variant-bg-hover));
101
+ --xh-action-bg-pressed: var(--xh-sortable-drag-bg-active, var(--xh-_action-variant-bg-pressed));
102
+ --xh-action-fg-rest: var(--xh-sortable-drag-fg, var(--xh-fg-muted));
103
+ --xh-action-fg-hover: var(--xh-sortable-drag-fg-hover, var(--xh-fg-default));
104
+ --xh-action-fg-pressed: var(--xh-sortable-drag-fg-hover, var(--xh-fg-default));
105
+ --xh-action-fg-disabled: var(--xh-sortable-drag-fg-disabled, var(--xh-fg-disabled));
106
+ --xh-action-border-rest: transparent;
107
+ --xh-action-highlight-rest: transparent;
108
+ --xh-action-shadow-rest: none;
109
+ --xh-action-shadow-hover: none;
110
+ --xh-action-shadow-pressed: none;
111
+ --xh-action-cursor-rest: grab;
112
+ --xh-action-cursor-hover: grab;
113
+ --xh-action-cursor-focus-visible: grab;
114
+ --xh-action-cursor-pressed: grabbing;
115
+ /* 作者塞进把手的图标按档取字形尺(xs → 16px);皮肤画的兜底抓手是两条描边线,不走这把尺 */
116
+ --xh-icon-size: var(--xh-sortable-drag-icon-size, var(--xh-_action-profile-glyph-size));
117
+
118
+ border-width: 0;
119
+ }
120
+
121
+ /* 抓手是两条竖线:盒子取边框盒,两侧描边就是那两条线,宽高与线宽都走令牌。
122
+ :empty 守卫让作者塞进来的图标整个顶掉它,而不是两份叠在一起。
123
+ 不画这条的话按钮里空无一物,只剩一块摸不着边的透明命中区 */
124
+ .xh-scope-sortable[data-part='item-drag-trigger']:empty::after {
125
+ content: '';
126
+ display: block;
127
+ inline-size: var(--xh-sortable-drag-grip-w, var(--xh-space-1));
128
+ block-size: var(--xh-sortable-drag-grip-h, var(--xh-space-3));
129
+ border-inline: var(--xh-stroke-thin) solid currentColor;
130
+ }
131
+
132
+ /* 手指落点:家族 icon 档用 ::after 把命中区扩到 44×44;没塞图标的把手 ::after 已被抓手占着,
133
+ 抓手那条只写了宽高与描边,家族的定位、44px 下限与 -50% 平移会从同一个 ::after 漏进来,
134
+ 两条竖线被撑成 44px 高、跨出把手——这里逐项钉回,热区改由空着的 ::before 扩;
135
+ 作者塞了图标时 :empty 不成立,家族的 ::after 照常落下 */
136
+ @media (pointer: coarse) {
137
+ .xh-scope-sortable[data-part='item-drag-trigger']:empty::after {
138
+ position: static;
139
+ min-inline-size: 0;
140
+ min-block-size: 0;
141
+ translate: none;
142
+ }
143
+
144
+ .xh-scope-sortable[data-part='item-drag-trigger']:empty::before {
145
+ content: '';
146
+ position: absolute;
147
+ inset-block-start: 50%;
148
+ inset-inline-start: 50%;
149
+ min-inline-size: 44px;
150
+ min-block-size: 44px;
151
+ inline-size: 100%;
152
+ block-size: 100%;
153
+ translate: -50% -50%;
154
+ }
155
+
156
+ /* 与家族同一笔:起点是逻辑属性、平移是物理通道,rtl 下行内分量掉头,热区才落回把手中心 */
157
+ .xh-scope-sortable[data-part='item-drag-trigger']:empty:dir(rtl)::before {
158
+ translate: 50% -50%;
159
+ }
160
+ }
161
+
162
+ /* 拖动中(指针按住或键盘拾起):光标换成"抓着"的样子,各态的手型槽一并换掉——
163
+ 家族的悬停 / 按下块比这条特指度高,直接写 cursor 会被盖回去 */
164
+ .xh-scope-sortable[data-part='item-drag-trigger'][data-dragging] {
165
+ --xh-action-cursor-rest: grabbing;
166
+ --xh-action-cursor-hover: grabbing;
167
+ --xh-action-cursor-focus-visible: grabbing;
168
+ --xh-action-cursor-pressed: grabbing;
169
+ }
170
+
171
+ /* 落点线:容器的绝对定位子节点,起点与长度由连接层每帧写内联,这里只给粗细与颜色。
172
+ 容器要自建定位上下文,线才落在它自己的坐标系里 */
173
+ .xh-scope-sortable[data-part='root']:has([data-part='drop-indicator']) {
174
+ position: relative;
175
+ }
176
+
177
+ /* 不写层号:它是定位子节点,写在末项之后就画在各项之上,组件内不另立层序 */
178
+ .xh-scope-sortable[data-part='drop-indicator'] {
179
+ position: absolute;
180
+ display: block;
181
+ /* 线不接指针:它盖在项上面,接了就挡住落点那一格 */
182
+ pointer-events: none;
183
+ border-radius: var(--xh-sortable-drop-indicator-radius, var(--xh-shape-pill));
184
+ background: var(--xh-sortable-drop-indicator-bg, var(--xh-bg-brand));
185
+ /* 落点一格一格地跳,线跟着滑过去 */
186
+ transition: translate var(--xh-motion-duration-nudge) var(--xh-motion-ease-continuous);
187
+ }
188
+
189
+ /* 竖排时是一条横线铺满容器,横排与换行网格时是一条竖线 */
190
+ .xh-scope-sortable[data-part='drop-indicator'][data-orientation='vertical'] {
191
+ inline-size: 100%;
192
+ block-size: var(--xh-sortable-drop-indicator-size, var(--xh-stroke-thick));
193
+ }
194
+
195
+ .xh-scope-sortable[data-part='drop-indicator'][data-orientation='horizontal'],
196
+ .xh-scope-sortable[data-part='drop-indicator'][data-orientation='both'] {
197
+ inline-size: var(--xh-sortable-drop-indicator-size, var(--xh-stroke-thick));
198
+ block-size: 100%;
199
+ }
200
+
201
+ /* 落点线是一块纯底色,高对比档里底色被统一换成 Canvas,整根消失:换成系统高亮色画回来。
202
+ 跨列表时落在哪个列表只靠这条线与让出的那一格表出,这一档里同样要看得见 */
203
+ @media (forced-colors: active) {
204
+ .xh-scope-sortable[data-part='drop-indicator'] {
205
+ background: Highlight;
206
+ }
207
+ }
208
+
209
+ /* 活动区域只说给读屏听,不占版面。声明与 shared/visually-hidden.ts 逐条同值。 */
210
+ .xh-scope-sortable[data-part='live-region'] {
211
+ position: absolute;
212
+ inline-size: 1px;
213
+ block-size: 1px;
214
+ padding: 0;
215
+ margin: -1px;
216
+ overflow: hidden;
217
+ clip-path: inset(50%);
218
+ white-space: nowrap;
219
+ border: 0;
220
+ }
221
+ /* 给了 display 的角色节点必须补这条:display 声明会盖掉 UA 的 [hidden]{display:none},
222
+ 不补的话作者给节点加 hidden 后它照样显示 */
223
+ .xh-scope-sortable[data-part='root'][hidden],
224
+ .xh-scope-sortable[data-part='item-drag-trigger'][hidden],
225
+ .xh-scope-sortable[data-part='drop-indicator'][hidden] {
226
+ display: none;
227
+ }
228
+ }