@xihan-ui/styles 1.0.0-alpha.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 (114) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/LICENSE +21 -0
  3. package/README.md +27 -0
  4. package/css/accordion.css +108 -0
  5. package/css/affix.css +27 -0
  6. package/css/alert.css +108 -0
  7. package/css/anchor.css +137 -0
  8. package/css/avatar-group.css +82 -0
  9. package/css/avatar.css +55 -0
  10. package/css/back-top.css +61 -0
  11. package/css/badge.css +50 -0
  12. package/css/breadcrumb.css +127 -0
  13. package/css/button-group.css +131 -0
  14. package/css/button.css +98 -0
  15. package/css/calendar.css +219 -0
  16. package/css/card.css +116 -0
  17. package/css/carousel.css +193 -0
  18. package/css/cascader.css +397 -0
  19. package/css/checkbox-group.css +185 -0
  20. package/css/checkbox.css +91 -0
  21. package/css/clipboard.css +133 -0
  22. package/css/code-block.css +81 -0
  23. package/css/collapsible.css +63 -0
  24. package/css/color-picker.css +424 -0
  25. package/css/combobox.css +433 -0
  26. package/css/composer.css +127 -0
  27. package/css/context-menu.css +263 -0
  28. package/css/countdown.css +21 -0
  29. package/css/date-field.css +200 -0
  30. package/css/date-picker.css +231 -0
  31. package/css/descriptions.css +200 -0
  32. package/css/dialog.css +127 -0
  33. package/css/drawer.css +372 -0
  34. package/css/dynamic-input.css +157 -0
  35. package/css/editable.css +249 -0
  36. package/css/ellipsis.css +41 -0
  37. package/css/empty-state.css +78 -0
  38. package/css/field.css +65 -0
  39. package/css/file-upload.css +298 -0
  40. package/css/flex.css +95 -0
  41. package/css/float-button.css +121 -0
  42. package/css/form.css +185 -0
  43. package/css/gradient-text.css +62 -0
  44. package/css/grid.css +428 -0
  45. package/css/highlight.css +21 -0
  46. package/css/hover-card.css +146 -0
  47. package/css/icon-wrapper.css +64 -0
  48. package/css/icon.css +54 -0
  49. package/css/image.css +45 -0
  50. package/css/infinite-scroll.css +22 -0
  51. package/css/layers.css +2 -0
  52. package/css/layout.css +169 -0
  53. package/css/list.css +117 -0
  54. package/css/listbox.css +174 -0
  55. package/css/loading-bar.css +66 -0
  56. package/css/log.css +66 -0
  57. package/css/marquee.css +182 -0
  58. package/css/mention.css +222 -0
  59. package/css/menu.css +144 -0
  60. package/css/menubar.css +271 -0
  61. package/css/motion.css +58 -0
  62. package/css/navigation-menu.css +270 -0
  63. package/css/number-animation.css +32 -0
  64. package/css/number-field.css +219 -0
  65. package/css/page-header.css +85 -0
  66. package/css/pagination.css +148 -0
  67. package/css/pin-input.css +157 -0
  68. package/css/popconfirm.css +150 -0
  69. package/css/popover.css +150 -0
  70. package/css/popselect.css +207 -0
  71. package/css/progress.css +37 -0
  72. package/css/qr-code.css +50 -0
  73. package/css/radio-group.css +101 -0
  74. package/css/rating.css +141 -0
  75. package/css/reset.css +22 -0
  76. package/css/result.css +104 -0
  77. package/css/scroll-area.css +176 -0
  78. package/css/select.css +264 -0
  79. package/css/separator.css +17 -0
  80. package/css/skeleton.css +78 -0
  81. package/css/slider.css +197 -0
  82. package/css/spinner.css +74 -0
  83. package/css/splitter.css +127 -0
  84. package/css/statistic.css +67 -0
  85. package/css/steps.css +252 -0
  86. package/css/switch.css +61 -0
  87. package/css/table.css +404 -0
  88. package/css/tabs.css +157 -0
  89. package/css/tags-input.css +360 -0
  90. package/css/text-field.css +195 -0
  91. package/css/thread.css +107 -0
  92. package/css/time-field.css +200 -0
  93. package/css/time-picker.css +347 -0
  94. package/css/time.css +20 -0
  95. package/css/timeline.css +284 -0
  96. package/css/toast.css +195 -0
  97. package/css/toaster.css +69 -0
  98. package/css/toggle-group.css +160 -0
  99. package/css/toggle.css +103 -0
  100. package/css/tone.css +85 -0
  101. package/css/toolbar.css +114 -0
  102. package/css/tooltip.css +109 -0
  103. package/css/tour.css +305 -0
  104. package/css/transfer.css +318 -0
  105. package/css/tree-select.css +441 -0
  106. package/css/tree.css +204 -0
  107. package/css/typography.css +151 -0
  108. package/css/undefined.css +38 -0
  109. package/css/virtualizer.css +104 -0
  110. package/css/visually-hidden.css +13 -0
  111. package/css/watermark.css +48 -0
  112. package/index.css +113 -0
  113. package/index.unlayered.css +16164 -0
  114. package/package.json +163 -0
package/css/form.css ADDED
@@ -0,0 +1,185 @@
1
+ @layer xihan.components {
2
+ /* 表单是一列字段:竖排、字段之间留一档间距。root 就是那个原生 <form> */
3
+ [data-scope='form'][data-part='root'] {
4
+ display: flex;
5
+ flex-direction: column;
6
+ gap: var(--xh-form-gap, var(--xh-stack-gap-md));
7
+ margin: 0;
8
+ }
9
+
10
+ /* 只要声明了 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去 */
11
+ [data-scope='form'][data-part='root'][hidden] {
12
+ display: none;
13
+ }
14
+
15
+ /* 字段容器只管排版与状态标记:标题、控件、描述、错误文案都是里面那个 Field 的活儿 */
16
+ [data-scope='form'][data-part='field-group'] {
17
+ display: flex;
18
+ flex-direction: column;
19
+ gap: var(--xh-form-field-gap, var(--xh-space-1));
20
+ }
21
+
22
+ [data-scope='form'][data-part='field-group'][hidden] {
23
+ display: none;
24
+ }
25
+
26
+ /* 出错的字段在起始缘竖一条色带:读屏之外还得有一眼看得见的定位标记。
27
+ 用逻辑属性,RTL 下自动换到右侧 */
28
+ [data-scope='form'][data-part='field-group'][data-invalid] {
29
+ padding-inline-start: var(--xh-form-field-invalid-px, var(--xh-space-2));
30
+ border-inline-start: var(--xh-stroke-thick) solid var(--xh-form-field-invalid-border, var(--xh-color-danger-500));
31
+ }
32
+
33
+ /* 容器带着 tabindex=-1:控件全禁用时焦点会落在它自己身上,
34
+ 那一刻必须画环,否则键盘用户看不出自己被送到了哪儿 */
35
+ [data-scope='form'][data-part='field-group']:focus-visible {
36
+ outline: var(--xh-ring-width) solid var(--xh-ring-focus);
37
+ outline-offset: var(--xh-ring-offset);
38
+ }
39
+
40
+ /* 提交失败后的错误汇总。role=alert 常挂,靠 hidden 显隐 */
41
+ [data-scope='form'][data-part='error-summary'] {
42
+ display: flex;
43
+ flex-direction: column;
44
+ gap: var(--xh-form-summary-gap, var(--xh-space-1_5));
45
+ padding-block: var(--xh-form-summary-py, var(--xh-space-3));
46
+ padding-inline: var(--xh-form-summary-px, var(--xh-control-px-md));
47
+ border: var(--xh-stroke-thin) solid var(--xh-form-summary-border, var(--xh-color-danger-500));
48
+ border-radius: var(--xh-form-summary-radius, var(--xh-shape-surface));
49
+ background: var(--xh-form-summary-bg, var(--xh-bg-surface));
50
+ color: var(--xh-form-summary-fg, var(--xh-fg-danger));
51
+ font-size: var(--xh-form-summary-font-size, var(--xh-text-body-size));
52
+ line-height: var(--xh-leading-normal);
53
+ box-shadow: var(--xh-form-summary-shadow, var(--xh-elevation-1));
54
+ }
55
+
56
+ /* 漏了这条,摘要一旦出现过就再也撤不下去(上面那条 display 盖掉了 UA 的 [hidden] 规则) */
57
+ [data-scope='form'][data-part='error-summary'][hidden] {
58
+ display: none;
59
+ }
60
+
61
+ /* 摘要不承载焦点(焦点直接送去出错的字段),它只是一段播报,落焦时不画环 */
62
+ [data-scope='form'][data-part='error-summary']:focus-visible {
63
+ outline: none;
64
+ }
65
+
66
+ /* 从收起翻成显出的那一下给一小段入场:读屏靠 role=alert 播报,
67
+ 视觉这边也得有个"它是刚冒出来的"的交代,否则像一直杵在那儿 */
68
+ [data-scope='form'][data-part='error-summary'][data-state='invalid'] {
69
+ animation: xh-form-summary-enter var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
70
+ }
71
+
72
+ /* 摘要里的每一条是一个真链接,指向对应字段容器 */
73
+ [data-scope='form'][data-part='error-summary-item'] {
74
+ display: block;
75
+ color: inherit;
76
+ font-size: var(--xh-form-summary-item-font-size, var(--xh-font-size-sm));
77
+ text-decoration: underline;
78
+ text-underline-offset: 2px;
79
+ cursor: pointer;
80
+ }
81
+
82
+ /* 没有对应错误的条目由连接层给 hidden;上面那条 display 已把 UA 规则盖掉 */
83
+ [data-scope='form'][data-part='error-summary-item'][hidden] {
84
+ display: none;
85
+ }
86
+
87
+ [data-scope='form'][data-part='error-summary-item']:hover {
88
+ color: var(--xh-form-summary-item-fg-hover, var(--xh-fg-danger-hover));
89
+ }
90
+
91
+ [data-scope='form'][data-part='error-summary-item']:focus-visible {
92
+ outline: var(--xh-ring-width) solid var(--xh-ring-focus);
93
+ outline-offset: var(--xh-ring-offset);
94
+ }
95
+
96
+ /* 两颗按钮共用一份底子:它们是同一种东西,只是干的活不同,
97
+ 分开写迟早会改了一颗忘了另一颗 */
98
+ [data-scope='form'][data-part='submit-trigger'],
99
+ [data-scope='form'][data-part='reset-trigger'] {
100
+ display: inline-flex;
101
+ flex: none;
102
+ align-items: center;
103
+ justify-content: center;
104
+ block-size: var(--xh-form-trigger-h, var(--xh-control-h-md));
105
+ padding-block: 0;
106
+ padding-inline: var(--xh-form-trigger-px, var(--xh-control-px-md));
107
+ border: var(--xh-stroke-thin) solid var(--xh-form-trigger-border, var(--xh-border-default));
108
+ border-radius: var(--xh-form-trigger-radius, var(--xh-shape-control));
109
+ background: var(--xh-form-trigger-bg, var(--xh-bg-subtle));
110
+ color: var(--xh-form-trigger-fg, var(--xh-fg-default));
111
+ /* 表单控件不继承页面字体,只给字号会让按钮用 UA 默认字族,与周围文本对不上 */
112
+ font-family: inherit;
113
+ font-size: var(--xh-form-trigger-font-size, var(--xh-text-body-size));
114
+ line-height: var(--xh-leading-none);
115
+ white-space: nowrap;
116
+ cursor: pointer;
117
+ user-select: none;
118
+ transition: background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
119
+ }
120
+
121
+ [data-scope='form'][data-part='submit-trigger'][hidden],
122
+ [data-scope='form'][data-part='reset-trigger'][hidden] {
123
+ display: none;
124
+ }
125
+
126
+ [data-scope='form'][data-part='submit-trigger']:hover:not(:disabled),
127
+ [data-scope='form'][data-part='reset-trigger']:hover:not(:disabled) {
128
+ border-color: var(--xh-form-trigger-border-hover, var(--xh-border-strong));
129
+ background: var(--xh-form-trigger-bg-hover, var(--xh-bg-subtle-hover));
130
+ }
131
+
132
+ [data-scope='form'][data-part='submit-trigger']:active:not(:disabled),
133
+ [data-scope='form'][data-part='reset-trigger']:active:not(:disabled) {
134
+ background: var(--xh-form-trigger-bg-active, var(--xh-bg-subtle-active));
135
+ }
136
+
137
+ [data-scope='form'][data-part='submit-trigger']:focus-visible,
138
+ [data-scope='form'][data-part='reset-trigger']:focus-visible {
139
+ outline: var(--xh-ring-width) solid var(--xh-ring-focus);
140
+ outline-offset: var(--xh-ring-offset);
141
+ }
142
+
143
+ /* 单体控件用 :disabled(集合条目才用 [data-disabled]):
144
+ 整表禁用时提交键置灰,只读时重置键也一并落到这条上 */
145
+ [data-scope='form'][data-part='submit-trigger']:disabled,
146
+ [data-scope='form'][data-part='reset-trigger']:disabled {
147
+ border-color: var(--xh-form-trigger-border-disabled, var(--xh-border-subtle));
148
+ background: var(--xh-form-trigger-bg-disabled, var(--xh-bg-muted));
149
+ color: var(--xh-fg-disabled);
150
+ cursor: not-allowed;
151
+ }
152
+
153
+ /* 提交是这一组里的主操作,给它一层实心底色区分开 */
154
+ [data-scope='form'][data-part='submit-trigger']:not(:disabled) {
155
+ border-color: var(--xh-form-submit-bg, var(--xh-bg-brand));
156
+ background: var(--xh-form-submit-bg, var(--xh-bg-brand));
157
+ color: var(--xh-form-submit-fg, var(--xh-fg-on-brand));
158
+ }
159
+
160
+ [data-scope='form'][data-part='submit-trigger']:hover:not(:disabled) {
161
+ border-color: var(--xh-form-submit-bg-hover, var(--xh-bg-brand-hover));
162
+ background: var(--xh-form-submit-bg-hover, var(--xh-bg-brand-hover));
163
+ }
164
+
165
+ [data-scope='form'][data-part='submit-trigger']:active:not(:disabled) {
166
+ border-color: var(--xh-form-submit-bg-active, var(--xh-bg-brand-active));
167
+ background: var(--xh-form-submit-bg-active, var(--xh-bg-brand-active));
168
+ }
169
+ }
170
+
171
+ @layer xihan.motion {
172
+ /* 关键帧写在自己文件里、名字带组件前缀:motion.css 是公共的,
173
+ 往那儿加一条只服务本组件的动画会让所有组件都得跟着重下载 */
174
+ @keyframes xh-form-summary-enter {
175
+ from {
176
+ opacity: 0;
177
+ translate: 0 calc(-1 * var(--xh-space-1));
178
+ }
179
+
180
+ to {
181
+ opacity: 1;
182
+ translate: 0 0;
183
+ }
184
+ }
185
+ }
@@ -0,0 +1,62 @@
1
+ @layer xihan.components {
2
+ /* 渐变画在背景上,再用 background-clip 把背景裁进字形里;前景必须透明才透得出底下的渐变。
3
+ 两条 background-clip 都写:WebKit 只认带前缀那条。
4
+ -webkit-text-fill-color 在 WebKit 里决定字形填充色并盖过 color,也要一并透明。 */
5
+ [data-scope='gradient-text'][data-part='root'] {
6
+ /* 走向由 data-direction 换掉这一个槽,背景那条声明只写一遍 */
7
+ --xh-_gradient-text-dir: to right;
8
+
9
+ background-image: linear-gradient(
10
+ var(--xh-_gradient-text-dir),
11
+ var(--xh-gradient-text-from, var(--xh-color-brand-500)),
12
+ var(--xh-gradient-text-to, var(--xh-color-brand-700))
13
+ );
14
+ -webkit-background-clip: text;
15
+ background-clip: text;
16
+ color: transparent;
17
+ -webkit-text-fill-color: transparent;
18
+ }
19
+
20
+ /* —— 走向 —— */
21
+ /* 逐档换算成 CSS 的 to <边或角>,四条边加四个角 */
22
+ [data-scope='gradient-text'][data-part='root'][data-direction='to-right'] {
23
+ --xh-_gradient-text-dir: to right;
24
+ }
25
+
26
+ [data-scope='gradient-text'][data-part='root'][data-direction='to-left'] {
27
+ --xh-_gradient-text-dir: to left;
28
+ }
29
+
30
+ [data-scope='gradient-text'][data-part='root'][data-direction='to-bottom'] {
31
+ --xh-_gradient-text-dir: to bottom;
32
+ }
33
+
34
+ [data-scope='gradient-text'][data-part='root'][data-direction='to-top'] {
35
+ --xh-_gradient-text-dir: to top;
36
+ }
37
+
38
+ [data-scope='gradient-text'][data-part='root'][data-direction='to-bottom-right'] {
39
+ --xh-_gradient-text-dir: to bottom right;
40
+ }
41
+
42
+ [data-scope='gradient-text'][data-part='root'][data-direction='to-bottom-left'] {
43
+ --xh-_gradient-text-dir: to bottom left;
44
+ }
45
+
46
+ [data-scope='gradient-text'][data-part='root'][data-direction='to-top-right'] {
47
+ --xh-_gradient-text-dir: to top right;
48
+ }
49
+
50
+ [data-scope='gradient-text'][data-part='root'][data-direction='to-top-left'] {
51
+ --xh-_gradient-text-dir: to top left;
52
+ }
53
+
54
+ /* 强制色模式下系统会禁掉背景图,留着透明前景整段字就彻底看不见了,这里把填充色还回去 */
55
+ @media (forced-colors: active) {
56
+ [data-scope='gradient-text'][data-part='root'] {
57
+ background-image: none;
58
+ color: inherit;
59
+ -webkit-text-fill-color: currentColor;
60
+ }
61
+ }
62
+ }
package/css/grid.css ADDED
@@ -0,0 +1,428 @@
1
+ @layer xihan.components {
2
+ [data-scope='grid'][data-part='root'] {
3
+ display: grid;
4
+ /* 各列等宽;下限写 0 而不是 auto,一段长文本才不会把自己那列撑宽 */
5
+ /* 使用者槽位排在档位之前,写死一份轨道表即盖过所有列数档 */
6
+ grid-template-columns: var(--xh-grid-columns, repeat(var(--xh-_grid-cols), minmax(0, 1fr)));
7
+ /* 不写 gap 档位就不留间距 */
8
+ gap: var(--xh-grid-gap, var(--xh-space-0));
9
+ /* 列数收在根上这一个槽位里,换档只改这里;每一层都声明一遍,嵌套时内层不吃外层的值 */
10
+ --xh-_grid-cols: 1;
11
+ }
12
+
13
+ /* —— 列数 —— */
14
+ /* 一列是上面的缺省,这里从两列起逐档写 */
15
+ [data-scope='grid'][data-part='root'][data-cols='2'] {
16
+ --xh-_grid-cols: 2;
17
+ }
18
+
19
+ [data-scope='grid'][data-part='root'][data-cols='3'] {
20
+ --xh-_grid-cols: 3;
21
+ }
22
+
23
+ [data-scope='grid'][data-part='root'][data-cols='4'] {
24
+ --xh-_grid-cols: 4;
25
+ }
26
+
27
+ [data-scope='grid'][data-part='root'][data-cols='5'] {
28
+ --xh-_grid-cols: 5;
29
+ }
30
+
31
+ [data-scope='grid'][data-part='root'][data-cols='6'] {
32
+ --xh-_grid-cols: 6;
33
+ }
34
+
35
+ [data-scope='grid'][data-part='root'][data-cols='7'] {
36
+ --xh-_grid-cols: 7;
37
+ }
38
+
39
+ [data-scope='grid'][data-part='root'][data-cols='8'] {
40
+ --xh-_grid-cols: 8;
41
+ }
42
+
43
+ [data-scope='grid'][data-part='root'][data-cols='9'] {
44
+ --xh-_grid-cols: 9;
45
+ }
46
+
47
+ [data-scope='grid'][data-part='root'][data-cols='10'] {
48
+ --xh-_grid-cols: 10;
49
+ }
50
+
51
+ [data-scope='grid'][data-part='root'][data-cols='11'] {
52
+ --xh-_grid-cols: 11;
53
+ }
54
+
55
+ [data-scope='grid'][data-part='root'][data-cols='12'] {
56
+ --xh-_grid-cols: 12;
57
+ }
58
+
59
+ /* —— 逐档列数 —— */
60
+ /* 移动优先:先按 data-cols 排定,视口每宽到一档就换成那一档的列数,没写的档沿用比它窄的那一档。
61
+ 四档自窄到宽依次写,只用 min-width:媒体查询不改选择器权重,宽视口上同时命中好几档时由源码序决定谁生效。
62
+ 宽度写字面量:自定义属性在 @media 条件里不参与求值,令牌变量写在这里等于没写条件。
63
+ 每档都从一列写起:base 分多列、某一档收回一列同样是合法的一档。 */
64
+ @media (min-width: 640px) {
65
+ [data-scope='grid'][data-part='root'][data-cols-sm='1'] {
66
+ --xh-_grid-cols: 1;
67
+ }
68
+
69
+ [data-scope='grid'][data-part='root'][data-cols-sm='2'] {
70
+ --xh-_grid-cols: 2;
71
+ }
72
+
73
+ [data-scope='grid'][data-part='root'][data-cols-sm='3'] {
74
+ --xh-_grid-cols: 3;
75
+ }
76
+
77
+ [data-scope='grid'][data-part='root'][data-cols-sm='4'] {
78
+ --xh-_grid-cols: 4;
79
+ }
80
+
81
+ [data-scope='grid'][data-part='root'][data-cols-sm='5'] {
82
+ --xh-_grid-cols: 5;
83
+ }
84
+
85
+ [data-scope='grid'][data-part='root'][data-cols-sm='6'] {
86
+ --xh-_grid-cols: 6;
87
+ }
88
+
89
+ [data-scope='grid'][data-part='root'][data-cols-sm='7'] {
90
+ --xh-_grid-cols: 7;
91
+ }
92
+
93
+ [data-scope='grid'][data-part='root'][data-cols-sm='8'] {
94
+ --xh-_grid-cols: 8;
95
+ }
96
+
97
+ [data-scope='grid'][data-part='root'][data-cols-sm='9'] {
98
+ --xh-_grid-cols: 9;
99
+ }
100
+
101
+ [data-scope='grid'][data-part='root'][data-cols-sm='10'] {
102
+ --xh-_grid-cols: 10;
103
+ }
104
+
105
+ [data-scope='grid'][data-part='root'][data-cols-sm='11'] {
106
+ --xh-_grid-cols: 11;
107
+ }
108
+
109
+ [data-scope='grid'][data-part='root'][data-cols-sm='12'] {
110
+ --xh-_grid-cols: 12;
111
+ }
112
+ }
113
+
114
+ @media (min-width: 768px) {
115
+ [data-scope='grid'][data-part='root'][data-cols-md='1'] {
116
+ --xh-_grid-cols: 1;
117
+ }
118
+
119
+ [data-scope='grid'][data-part='root'][data-cols-md='2'] {
120
+ --xh-_grid-cols: 2;
121
+ }
122
+
123
+ [data-scope='grid'][data-part='root'][data-cols-md='3'] {
124
+ --xh-_grid-cols: 3;
125
+ }
126
+
127
+ [data-scope='grid'][data-part='root'][data-cols-md='4'] {
128
+ --xh-_grid-cols: 4;
129
+ }
130
+
131
+ [data-scope='grid'][data-part='root'][data-cols-md='5'] {
132
+ --xh-_grid-cols: 5;
133
+ }
134
+
135
+ [data-scope='grid'][data-part='root'][data-cols-md='6'] {
136
+ --xh-_grid-cols: 6;
137
+ }
138
+
139
+ [data-scope='grid'][data-part='root'][data-cols-md='7'] {
140
+ --xh-_grid-cols: 7;
141
+ }
142
+
143
+ [data-scope='grid'][data-part='root'][data-cols-md='8'] {
144
+ --xh-_grid-cols: 8;
145
+ }
146
+
147
+ [data-scope='grid'][data-part='root'][data-cols-md='9'] {
148
+ --xh-_grid-cols: 9;
149
+ }
150
+
151
+ [data-scope='grid'][data-part='root'][data-cols-md='10'] {
152
+ --xh-_grid-cols: 10;
153
+ }
154
+
155
+ [data-scope='grid'][data-part='root'][data-cols-md='11'] {
156
+ --xh-_grid-cols: 11;
157
+ }
158
+
159
+ [data-scope='grid'][data-part='root'][data-cols-md='12'] {
160
+ --xh-_grid-cols: 12;
161
+ }
162
+ }
163
+
164
+ @media (min-width: 1024px) {
165
+ [data-scope='grid'][data-part='root'][data-cols-lg='1'] {
166
+ --xh-_grid-cols: 1;
167
+ }
168
+
169
+ [data-scope='grid'][data-part='root'][data-cols-lg='2'] {
170
+ --xh-_grid-cols: 2;
171
+ }
172
+
173
+ [data-scope='grid'][data-part='root'][data-cols-lg='3'] {
174
+ --xh-_grid-cols: 3;
175
+ }
176
+
177
+ [data-scope='grid'][data-part='root'][data-cols-lg='4'] {
178
+ --xh-_grid-cols: 4;
179
+ }
180
+
181
+ [data-scope='grid'][data-part='root'][data-cols-lg='5'] {
182
+ --xh-_grid-cols: 5;
183
+ }
184
+
185
+ [data-scope='grid'][data-part='root'][data-cols-lg='6'] {
186
+ --xh-_grid-cols: 6;
187
+ }
188
+
189
+ [data-scope='grid'][data-part='root'][data-cols-lg='7'] {
190
+ --xh-_grid-cols: 7;
191
+ }
192
+
193
+ [data-scope='grid'][data-part='root'][data-cols-lg='8'] {
194
+ --xh-_grid-cols: 8;
195
+ }
196
+
197
+ [data-scope='grid'][data-part='root'][data-cols-lg='9'] {
198
+ --xh-_grid-cols: 9;
199
+ }
200
+
201
+ [data-scope='grid'][data-part='root'][data-cols-lg='10'] {
202
+ --xh-_grid-cols: 10;
203
+ }
204
+
205
+ [data-scope='grid'][data-part='root'][data-cols-lg='11'] {
206
+ --xh-_grid-cols: 11;
207
+ }
208
+
209
+ [data-scope='grid'][data-part='root'][data-cols-lg='12'] {
210
+ --xh-_grid-cols: 12;
211
+ }
212
+ }
213
+
214
+ @media (min-width: 1280px) {
215
+ [data-scope='grid'][data-part='root'][data-cols-xl='1'] {
216
+ --xh-_grid-cols: 1;
217
+ }
218
+
219
+ [data-scope='grid'][data-part='root'][data-cols-xl='2'] {
220
+ --xh-_grid-cols: 2;
221
+ }
222
+
223
+ [data-scope='grid'][data-part='root'][data-cols-xl='3'] {
224
+ --xh-_grid-cols: 3;
225
+ }
226
+
227
+ [data-scope='grid'][data-part='root'][data-cols-xl='4'] {
228
+ --xh-_grid-cols: 4;
229
+ }
230
+
231
+ [data-scope='grid'][data-part='root'][data-cols-xl='5'] {
232
+ --xh-_grid-cols: 5;
233
+ }
234
+
235
+ [data-scope='grid'][data-part='root'][data-cols-xl='6'] {
236
+ --xh-_grid-cols: 6;
237
+ }
238
+
239
+ [data-scope='grid'][data-part='root'][data-cols-xl='7'] {
240
+ --xh-_grid-cols: 7;
241
+ }
242
+
243
+ [data-scope='grid'][data-part='root'][data-cols-xl='8'] {
244
+ --xh-_grid-cols: 8;
245
+ }
246
+
247
+ [data-scope='grid'][data-part='root'][data-cols-xl='9'] {
248
+ --xh-_grid-cols: 9;
249
+ }
250
+
251
+ [data-scope='grid'][data-part='root'][data-cols-xl='10'] {
252
+ --xh-_grid-cols: 10;
253
+ }
254
+
255
+ [data-scope='grid'][data-part='root'][data-cols-xl='11'] {
256
+ --xh-_grid-cols: 11;
257
+ }
258
+
259
+ [data-scope='grid'][data-part='root'][data-cols-xl='12'] {
260
+ --xh-_grid-cols: 12;
261
+ }
262
+ }
263
+
264
+ /* —— 间距档位 —— */
265
+ /* 每一档指向一个间距令牌,行与行之间也吃这同一份间距 */
266
+ [data-scope='grid'][data-part='root'][data-gap='xs'] {
267
+ gap: var(--xh-grid-gap, var(--xh-space-1));
268
+ }
269
+
270
+ [data-scope='grid'][data-part='root'][data-gap='sm'] {
271
+ gap: var(--xh-grid-gap, var(--xh-space-2));
272
+ }
273
+
274
+ [data-scope='grid'][data-part='root'][data-gap='md'] {
275
+ gap: var(--xh-grid-gap, var(--xh-space-3));
276
+ }
277
+
278
+ [data-scope='grid'][data-part='root'][data-gap='lg'] {
279
+ gap: var(--xh-grid-gap, var(--xh-space-4));
280
+ }
281
+
282
+ [data-scope='grid'][data-part='root'][data-gap='xl'] {
283
+ gap: var(--xh-grid-gap, var(--xh-space-6));
284
+ }
285
+
286
+ /* —— 块向对齐 —— */
287
+ /* 管的是每一项在自己那格里怎么摆,不是格子在容器里怎么摆:列宽由轨道表定死,容器不留富余 */
288
+ [data-scope='grid'][data-part='root'][data-align='start'] {
289
+ align-items: start;
290
+ }
291
+
292
+ [data-scope='grid'][data-part='root'][data-align='center'] {
293
+ align-items: center;
294
+ }
295
+
296
+ [data-scope='grid'][data-part='root'][data-align='end'] {
297
+ align-items: end;
298
+ }
299
+
300
+ [data-scope='grid'][data-part='root'][data-align='stretch'] {
301
+ align-items: stretch;
302
+ }
303
+
304
+ [data-scope='grid'][data-part='root'][data-align='baseline'] {
305
+ align-items: baseline;
306
+ }
307
+
308
+ /* —— 行内对齐 —— */
309
+ [data-scope='grid'][data-part='root'][data-justify='start'] {
310
+ justify-items: start;
311
+ }
312
+
313
+ [data-scope='grid'][data-part='root'][data-justify='center'] {
314
+ justify-items: center;
315
+ }
316
+
317
+ [data-scope='grid'][data-part='root'][data-justify='end'] {
318
+ justify-items: end;
319
+ }
320
+
321
+ [data-scope='grid'][data-part='root'][data-justify='stretch'] {
322
+ justify-items: stretch;
323
+ }
324
+
325
+ /* —— 格子 —— */
326
+ [data-scope='grid'][data-part='item'] {
327
+ grid-column-start: var(--xh-_grid-start);
328
+ grid-column-end: span var(--xh-_grid-span);
329
+
330
+ /* 两个槽位在每一格上都声明一遍,嵌套时内层的格子不吃外层那一格的值 */
331
+ --xh-_grid-span: 1;
332
+ --xh-_grid-start: auto;
333
+ }
334
+
335
+ /* —— 跨列 —— */
336
+ /* 占一列是上面的缺省,这里从跨两列起逐档写 */
337
+ [data-scope='grid'][data-part='item'][data-span='2'] {
338
+ --xh-_grid-span: 2;
339
+ }
340
+
341
+ [data-scope='grid'][data-part='item'][data-span='3'] {
342
+ --xh-_grid-span: 3;
343
+ }
344
+
345
+ [data-scope='grid'][data-part='item'][data-span='4'] {
346
+ --xh-_grid-span: 4;
347
+ }
348
+
349
+ [data-scope='grid'][data-part='item'][data-span='5'] {
350
+ --xh-_grid-span: 5;
351
+ }
352
+
353
+ [data-scope='grid'][data-part='item'][data-span='6'] {
354
+ --xh-_grid-span: 6;
355
+ }
356
+
357
+ [data-scope='grid'][data-part='item'][data-span='7'] {
358
+ --xh-_grid-span: 7;
359
+ }
360
+
361
+ [data-scope='grid'][data-part='item'][data-span='8'] {
362
+ --xh-_grid-span: 8;
363
+ }
364
+
365
+ [data-scope='grid'][data-part='item'][data-span='9'] {
366
+ --xh-_grid-span: 9;
367
+ }
368
+
369
+ [data-scope='grid'][data-part='item'][data-span='10'] {
370
+ --xh-_grid-span: 10;
371
+ }
372
+
373
+ [data-scope='grid'][data-part='item'][data-span='11'] {
374
+ --xh-_grid-span: 11;
375
+ }
376
+
377
+ [data-scope='grid'][data-part='item'][data-span='12'] {
378
+ --xh-_grid-span: 12;
379
+ }
380
+
381
+ /* —— 错列 —— */
382
+ /* 错 N 列 = 改从第 N+1 条列线起排,前面那 N 列空着。
383
+ 列线跟着书写方向走,RTL 下自动从另一头数。
384
+ 错的是列线不是「相对上一格再往后几格」:同一行里前面已经排到更后面时,这一格落到下一行的那条列线上。 */
385
+ [data-scope='grid'][data-part='item'][data-offset='1'] {
386
+ --xh-_grid-start: 2;
387
+ }
388
+
389
+ [data-scope='grid'][data-part='item'][data-offset='2'] {
390
+ --xh-_grid-start: 3;
391
+ }
392
+
393
+ [data-scope='grid'][data-part='item'][data-offset='3'] {
394
+ --xh-_grid-start: 4;
395
+ }
396
+
397
+ [data-scope='grid'][data-part='item'][data-offset='4'] {
398
+ --xh-_grid-start: 5;
399
+ }
400
+
401
+ [data-scope='grid'][data-part='item'][data-offset='5'] {
402
+ --xh-_grid-start: 6;
403
+ }
404
+
405
+ [data-scope='grid'][data-part='item'][data-offset='6'] {
406
+ --xh-_grid-start: 7;
407
+ }
408
+
409
+ [data-scope='grid'][data-part='item'][data-offset='7'] {
410
+ --xh-_grid-start: 8;
411
+ }
412
+
413
+ [data-scope='grid'][data-part='item'][data-offset='8'] {
414
+ --xh-_grid-start: 9;
415
+ }
416
+
417
+ [data-scope='grid'][data-part='item'][data-offset='9'] {
418
+ --xh-_grid-start: 10;
419
+ }
420
+
421
+ [data-scope='grid'][data-part='item'][data-offset='10'] {
422
+ --xh-_grid-start: 11;
423
+ }
424
+
425
+ [data-scope='grid'][data-part='item'][data-offset='11'] {
426
+ --xh-_grid-start: 12;
427
+ }
428
+ }
@@ -0,0 +1,21 @@
1
+ @layer xihan.components {
2
+ /* 文本按原样显示:命中位置是按原串逐字符算的,折叠掉连续空格与换行会让看到的
3
+ 与算出来的对不上。pre-wrap 保留空白但仍在容器边界换行 */
4
+ [data-scope='highlight'][data-part='root'] {
5
+ white-space: pre-wrap;
6
+ }
7
+
8
+ /* 浏览器给 mark 的默认底色是一个固定的亮黄,暗色主题下压在深底上刺眼、
9
+ 配的黑字也不随主题走;这里整份换成随主题走的品牌淡底 */
10
+ [data-scope='highlight'][data-part='mark'] {
11
+ padding-inline: var(--xh-space-0_5);
12
+ border-radius: var(--xh-highlight-radius, var(--xh-radius-sm));
13
+ background: var(--xh-highlight-bg, var(--xh-bg-brand-subtle));
14
+ color: var(--xh-highlight-fg, var(--xh-fg-brand-strong));
15
+ font-weight: var(--xh-font-weight-medium);
16
+ /* 命中片段跨行时两半各自收边,否则圆角与内边距只画在整段的首尾。
17
+ 两条都写:WebKit 只认带前缀那条 */
18
+ -webkit-box-decoration-break: clone;
19
+ box-decoration-break: clone;
20
+ }
21
+ }