@astryx-vue/lab 0.0.0-stage → 0.1.1

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.
@@ -0,0 +1,204 @@
1
+ @layer astryx.reset, astryx.tokens, astryx.base, astryx.components, astryx.overrides;
2
+
3
+ @layer astryx.components {
4
+ /*
5
+ * 尺寸、颜色和每一层的取值都从这里进:变体(data-variation)改层的内部变量,
6
+ * 尺寸(data-size)改边长和描边宽度,颜色(data-color)改 color。
7
+ * 使用方可以直接覆盖 --astryx-icon-* 这几个变量,不用碰选择器。
8
+ */
9
+
10
+ .astryx-svg-icon {
11
+ /* 层的默认值就是 linear 变体的取值,见下面的 data-variation 覆盖。 */
12
+ --_icon-primary-fill: none;
13
+ --_icon-primary-stroke: currentcolor;
14
+ --_icon-primary-opacity: 1;
15
+ --_icon-primary-stroke-role-fill: none;
16
+ --_icon-primary-stroke-role-stroke: currentcolor;
17
+ --_icon-primary-stroke-role-opacity: 1;
18
+ --_icon-primary-stroke-role-width: 1.5;
19
+ --_icon-secondary-fill: none;
20
+ --_icon-secondary-stroke: currentcolor;
21
+ --_icon-secondary-opacity: 1;
22
+ --_icon-secondary-stroke-role-fill: none;
23
+ --_icon-secondary-stroke-role-stroke: currentcolor;
24
+ --_icon-secondary-stroke-role-opacity: 1;
25
+ --_icon-secondary-stroke-role-width: 1.5;
26
+
27
+ display: inline-flex;
28
+ flex-shrink: 0;
29
+ width: var(--astryx-icon-size, 24px);
30
+ height: var(--astryx-icon-size, 24px);
31
+ padding-inline-start: var(--astryx-icon-inline-offset, 0px);
32
+ padding-block-start: var(--astryx-icon-block-offset, 0px);
33
+ }
34
+
35
+ /* 颜色角色,和 core 的 Icon 语义一致。 */
36
+ .astryx-svg-icon[data-color='primary'] {
37
+ color: var(--astryx-color-icon-primary, light-dark(#000000, #ffffff));
38
+ }
39
+
40
+ .astryx-svg-icon[data-color='secondary'] {
41
+ color: var(--astryx-color-icon-secondary, light-dark(#6a6a6a, #9e9e9e));
42
+ }
43
+
44
+ .astryx-svg-icon[data-color='disabled'] {
45
+ color: var(--astryx-color-icon-disabled, light-dark(#919191, #525252));
46
+ }
47
+
48
+ .astryx-svg-icon[data-color='accent'] {
49
+ color: var(--astryx-color-accent, light-dark(#1b1b1b, #f1f1f1));
50
+ }
51
+
52
+ .astryx-svg-icon[data-color='positive'] {
53
+ color: var(--astryx-color-success, light-dark(#00490b, #a4d6a3));
54
+ }
55
+
56
+ .astryx-svg-icon[data-color='negative'] {
57
+ color: var(--astryx-color-error, light-dark(#76000c, #ffc4be));
58
+ }
59
+
60
+ .astryx-svg-icon[data-color='warning'] {
61
+ color: var(--astryx-color-warning, light-dark(#4b3900, #f8d36a));
62
+ }
63
+
64
+ .astryx-svg-icon[data-color='inherit'] {
65
+ color: inherit;
66
+ }
67
+
68
+ /* 光学补偿:越小描边越粗,看上去粗细才一致。 */
69
+ .astryx-svg-icon[data-size='xsm'] {
70
+ --astryx-icon-size: 12px;
71
+ --astryx-icon-stroke-width: 2;
72
+ }
73
+
74
+ .astryx-svg-icon[data-size='sm'] {
75
+ --astryx-icon-size: 16px;
76
+ --astryx-icon-stroke-width: 1.75;
77
+ }
78
+
79
+ .astryx-svg-icon[data-size='md'] {
80
+ --astryx-icon-size: 20px;
81
+ --astryx-icon-stroke-width: 1.5;
82
+ }
83
+
84
+ .astryx-svg-icon[data-size='lg'] {
85
+ --astryx-icon-size: 24px;
86
+ --astryx-icon-stroke-width: 1.5;
87
+ }
88
+
89
+ /* linear:填充角色其实只描边,描边角色不透明。 */
90
+ .astryx-svg-icon[data-variation='linear'] {
91
+ --_icon-primary-fill: none;
92
+ --_icon-primary-stroke: currentcolor;
93
+ --_icon-primary-opacity: 1;
94
+ --_icon-primary-stroke-role-fill: none;
95
+ --_icon-primary-stroke-role-stroke: currentcolor;
96
+ --_icon-primary-stroke-role-opacity: 1;
97
+ --_icon-secondary-fill: none;
98
+ --_icon-secondary-stroke: currentcolor;
99
+ --_icon-secondary-opacity: 1;
100
+ --_icon-secondary-stroke-role-fill: none;
101
+ --_icon-secondary-stroke-role-stroke: currentcolor;
102
+ --_icon-secondary-stroke-role-opacity: 1;
103
+ }
104
+
105
+ /* bold:填充角色变实心(重叠靠遮罩挖),描边角色加粗。 */
106
+ .astryx-svg-icon[data-variation='bold'] {
107
+ --_icon-primary-fill: currentcolor;
108
+ --_icon-primary-stroke: none;
109
+ --_icon-primary-opacity: 1;
110
+ --_icon-primary-stroke-role-fill: none;
111
+ --_icon-primary-stroke-role-stroke: currentcolor;
112
+ --_icon-primary-stroke-role-opacity: 1;
113
+ --_icon-primary-stroke-role-width: 2;
114
+ --_icon-secondary-fill: currentcolor;
115
+ --_icon-secondary-stroke: none;
116
+ --_icon-secondary-opacity: 1;
117
+ --_icon-secondary-stroke-role-fill: none;
118
+ --_icon-secondary-stroke-role-stroke: currentcolor;
119
+ --_icon-secondary-stroke-role-opacity: 1;
120
+ --_icon-secondary-stroke-role-width: 2.5;
121
+ }
122
+
123
+ /* twotone:次层和描边角色淡下去,留出主次的层次。 */
124
+ .astryx-svg-icon[data-variation='twotone'] {
125
+ --_icon-primary-fill: none;
126
+ --_icon-primary-stroke: currentcolor;
127
+ --_icon-primary-opacity: 1;
128
+ --_icon-primary-stroke-role-fill: none;
129
+ --_icon-primary-stroke-role-stroke: currentcolor;
130
+ --_icon-primary-stroke-role-opacity: 0.4;
131
+ --_icon-secondary-fill: none;
132
+ --_icon-secondary-stroke: currentcolor;
133
+ --_icon-secondary-opacity: 0.4;
134
+ --_icon-secondary-stroke-role-fill: none;
135
+ --_icon-secondary-stroke-role-stroke: currentcolor;
136
+ --_icon-secondary-stroke-role-opacity: 0.4;
137
+ }
138
+
139
+ /* bulk:主层实心,次层和描边角色淡下去。 */
140
+ .astryx-svg-icon[data-variation='bulk'] {
141
+ --_icon-primary-fill: currentcolor;
142
+ --_icon-primary-stroke: none;
143
+ --_icon-primary-opacity: 1;
144
+ --_icon-primary-stroke-role-fill: none;
145
+ --_icon-primary-stroke-role-stroke: currentcolor;
146
+ --_icon-primary-stroke-role-opacity: 0.4;
147
+ --_icon-secondary-fill: currentcolor;
148
+ --_icon-secondary-stroke: none;
149
+ --_icon-secondary-opacity: 0.4;
150
+ --_icon-secondary-stroke-role-fill: none;
151
+ --_icon-secondary-stroke-role-stroke: currentcolor;
152
+ --_icon-secondary-stroke-role-opacity: 0.4;
153
+ }
154
+
155
+ /* broken:次层整层不画。 */
156
+ .astryx-svg-icon[data-variation='broken'] {
157
+ --_icon-primary-fill: none;
158
+ --_icon-primary-stroke: currentcolor;
159
+ --_icon-primary-opacity: 1;
160
+ --_icon-primary-stroke-role-fill: none;
161
+ --_icon-primary-stroke-role-stroke: currentcolor;
162
+ --_icon-primary-stroke-role-opacity: 1;
163
+ --_icon-secondary-fill: none;
164
+ --_icon-secondary-stroke: currentcolor;
165
+ --_icon-secondary-opacity: 0;
166
+ --_icon-secondary-stroke-role-fill: none;
167
+ --_icon-secondary-stroke-role-stroke: currentcolor;
168
+ --_icon-secondary-stroke-role-opacity: 0;
169
+ }
170
+
171
+ /* 四个图层组:主层/次层各分出填充角色和描边角色。 */
172
+ .astryx-svg-icon__layer {
173
+ stroke-linecap: var(--astryx-icon-stroke-linecap, round);
174
+ stroke-linejoin: var(--astryx-icon-stroke-linejoin, round);
175
+ }
176
+
177
+ .astryx-svg-icon__layer--primary-fill {
178
+ fill: var(--_icon-primary-fill);
179
+ stroke: var(--_icon-primary-stroke);
180
+ opacity: var(--_icon-primary-opacity);
181
+ stroke-width: var(--astryx-icon-stroke-width, 1.5);
182
+ }
183
+
184
+ .astryx-svg-icon__layer--primary-stroke {
185
+ fill: var(--_icon-primary-stroke-role-fill);
186
+ stroke: var(--_icon-primary-stroke-role-stroke);
187
+ opacity: var(--_icon-primary-stroke-role-opacity);
188
+ stroke-width: var(--_icon-primary-stroke-role-width);
189
+ }
190
+
191
+ .astryx-svg-icon__layer--secondary-fill {
192
+ fill: var(--_icon-secondary-fill);
193
+ stroke: var(--_icon-secondary-stroke);
194
+ opacity: var(--_icon-secondary-opacity);
195
+ stroke-width: var(--astryx-icon-stroke-width, 1.5);
196
+ }
197
+
198
+ .astryx-svg-icon__layer--secondary-stroke {
199
+ fill: var(--_icon-secondary-stroke-role-fill);
200
+ stroke: var(--_icon-secondary-stroke-role-stroke);
201
+ opacity: var(--_icon-secondary-stroke-role-opacity);
202
+ stroke-width: var(--_icon-secondary-stroke-role-width);
203
+ }
204
+ }
@@ -0,0 +1,46 @@
1
+ @layer astryx.reset, astryx.tokens, astryx.base, astryx.components, astryx.overrides;
2
+
3
+ @layer astryx.components {
4
+ /* 弹层面板:两栏区域自己滚,底部操作一直留在弹层底部。宽度和去内边距由组件传给 ComplexSelector 的 contentStyle 决定。 */
5
+ .astryx-transfer-list-selector__surface {
6
+ display: flex;
7
+ flex-direction: column;
8
+ min-width: 0;
9
+ min-height: 0;
10
+ max-height: inherit;
11
+ }
12
+
13
+ /* 两栏区域自己滚,底部按钮一直留在弹层里。 */
14
+ .astryx-transfer-list-selector__fieldset {
15
+ flex-grow: 1;
16
+ flex-shrink: 1;
17
+ flex-basis: auto;
18
+ min-width: 0;
19
+ min-height: 0;
20
+ margin: 0;
21
+ padding: 0;
22
+ border: 0;
23
+ overflow-y: auto;
24
+ overscroll-behavior: contain;
25
+ }
26
+
27
+ /* 提交中的字段区读起来像不可用,但仍然能聚焦:禁用它会把焦点丢到 body。 */
28
+ .astryx-transfer-list-selector__surface[aria-busy='true'] .astryx-transfer-list-selector__fieldset {
29
+ cursor: progress;
30
+ }
31
+
32
+ .astryx-transfer-list-selector__fieldset:disabled {
33
+ cursor: default;
34
+ }
35
+
36
+ .astryx-transfer-list-selector__footer {
37
+ display: flex;
38
+ flex-shrink: 0;
39
+ align-items: center;
40
+ justify-content: flex-end;
41
+ gap: var(--astryx-spacing-2, 8px);
42
+ padding: var(--astryx-spacing-3, 12px);
43
+ border-block-start: var(--astryx-border-width, 1px) solid var(--astryx-color-border, #00000014);
44
+ background-color: var(--astryx-color-background-surface, #fff);
45
+ }
46
+ }
@@ -0,0 +1,234 @@
1
+ @layer astryx.reset, astryx.tokens, astryx.base, astryx.components, astryx.overrides;
2
+
3
+ @layer astryx.components {
4
+ /*
5
+ * 两栏之间靠容器查询决定是并排还是上下堆叠:宽的时候左右分栏,
6
+ * 窄的时候改成上下两段,分隔线也跟着从竖的变横的。
7
+ */
8
+ .astryx-transfer-list {
9
+ display: flex;
10
+ flex-direction: column;
11
+ gap: 0;
12
+ min-width: 0;
13
+ container-type: inline-size;
14
+ }
15
+
16
+ .astryx-transfer-list__heading {
17
+ display: flex;
18
+ flex-direction: column;
19
+ gap: var(--astryx-spacing-1, 4px);
20
+ padding-inline: var(--astryx-spacing-3, 12px);
21
+ }
22
+
23
+ .astryx-transfer-list__controls {
24
+ display: flex;
25
+ align-items: flex-end;
26
+ gap: var(--astryx-spacing-2, 8px);
27
+ min-width: 0;
28
+ padding: var(--astryx-spacing-3, 12px);
29
+ }
30
+
31
+ /* core 的 TextInput 外壳会缩到内容宽,这里让它撑满这一行。 */
32
+ .astryx-transfer-list__search {
33
+ flex: 1;
34
+ min-width: 0;
35
+ }
36
+
37
+ .astryx-transfer-list-collection {
38
+ display: grid;
39
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
40
+ gap: 0;
41
+ min-width: 0;
42
+ }
43
+
44
+ .astryx-transfer-list-panel {
45
+ display: flex;
46
+ flex-direction: column;
47
+ min-width: 0;
48
+ overflow: hidden;
49
+ /* 焦点环画在面板自己的边上,所以往里收,不能超出组件边界。 */
50
+ outline-offset: 0;
51
+ }
52
+
53
+ .astryx-transfer-list-panel:focus-visible {
54
+ outline: var(--astryx-focus-outline-width, 2px) var(--astryx-focus-outline-style, solid) var(--astryx-focus-outline-color, currentcolor);
55
+ outline-offset: calc(-1 * var(--astryx-focus-outline-width, 2px));
56
+ }
57
+
58
+ /* 可选栏和已选栏之间那条分隔线。窄屏时改成上边线。 */
59
+ .astryx-transfer-list-panel[data-side='available'] {
60
+ border-inline-start: var(--astryx-border-width, 1px) solid var(--astryx-color-border, #00000014);
61
+ }
62
+
63
+ .astryx-transfer-list-panel__header {
64
+ display: flex;
65
+ align-items: center;
66
+ justify-content: space-between;
67
+ gap: var(--astryx-spacing-2, 8px);
68
+ padding-block: var(--astryx-spacing-2, 8px);
69
+ padding-inline: var(--astryx-spacing-3, 12px);
70
+ border-block-end: var(--astryx-border-width, 1px) solid var(--astryx-color-border, #00000014);
71
+ }
72
+
73
+ /*
74
+ * 表头的批量操作看起来像文字链接,但点击区域仍然要够 24px,
75
+ * 所以只把上下内边距压平、给一个最小高度,文字位置不变。
76
+ */
77
+ .astryx-transfer-list-header-action {
78
+ height: auto;
79
+ min-block-size: var(--astryx-size-element-sm, 28px);
80
+ padding-block: 0;
81
+ padding-inline: 0;
82
+ border: 0;
83
+ border-radius: 0;
84
+ background-color: transparent;
85
+ color: var(--astryx-color-text-accent, light-dark(#0a66ff, #7cb8ff));
86
+ font-size: var(--astryx-text-body-size, 0.875rem);
87
+ font-weight: var(--astryx-text-body-weight, 400);
88
+ line-height: var(--astryx-text-body-leading, 1.4);
89
+ cursor: pointer;
90
+ }
91
+
92
+ .astryx-transfer-list-header-action:hover:where(:not(:disabled, [aria-disabled='true'])) {
93
+ text-decoration: underline;
94
+ }
95
+
96
+ /* 禁用时指针样式和普通文字一致,不做「不可点」的暗示。 */
97
+ .astryx-transfer-list-header-action:is(:disabled, [aria-disabled='true']) {
98
+ color: var(--astryx-color-text-secondary, light-dark(#6a6a6a, #9e9e9e));
99
+ cursor: default;
100
+ }
101
+
102
+ .astryx-transfer-list-header-action:focus-visible {
103
+ outline: var(--astryx-focus-outline-width, 2px) var(--astryx-focus-outline-style, solid) var(--astryx-focus-outline-color, currentcolor);
104
+ outline-offset: var(--astryx-focus-outline-offset, 2px);
105
+ }
106
+
107
+ /* 面板主体:给一个高度区间,条目多了自己滚,不让整页跟着变长。 */
108
+ .astryx-transfer-list-panel__body {
109
+ min-block-size: var(--astryx-transfer-list-panel-min-block-size, 12rem);
110
+ max-block-size: var(--astryx-transfer-list-panel-max-block-size, 20rem);
111
+ overflow-y: auto;
112
+ overscroll-behavior: contain;
113
+ scrollbar-gutter: stable;
114
+ padding: 0;
115
+ }
116
+
117
+ .astryx-transfer-list-panel__group-heading {
118
+ padding-block: var(--astryx-spacing-1, 4px);
119
+ padding-inline: var(--astryx-spacing-3, 12px);
120
+ }
121
+
122
+ .astryx-transfer-list-panel__group-heading:first-child {
123
+ margin-block-start: 0;
124
+ }
125
+
126
+ .astryx-transfer-list-item {
127
+ min-width: 0;
128
+ padding-inline: var(--astryx-spacing-3, 12px);
129
+ }
130
+
131
+ .astryx-transfer-list-panel__empty {
132
+ display: flex;
133
+ align-items: center;
134
+ justify-content: center;
135
+ min-block-size: var(--astryx-transfer-list-panel-min-block-size, 12rem);
136
+ padding: var(--astryx-spacing-4, 16px);
137
+ text-align: center;
138
+ }
139
+
140
+ /* 键盘拿起中的行铺一层强调色,表示它正在被移动。 */
141
+ .astryx-transfer-list-item[data-state='reordering'] {
142
+ background-color: var(--astryx-color-accent-muted, light-dark(#f1f1f1, #262626));
143
+ }
144
+
145
+ /* 拖动中的源行半透明,说明它是被拿起来那一行。 */
146
+ .astryx-transfer-list-item[data-transfer-list-reorder-source] {
147
+ opacity: 0.5;
148
+ user-select: none;
149
+ }
150
+
151
+ /* 落点指示线画在行的上边或下边。 */
152
+ .astryx-transfer-list-item[data-transfer-list-drop-target] {
153
+ position: relative;
154
+ }
155
+
156
+ .astryx-transfer-list-item[data-transfer-list-drop-target]::before,
157
+ .astryx-transfer-list-item[data-transfer-list-drop-target]::after {
158
+ content: '';
159
+ position: absolute;
160
+ inset-inline: 0;
161
+ height: var(--astryx-spacing-0-5, 2px);
162
+ border-radius: var(--astryx-radius-full, 9999px);
163
+ background-color: var(--astryx-color-accent, light-dark(#0a0a0a, #fafafa));
164
+ pointer-events: none;
165
+ z-index: 2;
166
+ }
167
+
168
+ .astryx-transfer-list-item[data-transfer-list-drop-target='before']::before {
169
+ inset-block-start: calc(-1 * var(--astryx-spacing-0-5, 2px));
170
+ }
171
+
172
+ .astryx-transfer-list-item[data-transfer-list-drop-target='after']::after {
173
+ inset-block-end: calc(-1 * var(--astryx-spacing-0-5, 2px));
174
+ }
175
+
176
+ /*
177
+ * 手柄给出抓取手势,并且吃掉触摸滚动,否则手机上竖着拖会变成滚动页面。
178
+ * 禁用时回到普通指针。
179
+ */
180
+ .astryx-transfer-list-reorder-handle {
181
+ margin-inline-start: calc(-1 * var(--astryx-spacing-1-5, 6px));
182
+ cursor: grab;
183
+ touch-action: none;
184
+ }
185
+
186
+ .astryx-transfer-list-reorder-handle[aria-pressed='true'] {
187
+ cursor: grabbing;
188
+ }
189
+
190
+ .astryx-transfer-list-reorder-handle:is(:disabled, [aria-disabled='true']) {
191
+ cursor: default;
192
+ }
193
+
194
+ /* 跟着指针走的克隆体。位置的 top/left/width 由组件内联给出。 */
195
+ .astryx-transfer-list-drag-preview {
196
+ position: fixed;
197
+ z-index: 2147483000;
198
+ opacity: 0.5;
199
+ pointer-events: none;
200
+ user-select: none;
201
+ will-change: transform;
202
+ margin: 0;
203
+ padding-inline: var(--astryx-spacing-3, 12px);
204
+ list-style: none;
205
+ }
206
+
207
+ /* 窄的时候改成上下两栏,分隔线也从竖的换成横的。 */
208
+ @container (max-width: 40rem) {
209
+ .astryx-transfer-list-collection {
210
+ grid-template-columns: minmax(0, 1fr);
211
+ }
212
+
213
+ .astryx-transfer-list-panel[data-side='available'] {
214
+ border-inline-start: 0;
215
+ border-block-start: var(--astryx-border-width, 1px) solid var(--astryx-color-border, #00000014);
216
+ }
217
+
218
+ .astryx-transfer-list-panel__header {
219
+ background-color: var(--astryx-color-background-body, #fff);
220
+ }
221
+
222
+ .astryx-transfer-list-panel__body {
223
+ min-block-size: 0;
224
+ max-block-size: none;
225
+ overflow-y: visible;
226
+ overscroll-behavior: auto;
227
+ scrollbar-gutter: auto;
228
+ }
229
+
230
+ .astryx-transfer-list-panel__empty {
231
+ min-block-size: 0;
232
+ }
233
+ }
234
+ }