@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,225 @@
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
+ /* 定义 icon 样式。 */
7
+
8
+ @layer xihan.components {
9
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
10
+ .xh-scope-icon {
11
+ --xh-icon-skin: 1;
12
+ }
13
+
14
+ /*
15
+ * 根 <svg>。直径、描边粗细、行内位置都由这里给,记录只带几何。
16
+ * 不写 fill / stroke:记录里那两条呈现属性取 currentColor,改这里会把
17
+ * 描边图标与实心图标一起改掉;皮肤只给 color,配色随上下文流下来。
18
+ */
19
+ .xh-scope-icon[data-part='root'] {
20
+ display: inline-block;
21
+ flex: none;
22
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-md));
23
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-md));
24
+
25
+ /* 替换元素的基线就是自身下边缘,落在文字基线上时整块图形都在基线以上、看着偏高。
26
+ 往下挪一小段,单位是 em,跟着相邻文字的字号一起缩放 */
27
+ vertical-align: var(--xh-icon-shift, var(--xh-glyph-baseline-shift));
28
+ color: var(--xh-icon-fg, currentColor);
29
+
30
+ /* 记录把 stroke-width 写成根上的呈现属性,呈现属性的层叠优先级低于任何 CSS 规则,
31
+ 这条与下面两档因此能接管粗细,再沿继承落到每个图元上 */
32
+ stroke-width: var(--xh-icon-stroke, var(--xh-glyph-stroke-regular));
33
+ }
34
+
35
+ /* 声明了 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去 */
36
+ .xh-scope-icon[data-part='root'][hidden] {
37
+ display: none;
38
+ }
39
+
40
+ /* 八档直径,缺省档 md 写在上面的基础规则里。
41
+ 每一档都把 --xh-icon-size 排在自己的档值前面:这个槽是外层统一图元直径的通道,
42
+ 档值直接写终值的话,写了 data-size 的那一枚就脱离外层控制,作者在祖先上的覆盖也改不动它 */
43
+ .xh-scope-icon[data-part='root'][data-size='text'] {
44
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
45
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
46
+ }
47
+
48
+ .xh-scope-icon[data-part='root'][data-size='sm'] {
49
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-sm));
50
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-sm));
51
+ }
52
+
53
+ .xh-scope-icon[data-part='root'][data-size='md'] {
54
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-md));
55
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-md));
56
+ }
57
+
58
+ .xh-scope-icon[data-part='root'][data-size='lg'] {
59
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-lg));
60
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-lg));
61
+ }
62
+
63
+ .xh-scope-icon[data-part='root'][data-size='xl'] {
64
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-xl));
65
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-xl));
66
+ }
67
+
68
+ .xh-scope-icon[data-part='root'][data-size='2xl'] {
69
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-2xl));
70
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-2xl));
71
+ }
72
+
73
+ .xh-scope-icon[data-part='root'][data-size='3xl'] {
74
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-3xl));
75
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-3xl));
76
+ }
77
+
78
+ .xh-scope-icon[data-part='root'][data-size='4xl'] {
79
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-4xl));
80
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-4xl));
81
+ }
82
+
83
+ /* 三档描边,缺省档同样写在基础规则里;--xh-icon-stroke 同样排在档值前面 */
84
+ .xh-scope-icon[data-part='root'][data-weight='light'] {
85
+ stroke-width: var(--xh-icon-stroke, var(--xh-glyph-stroke-light));
86
+ }
87
+
88
+ .xh-scope-icon[data-part='root'][data-weight='bold'] {
89
+ stroke-width: var(--xh-icon-stroke, var(--xh-glyph-stroke-bold));
90
+ }
91
+
92
+ /* 语气:图标没有底色,语气只落在前景上,取普通背景上表达该语气的那档文字色。
93
+ 选择器上带 [data-tone] 是必需的:语气槽会沿继承流下来,不限定在写了语气的
94
+ 那个节点上,放在语气容器里的装饰图标会跟着一起改色 */
95
+ .xh-scope-icon[data-part='root'][data-tone] {
96
+ color: var(--xh-icon-fg, var(--xh-_tone-fg, currentColor));
97
+ }
98
+
99
+ /* 旋转:四分之一圈的整数倍,是把箭头指向别处的结构性角度,不是可调幅度。
100
+ 没有过渡也没有动画——转到位就停在那儿,减弱动效那一档碰不到它 */
101
+ .xh-scope-icon[data-part='root'][data-rotate='90'] {
102
+ rotate: 90deg;
103
+ }
104
+
105
+ .xh-scope-icon[data-part='root'][data-rotate='180'] {
106
+ rotate: 180deg;
107
+ }
108
+
109
+ .xh-scope-icon[data-part='root'][data-rotate='270'] {
110
+ rotate: 270deg;
111
+ }
112
+
113
+ /* 翻转:沿轴取反,同样是静态几何。与旋转是两个独立属性,同写时自然叠加 */
114
+ .xh-scope-icon[data-part='root'][data-flip='horizontal'] {
115
+ scale: -1 1;
116
+ }
117
+
118
+ .xh-scope-icon[data-part='root'][data-flip='vertical'] {
119
+ scale: 1 -1;
120
+ }
121
+
122
+ .xh-scope-icon[data-part='root'][data-flip='both'] {
123
+ scale: -1 -1;
124
+ }
125
+
126
+ /* —— 底框 —— */
127
+ /*
128
+ * 加了框的图标是一个定直径的圆底座:框画在 <svg> 自己的盒上,图元落在内容盒里居中。
129
+ * sm / md / lg 三档框与头像同档(取同一支控件高度令牌),图元按自己的档位取字形直径,
130
+ * 内衬由两者之差算出,框换档时图元跟着一起换。
131
+ * 框里的图元不读外层统一图元直径的通道 --xh-icon-size:框自己就是一个定尺对象,
132
+ * 落在按钮、提示条这类下发图元直径的容器里也不被改小。
133
+ * 排在档位与语气之后:框接管了盒的尺寸与配色。
134
+ */
135
+ .xh-scope-icon[data-part='root'][data-frame] {
136
+ /* 三档之外的档位经两支 step 槽给出字形直径与框直径,三档本身在下面的档位块里换 */
137
+ --xh-_icon-glyph: var(--xh-icon-frame-glyph-size, var(--xh-_icon-glyph-step, var(--xh-glyph-size-md)));
138
+ --xh-_icon-frame-size: var(--xh-icon-frame-size, var(--xh-_icon-frame-step, var(--xh-control-h-md)));
139
+
140
+ inline-size: var(--xh-_icon-frame-size);
141
+ block-size: var(--xh-_icon-frame-size);
142
+ padding: calc((var(--xh-_icon-frame-size) - var(--xh-_icon-glyph)) / 2 - var(--xh-stroke-thin));
143
+ border: var(--xh-stroke-thin) solid transparent;
144
+ border-radius: var(--xh-icon-frame-radius, var(--xh-shape-circle));
145
+ }
146
+
147
+ .xh-scope-icon[data-part='root'][data-frame][data-size='sm'] {
148
+ --xh-_icon-glyph: var(--xh-icon-frame-glyph-size, var(--xh-glyph-size-sm));
149
+ --xh-_icon-frame-size: var(--xh-icon-frame-size, var(--xh-control-h-sm));
150
+ }
151
+
152
+ .xh-scope-icon[data-part='root'][data-frame][data-size='lg'] {
153
+ --xh-_icon-glyph: var(--xh-icon-frame-glyph-size, var(--xh-glyph-size-lg));
154
+ --xh-_icon-frame-size: var(--xh-icon-frame-size, var(--xh-control-h-lg));
155
+ }
156
+
157
+ /* 头像只有三档;其余档的框沿用 md 档的内衬厚度:框直径 = 本档字形 + md 档框与字形之差 */
158
+ .xh-scope-icon[data-part='root'][data-frame][data-size='text'] {
159
+ --xh-_icon-glyph-step: var(--xh-glyph-size-text);
160
+ --xh-_icon-frame-step: calc(var(--xh-glyph-size-text) + var(--xh-control-h-md) - var(--xh-glyph-size-md));
161
+ }
162
+
163
+ .xh-scope-icon[data-part='root'][data-frame][data-size='xl'] {
164
+ --xh-_icon-glyph-step: var(--xh-glyph-size-xl);
165
+ --xh-_icon-frame-step: calc(var(--xh-glyph-size-xl) + var(--xh-control-h-md) - var(--xh-glyph-size-md));
166
+ }
167
+
168
+ .xh-scope-icon[data-part='root'][data-frame][data-size='2xl'] {
169
+ --xh-_icon-glyph-step: var(--xh-glyph-size-2xl);
170
+ --xh-_icon-frame-step: calc(var(--xh-glyph-size-2xl) + var(--xh-control-h-md) - var(--xh-glyph-size-md));
171
+ }
172
+
173
+ .xh-scope-icon[data-part='root'][data-frame][data-size='3xl'] {
174
+ --xh-_icon-glyph-step: var(--xh-glyph-size-3xl);
175
+ --xh-_icon-frame-step: calc(var(--xh-glyph-size-3xl) + var(--xh-control-h-md) - var(--xh-glyph-size-md));
176
+ }
177
+
178
+ .xh-scope-icon[data-part='root'][data-frame][data-size='4xl'] {
179
+ --xh-_icon-glyph-step: var(--xh-glyph-size-4xl);
180
+ --xh-_icon-frame-step: calc(var(--xh-glyph-size-4xl) + var(--xh-control-h-md) - var(--xh-glyph-size-md));
181
+ }
182
+
183
+ /* 框的四种形态只决定颜色怎么用;用哪族颜色由 data-tone 决定,没写语气取品牌实心 / 中性。
184
+ 语气只认自己身上的 data-tone:语气槽会沿继承流下来,放在语气容器里的框不跟着改色。
185
+ 实心档在顶边画一条极浅的内高光,把这块底座衬出厚度;另外三档面上没有实心底,不画 */
186
+ .xh-scope-icon[data-part='root'][data-frame='solid'] {
187
+ background: var(--xh-icon-frame-bg, var(--xh-bg-brand));
188
+ box-shadow: var(--xh-icon-frame-shadow, var(--xh-_highlight-brand));
189
+ color: var(--xh-icon-fg, var(--xh-fg-on-brand));
190
+ }
191
+
192
+ .xh-scope-icon[data-part='root'][data-frame='solid'][data-tone] {
193
+ background: var(--xh-icon-frame-bg, var(--xh-_tone));
194
+ box-shadow: var(--xh-icon-frame-shadow, var(--xh-_highlight-tone));
195
+ color: var(--xh-icon-fg, var(--xh-_tone-on));
196
+ }
197
+
198
+ .xh-scope-icon[data-part='root'][data-frame='subtle'] {
199
+ background: var(--xh-icon-frame-bg, var(--xh-bg-subtle));
200
+ color: var(--xh-icon-fg, var(--xh-fg-default));
201
+ }
202
+
203
+ .xh-scope-icon[data-part='root'][data-frame='subtle'][data-tone] {
204
+ background: var(--xh-icon-frame-bg, var(--xh-_tone-subtle));
205
+ color: var(--xh-icon-fg, var(--xh-_tone-fg));
206
+ }
207
+
208
+ .xh-scope-icon[data-part='root'][data-frame='outline'] {
209
+ border-color: var(--xh-icon-frame-border, var(--xh-border-default));
210
+ color: var(--xh-icon-fg, var(--xh-fg-default));
211
+ }
212
+
213
+ .xh-scope-icon[data-part='root'][data-frame='outline'][data-tone] {
214
+ border-color: var(--xh-icon-frame-border, var(--xh-_tone-border));
215
+ color: var(--xh-icon-fg, var(--xh-_tone-fg));
216
+ }
217
+
218
+ .xh-scope-icon[data-part='root'][data-frame='ghost'] {
219
+ color: var(--xh-icon-fg, var(--xh-fg-default));
220
+ }
221
+
222
+ .xh-scope-icon[data-part='root'][data-frame='ghost'][data-tone] {
223
+ color: var(--xh-icon-fg, var(--xh-_tone-fg));
224
+ }
225
+ }
@@ -0,0 +1,373 @@
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
+ /* 定义 image cropper 样式。 */
7
+
8
+ @import '../family/action-control.css';
9
+
10
+ @layer xihan.components {
11
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
12
+ .xh-scope-image-cropper {
13
+ --xh-image-cropper-skin: 1;
14
+ }
15
+
16
+ /* 定位分工:裁切框在视口里的 left / top / width / height,以及图片与裁切框的
17
+ transform,由连接层每帧写进内联样式——那四个数是图片像素换算出来的百分比,
18
+ 只有连接层算得出来。这份皮肤一个都不碰,写了不但是死声明,还会跟内联值抢位置。
19
+
20
+ 私有槽两个,都挂在 root 上靠继承发下去:
21
+ handle-size 是把手的边长,zoom 是当前缩放倍率——裁切框整体被 scale 放大,
22
+ 把手与描边要按倍率反向缩回去,否则放到 3 倍时把手也变成三倍大、描边变成三像素粗。 */
23
+ .xh-scope-image-cropper[data-part='root'] {
24
+ --xh-_image-cropper-handle-size: var(--xh-image-cropper-handle-size, var(--xh-control-indicator-size));
25
+ --xh-_image-cropper-zoom: 1;
26
+
27
+ position: relative;
28
+ display: block;
29
+ inline-size: var(--xh-image-cropper-w, 100%);
30
+ }
31
+
32
+ /* 量坐标的那个盒子。里面装的是图片像素坐标,不是文字:裁切框与把手的落点一律写物理属性,
33
+ 不依赖这里的文字方向。overflow 收口:放大后的图片与遮罩都靠它裁掉。 */
34
+ .xh-scope-image-cropper[data-part='viewport'] {
35
+ position: relative;
36
+ display: block;
37
+ overflow: hidden;
38
+ border-radius: var(--xh-image-cropper-viewport-radius, var(--xh-shape-surface));
39
+ background: var(--xh-image-cropper-bg, var(--xh-bg-muted));
40
+ user-select: none;
41
+ }
42
+
43
+ /* 图片铺满视口、高度自适应:视口的高度因此由图片撑出来,
44
+ 裁切框的百分比坐标才与图片的像素一一对应。 */
45
+ .xh-scope-image-cropper[data-part='image'] {
46
+ display: block;
47
+ inline-size: 100%;
48
+ block-size: auto;
49
+ }
50
+
51
+ /* 裁切框。遮罩用一圈超大的实心投影把框外压暗——不必再摆四块遮罩节点,
52
+ 圆形裁切时投影也自动跟着圆角走。描边按倍率缩回去,放大时仍是一根细线。 */
53
+ .xh-scope-image-cropper[data-part='crop-area'] {
54
+ --xh-_image-cropper-corner-radius: var(--xh-shape-control);
55
+
56
+ position: absolute;
57
+ box-sizing: border-box;
58
+ border-style: solid;
59
+ border-width: calc(var(--xh-stroke-thin) / var(--xh-_image-cropper-zoom));
60
+ border-color: var(--xh-image-cropper-crop-border, var(--xh-bg-surface));
61
+ box-shadow: 0 0 0 9999px var(--xh-image-cropper-mask, var(--xh-bg-overlay));
62
+ cursor: move;
63
+ }
64
+
65
+ /* 圆形裁切取 circle 档(50%):shape 的固定长度档画出来是胶囊不是椭圆,
66
+ 裁切框的宽高由数据决定、两边通常不等长,只有百分比才随框变成椭圆;圆角只能来自语义形状令牌 */
67
+ .xh-scope-image-cropper[data-part='crop-area'][data-shape='round'] {
68
+ --xh-_image-cropper-corner-radius: var(--xh-shape-circle);
69
+
70
+ border-radius: var(--xh-image-cropper-crop-area-radius, var(--xh-shape-circle));
71
+ }
72
+
73
+ .xh-scope-image-cropper[data-part='crop-area'][data-dragging] {
74
+ cursor: grabbing;
75
+ }
76
+
77
+ .xh-scope-image-cropper[data-part='crop-area'][data-readonly]:not([data-disabled]) {
78
+ cursor: default;
79
+ }
80
+
81
+ /* 三分构图参考线:两条竖线、两条横线,落点写死在三分处,不占节点、不吃指针。
82
+ 停靠点逐条写全而不用 repeating-:重复单元从 0 起算会在框的两条边缘上各多画一根,
83
+ 那两根与裁切框的描边叠在一起,看着像描边加粗了一倍。
84
+ 线宽跟着裁切框的倍率缩回去,与描边同一口径。
85
+ 圆形裁切时参考线没有意义,收起来。 */
86
+ .xh-scope-image-cropper[data-part='grid'] {
87
+ --xh-_image-cropper-grid-w: calc(var(--xh-stroke-thin) / var(--xh-_image-cropper-zoom));
88
+
89
+ position: absolute;
90
+ inset: 0;
91
+ background-image:
92
+ linear-gradient(
93
+ to right,
94
+ transparent 0 33.3333%,
95
+ var(--xh-image-cropper-grid-line, var(--xh-bg-subtle-opaque)) 33.3333% calc(33.3333% + var(--xh-_image-cropper-grid-w)),
96
+ transparent calc(33.3333% + var(--xh-_image-cropper-grid-w)) 66.6667%,
97
+ var(--xh-image-cropper-grid-line, var(--xh-bg-subtle-opaque)) 66.6667% calc(66.6667% + var(--xh-_image-cropper-grid-w)),
98
+ transparent calc(66.6667% + var(--xh-_image-cropper-grid-w)) 100%
99
+ ),
100
+ linear-gradient(
101
+ to bottom,
102
+ transparent 0 33.3333%,
103
+ var(--xh-image-cropper-grid-line, var(--xh-bg-subtle-opaque)) 33.3333% calc(33.3333% + var(--xh-_image-cropper-grid-w)),
104
+ transparent calc(33.3333% + var(--xh-_image-cropper-grid-w)) 66.6667%,
105
+ var(--xh-image-cropper-grid-line, var(--xh-bg-subtle-opaque)) 66.6667% calc(66.6667% + var(--xh-_image-cropper-grid-w)),
106
+ transparent calc(66.6667% + var(--xh-_image-cropper-grid-w)) 100%
107
+ );
108
+ pointer-events: none;
109
+ }
110
+
111
+ .xh-scope-image-cropper[data-part='grid'][data-shape='round'] {
112
+ background-image: none;
113
+ }
114
+
115
+ /* 把手的命中区仍以裁切框边界为中心,视觉短条与折角贴住边框并向框内绘制。 */
116
+ .xh-scope-image-cropper[data-part='crop-handle'] {
117
+ --xh-_image-cropper-handle-color: var(--xh-image-cropper-handle-bg, var(--xh-bg-surface));
118
+
119
+ position: absolute;
120
+ display: block;
121
+ box-sizing: border-box;
122
+ border: 0;
123
+ background: transparent;
124
+ inline-size: var(--xh-_image-cropper-handle-size);
125
+ block-size: var(--xh-_image-cropper-handle-size);
126
+ translate: -50% -50%;
127
+ scale: calc(1 / var(--xh-_image-cropper-zoom));
128
+ }
129
+
130
+ .xh-scope-image-cropper[data-part='crop-handle']::after {
131
+ content: '';
132
+ position: absolute;
133
+ box-sizing: border-box;
134
+ border-radius: var(--xh-image-cropper-handle-radius, var(--xh-shape-pill));
135
+ background: var(--xh-_image-cropper-handle-color);
136
+ pointer-events: none;
137
+ transition:
138
+ background-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
139
+ border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
140
+ }
141
+
142
+ /* 看得见的方块比手指小:另铺一层不可见的命中区,把它撑到最小可点尺寸。
143
+ inset 取负值即向四面外扩,方块本身更大时这个值转正、命中区仍是方块那么大。 */
144
+ .xh-scope-image-cropper[data-part='crop-handle']::before {
145
+ position: absolute;
146
+ inset: calc((var(--xh-_image-cropper-handle-size) - var(--xh-control-action-size)) / 2);
147
+ content: '';
148
+ }
149
+
150
+ /* 把手静息是白面(bg-surface),悬停从同一语义面派生一档,不切到品牌淡底;拖动中才是品牌实心。
151
+ 把手与网格线都压在照片上,取淡底的不透明档,照片深浅不一时才看得见 */
152
+ .xh-scope-image-cropper[data-part='crop-handle']:hover:not([data-disabled], [data-readonly]) {
153
+ --xh-_image-cropper-handle-color: var(--xh-image-cropper-handle-bg-hover, var(--xh-bg-subtle-opaque));
154
+ }
155
+
156
+ .xh-scope-image-cropper[data-part='crop-handle'][data-resizing] {
157
+ --xh-_image-cropper-handle-color: var(--xh-image-cropper-handle-bg-resizing, var(--xh-bg-brand));
158
+ }
159
+
160
+ .xh-scope-image-cropper[data-part='crop-handle']:focus-visible {
161
+ --xh-_image-cropper-handle-color: var(--xh-ring-focus);
162
+
163
+ outline: none;
164
+ }
165
+
166
+ /* —— 八个方位:落点 + 光标 —— */
167
+ .xh-scope-image-cropper[data-part='crop-handle'][data-position='nw'] {
168
+ top: 0;
169
+ /* stylelint-disable-next-line property-disallowed-list -- 裁切框的坐标是图片像素,落点跟着物理方向走 */
170
+ left: 0;
171
+ cursor: nwse-resize;
172
+ }
173
+
174
+ .xh-scope-image-cropper[data-part='crop-handle'][data-position='n'] {
175
+ top: 0;
176
+ /* stylelint-disable-next-line property-disallowed-list -- 同上 */
177
+ left: 50%;
178
+ cursor: ns-resize;
179
+ }
180
+
181
+ .xh-scope-image-cropper[data-part='crop-handle'][data-position='ne'] {
182
+ top: 0;
183
+ /* stylelint-disable-next-line property-disallowed-list -- 同上 */
184
+ left: 100%;
185
+ cursor: nesw-resize;
186
+ }
187
+
188
+ .xh-scope-image-cropper[data-part='crop-handle'][data-position='e'] {
189
+ top: 50%;
190
+ /* stylelint-disable-next-line property-disallowed-list -- 同上 */
191
+ left: 100%;
192
+ cursor: ew-resize;
193
+ }
194
+
195
+ .xh-scope-image-cropper[data-part='crop-handle'][data-position='se'] {
196
+ top: 100%;
197
+ /* stylelint-disable-next-line property-disallowed-list -- 同上 */
198
+ left: 100%;
199
+ cursor: nwse-resize;
200
+ }
201
+
202
+ .xh-scope-image-cropper[data-part='crop-handle'][data-position='s'] {
203
+ top: 100%;
204
+ /* stylelint-disable-next-line property-disallowed-list -- 同上 */
205
+ left: 50%;
206
+ cursor: ns-resize;
207
+ }
208
+
209
+ .xh-scope-image-cropper[data-part='crop-handle'][data-position='sw'] {
210
+ top: 100%;
211
+ /* stylelint-disable-next-line property-disallowed-list -- 同上 */
212
+ left: 0;
213
+ cursor: nesw-resize;
214
+ }
215
+
216
+ .xh-scope-image-cropper[data-part='crop-handle'][data-position='w'] {
217
+ top: 50%;
218
+ /* stylelint-disable-next-line property-disallowed-list -- 同上 */
219
+ left: 0;
220
+ cursor: ew-resize;
221
+ }
222
+
223
+ /* stylelint-disable property-disallowed-list -- 裁切框的八向位置使用图片物理坐标,内部标记必须朝对应物理方向内收 */
224
+ .xh-scope-image-cropper[data-part='crop-handle']:is([data-position='n'], [data-position='s'])::after {
225
+ left: 50%;
226
+ inline-size: var(--xh-image-cropper-handle-length, var(--xh-space-8));
227
+ block-size: var(--xh-image-cropper-handle-thickness, var(--xh-stroke-strong));
228
+ translate: -50% 0;
229
+ }
230
+
231
+ .xh-scope-image-cropper[data-part='crop-handle'][data-position='n']::after {
232
+ top: 50%;
233
+ }
234
+
235
+ .xh-scope-image-cropper[data-part='crop-handle'][data-position='s']::after {
236
+ bottom: 50%;
237
+ }
238
+
239
+ .xh-scope-image-cropper[data-part='crop-handle']:is([data-position='e'], [data-position='w'])::after {
240
+ top: 50%;
241
+ inline-size: var(--xh-image-cropper-handle-thickness, var(--xh-stroke-strong));
242
+ block-size: var(--xh-image-cropper-handle-length, var(--xh-space-8));
243
+ translate: 0 -50%;
244
+ }
245
+
246
+ .xh-scope-image-cropper[data-part='crop-handle'][data-position='e']::after {
247
+ right: 50%;
248
+ }
249
+
250
+ .xh-scope-image-cropper[data-part='crop-handle'][data-position='w']::after {
251
+ left: 50%;
252
+ }
253
+
254
+ .xh-scope-image-cropper[data-part='crop-handle'][data-position='nw'] {
255
+ border-start-start-radius: var(--xh-_image-cropper-corner-radius);
256
+ }
257
+
258
+ .xh-scope-image-cropper[data-part='crop-handle'][data-position='ne'] {
259
+ border-start-end-radius: var(--xh-_image-cropper-corner-radius);
260
+ }
261
+
262
+ .xh-scope-image-cropper[data-part='crop-handle'][data-position='sw'] {
263
+ border-end-start-radius: var(--xh-_image-cropper-corner-radius);
264
+ }
265
+
266
+ .xh-scope-image-cropper[data-part='crop-handle'][data-position='se'] {
267
+ border-end-end-radius: var(--xh-_image-cropper-corner-radius);
268
+ }
269
+
270
+ .xh-scope-image-cropper[data-part='crop-handle']:is(
271
+ [data-position='nw'],
272
+ [data-position='ne'],
273
+ [data-position='sw'],
274
+ [data-position='se']
275
+ )::after {
276
+ inline-size: calc(var(--xh-_image-cropper-handle-size) / 2);
277
+ block-size: calc(var(--xh-_image-cropper-handle-size) / 2);
278
+ border: 0 solid var(--xh-image-cropper-handle-border, var(--xh-_image-cropper-handle-color));
279
+ border-radius: inherit;
280
+ background: transparent;
281
+ outline: none;
282
+ }
283
+
284
+ .xh-scope-image-cropper[data-part='crop-handle'][data-position='nw']::after {
285
+ right: 0;
286
+ bottom: 0;
287
+ border-block-start-width: var(--xh-image-cropper-handle-thickness, var(--xh-stroke-strong));
288
+ border-inline-start-width: var(--xh-image-cropper-handle-thickness, var(--xh-stroke-strong));
289
+ }
290
+
291
+ .xh-scope-image-cropper[data-part='crop-handle'][data-position='ne']::after {
292
+ bottom: 0;
293
+ left: 0;
294
+ border-block-start-width: var(--xh-image-cropper-handle-thickness, var(--xh-stroke-strong));
295
+ border-inline-end-width: var(--xh-image-cropper-handle-thickness, var(--xh-stroke-strong));
296
+ }
297
+
298
+ .xh-scope-image-cropper[data-part='crop-handle'][data-position='sw']::after {
299
+ top: 0;
300
+ right: 0;
301
+ border-block-end-width: var(--xh-image-cropper-handle-thickness, var(--xh-stroke-strong));
302
+ border-inline-start-width: var(--xh-image-cropper-handle-thickness, var(--xh-stroke-strong));
303
+ }
304
+
305
+ .xh-scope-image-cropper[data-part='crop-handle'][data-position='se']::after {
306
+ top: 0;
307
+ left: 0;
308
+ border-block-end-width: var(--xh-image-cropper-handle-thickness, var(--xh-stroke-strong));
309
+ border-inline-end-width: var(--xh-image-cropper-handle-thickness, var(--xh-stroke-strong));
310
+ }
311
+ /* stylelint-enable property-disallowed-list */
312
+
313
+ /* 只读与禁用的光标排在八个方位之后:那八条每条都写了 cursor,特异性又完全相同,
314
+ 排在前面会被逐条盖掉,整条规则等于没写。 */
315
+ .xh-scope-image-cropper[data-part='crop-handle'][data-readonly] {
316
+ cursor: default;
317
+ }
318
+
319
+ .xh-scope-image-cropper[data-part='crop-handle'][data-disabled] {
320
+ cursor: not-allowed;
321
+ }
322
+
323
+ /* 两条控制轴用原生 range:拇指与轨道交给平台画,这里只给横向铺满与品牌色。
324
+ 不写 block-size:原生 range 的高度由 UA 与拇指尺寸定,写死会把拇指切掉一截。 */
325
+ .xh-scope-image-cropper[data-part='zoom-slider'],
326
+ .xh-scope-image-cropper[data-part='rotate-slider'] {
327
+ inline-size: var(--xh-image-cropper-slider-w, 100%);
328
+ /* 原生 range 自带左右各一段外边距,与铺满的宽度叠在一起就把这两条轴顶出容器 */
329
+ margin-inline: 0;
330
+ accent-color: var(--xh-image-cropper-slider-accent, var(--xh-bg-brand));
331
+ }
332
+
333
+ /*
334
+ * 翻转按钮是裁切器旁的独立开关钮:盒型、sm 档几何、outline 四态面、0.97 按压与粗指针命中区由家族配方
335
+ * 按连接层投影的 data-xh-action-* 给出。翻着(data-state='on')是无滑块开关的选中面:品牌淡底 12 → 悬停 20
336
+ * → 按压 28,前景 fg-on-brand-subtle;outline 的描边不换,淡底面上没有描边就与悬停面分不开。
337
+ */
338
+ .xh-scope-image-cropper[data-part='flip-trigger'] {
339
+ /* 作者塞进来的图标随档取字形尺(sm = 16px) */
340
+ --xh-icon-size: var(--xh-_action-profile-glyph-size);
341
+ }
342
+
343
+ .xh-scope-image-cropper[data-part='flip-trigger'][data-state='on'] {
344
+ --xh-action-bg-rest: var(--xh-bg-brand-subtle);
345
+ --xh-action-bg-hover: var(--xh-bg-brand-subtle-hover);
346
+ --xh-action-bg-pressed: var(--xh-bg-brand-subtle-active);
347
+ --xh-action-bg-focus-visible: var(--xh-bg-brand-subtle);
348
+ /* 翻着又被禁用:底色掺一半中性面,选中信息不丢。掺的是淡底的不透明档,墨色淡底半透明 */
349
+ --xh-action-bg-disabled: color-mix(in oklab, var(--xh-bg-brand-subtle) 50%, var(--xh-bg-subtle-opaque));
350
+ --xh-action-fg-rest: var(--xh-fg-on-brand-subtle);
351
+ --xh-action-fg-hover: var(--xh-fg-on-brand-subtle);
352
+ --xh-action-fg-pressed: var(--xh-fg-on-brand-subtle);
353
+ --xh-action-fg-focus-visible: var(--xh-fg-on-brand-subtle);
354
+ }
355
+
356
+ /* 禁用的整体压暗只做一次,落在最外层:视口、裁切框、把手各自再叠一层会越叠越黑。
357
+ 这里只用 opacity、不换前景色:框里是图像,没有文字可换。 */
358
+ .xh-scope-image-cropper[data-part='root'][data-disabled] {
359
+ opacity: var(--xh-state-disabled-opacity);
360
+ }
361
+
362
+ /* hidden-input 是 type=hidden 的原生输入,浏览器本就不渲染它,
363
+ 这里一条声明都不给:给了 display / 尺寸反而会把它拽回布局里撑出一块空白。 */
364
+
365
+ /* display 会盖掉 UA 的 [hidden]{display:none},凡是被赋了 display 的角色节点都要显式让位。
366
+ 这条必须排在全部 display 声明之后。 */
367
+ .xh-scope-image-cropper[data-part='root'][hidden],
368
+ .xh-scope-image-cropper[data-part='viewport'][hidden],
369
+ .xh-scope-image-cropper[data-part='image'][hidden],
370
+ .xh-scope-image-cropper[data-part='crop-handle'][hidden] {
371
+ display: none;
372
+ }
373
+ }