@scalewing/react 1.8.0 → 1.9.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.
- package/CHANGELOG.md +140 -0
- package/README.md +69 -2
- package/dist/anchored-position.d.ts +28 -0
- package/dist/anchored-position.js +17 -0
- package/dist/calendar-keys.d.ts +19 -0
- package/dist/calendar-keys.js +39 -0
- package/dist/calendar-labels.d.ts +12 -0
- package/dist/calendar-labels.js +32 -0
- package/dist/calendar-month.d.ts +36 -0
- package/dist/calendar-month.js +111 -0
- package/dist/calendar-years.d.ts +14 -0
- package/dist/calendar-years.js +20 -0
- package/dist/components/Accordion.d.ts +6 -1
- package/dist/components/Accordion.js +12 -3
- package/dist/components/ActionBar.d.ts +30 -0
- package/dist/components/ActionBar.js +13 -0
- package/dist/components/Box.d.ts +7 -3
- package/dist/components/Box.js +2 -2
- package/dist/components/DateField.d.ts +15 -1
- package/dist/components/DateField.js +58 -18
- package/dist/components/Field.d.ts +5 -1
- package/dist/components/Field.js +16 -4
- package/dist/components/FieldAdornment.d.ts +20 -0
- package/dist/components/FieldAdornment.js +34 -0
- package/dist/components/Grid.d.ts +4 -1
- package/dist/components/Grid.js +2 -2
- package/dist/components/Progress.d.ts +3 -1
- package/dist/components/Progress.js +2 -2
- package/dist/components/date-field/CalendarDialog.d.ts +26 -0
- package/dist/components/date-field/CalendarDialog.js +93 -0
- package/dist/components/date-field/CalendarGrid.d.ts +23 -0
- package/dist/components/date-field/CalendarGrid.js +36 -0
- package/dist/components/date-field/CalendarHeader.d.ts +18 -0
- package/dist/components/date-field/CalendarHeader.js +33 -0
- package/dist/components/date-field/DateFieldGlyph.d.ts +9 -0
- package/dist/components/date-field/DateFieldGlyph.js +15 -0
- package/dist/components/date-field/use-anchored-popover.d.ts +8 -0
- package/dist/components/date-field/use-anchored-popover.js +61 -0
- package/dist/components/date-field/use-date-entry.d.ts +20 -0
- package/dist/components/date-field/use-date-entry.js +61 -0
- package/dist/components/date-field/use-lang-locale.d.ts +7 -0
- package/dist/components/date-field/use-lang-locale.js +17 -0
- package/dist/css/css-accordion.js +55 -8
- package/dist/css/css-action-bar.d.ts +4 -0
- package/dist/css/css-action-bar.js +99 -0
- package/dist/css/css-action-menu.js +2 -1
- package/dist/css/css-box-border.d.ts +5 -0
- package/dist/css/css-box-border.js +24 -0
- package/dist/css/css-chrome.js +2 -1
- package/dist/css/css-components.js +10 -6
- package/dist/css/css-data.js +2 -1
- package/dist/css/css-date-field.js +241 -11
- package/dist/css/css-denomination-grid.js +2 -1
- package/dist/css/css-document.d.ts +2 -0
- package/dist/css/css-document.js +2 -1
- package/dist/css/css-field.js +61 -1
- package/dist/css/css-select.js +2 -1
- package/dist/css/css-tooltip.js +2 -1
- package/dist/css/stacking.d.ts +10 -0
- package/dist/css/stacking.js +47 -0
- package/dist/css/stylesheet.js +4 -0
- package/dist/date-entry-validity.d.ts +10 -0
- package/dist/date-entry-validity.js +16 -0
- package/dist/date-entry.d.ts +32 -0
- package/dist/date-entry.js +106 -0
- package/dist/date-field-labels.d.ts +38 -0
- package/dist/date-field-labels.js +22 -0
- package/dist/date-field-locale.d.ts +8 -0
- package/dist/date-field-locale.js +27 -0
- package/dist/date-formatters.d.ts +13 -0
- package/dist/date-formatters.js +28 -0
- package/dist/date-only.d.ts +23 -0
- package/dist/date-only.js +63 -9
- package/dist/index.d.ts +5 -3
- package/dist/index.js +3 -2
- package/dist/styles.css +388 -21
- package/package.json +1 -1
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { typographyVariants } from '@scalewing/tokens';
|
|
2
|
+
import { zIndex } from './stacking.js';
|
|
2
3
|
const body = typographyVariants.body;
|
|
3
4
|
const label = typographyVariants.label;
|
|
4
5
|
const caption = typographyVariants.caption;
|
|
5
|
-
|
|
6
|
+
/* The calendar button, month steps, and days are one square control wide. */
|
|
7
|
+
const square = 'var(--sw-control-md-min-height)';
|
|
8
|
+
/* Wide enough for "MM/DD/YYYY" in the system sans. */
|
|
9
|
+
const entryWidth = '12ch';
|
|
10
|
+
/* Outranks the canvas rule for text inputs so the button keeps its room. */
|
|
11
|
+
const input = '.sw-date-field .sw-date-field-control > .sw-date-field-input';
|
|
12
|
+
function fieldRules() {
|
|
6
13
|
return `.sw-date-field {
|
|
7
14
|
display: flex;
|
|
8
15
|
flex-direction: column;
|
|
@@ -20,7 +27,15 @@ export function cssDateFieldClasses() {
|
|
|
20
27
|
line-height: ${label.lineHeight}px;
|
|
21
28
|
}
|
|
22
29
|
|
|
23
|
-
.sw-date-field-
|
|
30
|
+
.sw-date-field-control {
|
|
31
|
+
align-self: flex-start;
|
|
32
|
+
display: flex;
|
|
33
|
+
max-width: 100%;
|
|
34
|
+
min-width: 0;
|
|
35
|
+
position: relative;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
${input} {
|
|
24
39
|
background: var(--sw-glass-fill);
|
|
25
40
|
border: 1px solid var(--sw-color-border);
|
|
26
41
|
border-radius: var(--sw-radius-sm);
|
|
@@ -28,26 +43,78 @@ export function cssDateFieldClasses() {
|
|
|
28
43
|
color: var(--sw-color-text);
|
|
29
44
|
font-family: var(--sw-font-sans);
|
|
30
45
|
font-size: ${body.fontSize}px;
|
|
46
|
+
font-variant-numeric: tabular-nums;
|
|
47
|
+
margin: 0;
|
|
48
|
+
max-width: 100%;
|
|
31
49
|
min-height: var(--sw-control-md-min-height);
|
|
32
50
|
min-width: 0;
|
|
33
|
-
padding-inline: var(--sw-control-md-padding-inline);
|
|
34
|
-
width:
|
|
51
|
+
padding-inline: var(--sw-control-md-padding-inline) ${square};
|
|
52
|
+
width: calc(${entryWidth} + var(--sw-control-md-padding-inline) + ${square});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
${input}::placeholder {
|
|
56
|
+
color: var(--sw-color-muted);
|
|
57
|
+
opacity: 1;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
${input}:focus {
|
|
61
|
+
box-shadow: none;
|
|
62
|
+
outline: none;
|
|
35
63
|
}
|
|
36
64
|
|
|
37
|
-
|
|
65
|
+
${input}:focus-visible {
|
|
38
66
|
outline: var(--sw-focus-ring-width) solid var(--sw-color-accent);
|
|
39
67
|
outline-offset: var(--sw-focus-ring-offset);
|
|
40
68
|
}
|
|
41
69
|
|
|
42
|
-
|
|
70
|
+
${input}[aria-invalid='true'] {
|
|
43
71
|
border-color: var(--sw-color-danger);
|
|
44
72
|
}
|
|
45
73
|
|
|
46
|
-
|
|
74
|
+
${input}:disabled,
|
|
75
|
+
.sw-date-field-button:disabled {
|
|
47
76
|
cursor: not-allowed;
|
|
48
77
|
opacity: var(--sw-disabled-opacity);
|
|
49
78
|
}
|
|
50
79
|
|
|
80
|
+
.sw-date-field-button {
|
|
81
|
+
align-items: center;
|
|
82
|
+
appearance: none;
|
|
83
|
+
background: transparent;
|
|
84
|
+
border: 0;
|
|
85
|
+
border-radius: var(--sw-radius-sm);
|
|
86
|
+
color: var(--sw-color-muted);
|
|
87
|
+
cursor: pointer;
|
|
88
|
+
display: flex;
|
|
89
|
+
inset-block: 0;
|
|
90
|
+
inset-inline-end: 0;
|
|
91
|
+
justify-content: center;
|
|
92
|
+
margin: 0;
|
|
93
|
+
padding: 0;
|
|
94
|
+
position: absolute;
|
|
95
|
+
width: ${square};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.sw-date-field-button:hover:not(:disabled),
|
|
99
|
+
.sw-date-field-button[aria-expanded='true'] {
|
|
100
|
+
color: var(--sw-color-text);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.sw-date-field-glyph {
|
|
104
|
+
fill: none;
|
|
105
|
+
flex: none;
|
|
106
|
+
height: var(--sw-space-5);
|
|
107
|
+
stroke: currentColor;
|
|
108
|
+
stroke-linecap: round;
|
|
109
|
+
stroke-linejoin: round;
|
|
110
|
+
stroke-width: 1.75;
|
|
111
|
+
width: var(--sw-space-5);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
[dir='rtl'] .sw-date-field-glyph-directional {
|
|
115
|
+
transform: scaleX(-1);
|
|
116
|
+
}
|
|
117
|
+
|
|
51
118
|
.sw-date-field-description,
|
|
52
119
|
.sw-date-field-error {
|
|
53
120
|
font-family: var(--sw-font-sans);
|
|
@@ -56,22 +123,185 @@ export function cssDateFieldClasses() {
|
|
|
56
123
|
}
|
|
57
124
|
|
|
58
125
|
.sw-date-field-description { color: var(--sw-color-muted); }
|
|
59
|
-
.sw-date-field-error { color: var(--sw-color-danger); }
|
|
126
|
+
.sw-date-field-error { color: var(--sw-color-danger); }`;
|
|
127
|
+
}
|
|
128
|
+
function calendarRules() {
|
|
129
|
+
return `.sw-date-field-calendar {
|
|
130
|
+
background: var(--sw-glass-fill);
|
|
131
|
+
border: 1px solid var(--sw-glass-border);
|
|
132
|
+
border-radius: var(--sw-radius-md);
|
|
133
|
+
box-shadow: var(--sw-elevation-md), inset 0 1px 0 var(--sw-glass-specular);
|
|
134
|
+
backdrop-filter: blur(var(--sw-glass-blur)) saturate(var(--sw-glass-saturate));
|
|
135
|
+
-webkit-backdrop-filter: blur(var(--sw-glass-blur)) saturate(var(--sw-glass-saturate));
|
|
136
|
+
box-sizing: border-box;
|
|
137
|
+
color: var(--sw-color-text);
|
|
138
|
+
display: flex;
|
|
139
|
+
flex-direction: column;
|
|
140
|
+
font-family: var(--sw-font-sans);
|
|
141
|
+
gap: var(--sw-space-2);
|
|
142
|
+
height: auto;
|
|
143
|
+
inset: auto;
|
|
144
|
+
margin: 0;
|
|
145
|
+
max-width: calc(100vw - var(--sw-space-2) - var(--sw-space-2));
|
|
146
|
+
overflow: visible;
|
|
147
|
+
padding: var(--sw-space-3);
|
|
148
|
+
position: fixed;
|
|
149
|
+
width: max-content;
|
|
150
|
+
${zIndex('popup')}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.sw-date-field-header {
|
|
154
|
+
align-items: center;
|
|
155
|
+
display: flex;
|
|
156
|
+
gap: var(--sw-space-1);
|
|
157
|
+
justify-content: space-between;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.sw-date-field-jump {
|
|
161
|
+
display: flex;
|
|
162
|
+
gap: var(--sw-space-1);
|
|
163
|
+
min-width: 0;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.sw-date-field-step {
|
|
167
|
+
align-items: center;
|
|
168
|
+
appearance: none;
|
|
169
|
+
background: transparent;
|
|
170
|
+
border: 0;
|
|
171
|
+
border-radius: var(--sw-radius-pill);
|
|
172
|
+
color: var(--sw-color-text);
|
|
173
|
+
cursor: pointer;
|
|
174
|
+
display: flex;
|
|
175
|
+
flex: none;
|
|
176
|
+
height: ${square};
|
|
177
|
+
justify-content: center;
|
|
178
|
+
margin: 0;
|
|
179
|
+
padding: 0;
|
|
180
|
+
width: ${square};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.sw-date-field-step[aria-disabled='true'] {
|
|
184
|
+
cursor: not-allowed;
|
|
185
|
+
opacity: var(--sw-disabled-opacity);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.sw-date-field-grid {
|
|
189
|
+
border-collapse: separate;
|
|
190
|
+
border-spacing: 0;
|
|
191
|
+
table-layout: fixed;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.sw-date-field-grid th {
|
|
195
|
+
color: var(--sw-color-muted);
|
|
196
|
+
font-size: ${caption.fontSize}px;
|
|
197
|
+
font-weight: normal;
|
|
198
|
+
line-height: ${caption.lineHeight}px;
|
|
199
|
+
padding: 0 0 var(--sw-space-1);
|
|
200
|
+
text-align: center;
|
|
201
|
+
}
|
|
60
202
|
|
|
61
|
-
|
|
62
|
-
|
|
203
|
+
.sw-date-field-day {
|
|
204
|
+
border: 1px solid transparent;
|
|
205
|
+
border-radius: var(--sw-radius-pill);
|
|
206
|
+
box-sizing: border-box;
|
|
207
|
+
cursor: pointer;
|
|
208
|
+
font-size: ${label.fontSize}px;
|
|
209
|
+
font-variant-numeric: tabular-nums;
|
|
210
|
+
height: ${square};
|
|
211
|
+
padding: 0;
|
|
212
|
+
text-align: center;
|
|
213
|
+
vertical-align: middle;
|
|
214
|
+
width: ${square};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.sw-date-field-day-outside {
|
|
218
|
+
color: var(--sw-color-muted);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.sw-date-field-step:hover:not([aria-disabled='true']),
|
|
222
|
+
.sw-date-field-day:hover:not([aria-disabled='true']) {
|
|
223
|
+
background: color-mix(in srgb, var(--sw-color-muted) 16%, transparent);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.sw-date-field-day[aria-current='date'] {
|
|
227
|
+
border-color: var(--sw-color-accent);
|
|
228
|
+
color: var(--sw-color-accent);
|
|
229
|
+
font-weight: ${label.fontWeight};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.sw-date-field-day[aria-selected='true'],
|
|
233
|
+
.sw-date-field-day[aria-selected='true']:hover {
|
|
234
|
+
background: var(--sw-color-accent);
|
|
235
|
+
border-color: var(--sw-color-accent);
|
|
236
|
+
color: var(--sw-color-onAccent);
|
|
237
|
+
font-weight: ${label.fontWeight};
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.sw-date-field-day[aria-disabled='true'] {
|
|
241
|
+
cursor: not-allowed;
|
|
242
|
+
opacity: var(--sw-disabled-opacity);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.sw-date-field-button:focus,
|
|
246
|
+
.sw-date-field-step:focus,
|
|
247
|
+
.sw-date-field-day:focus {
|
|
248
|
+
outline: none;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.sw-date-field-button:focus-visible,
|
|
252
|
+
.sw-date-field-step:focus-visible,
|
|
253
|
+
.sw-date-field-day:focus-visible {
|
|
254
|
+
outline: var(--sw-focus-ring-width) solid var(--sw-color-accent);
|
|
255
|
+
outline-offset: var(--sw-focus-ring-offset);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.sw-date-field-footer {
|
|
259
|
+
display: flex;
|
|
260
|
+
gap: var(--sw-space-1);
|
|
261
|
+
justify-content: flex-end;
|
|
262
|
+
}`;
|
|
263
|
+
}
|
|
264
|
+
function adaptiveRules() {
|
|
265
|
+
return `@media (prefers-reduced-transparency: reduce) {
|
|
266
|
+
${input} { background: var(--sw-color-surface); }
|
|
63
267
|
}
|
|
64
268
|
|
|
65
269
|
@media (forced-colors: active) {
|
|
66
|
-
|
|
270
|
+
${input}[aria-invalid='true'] { border-color: CanvasText; }
|
|
271
|
+
.sw-date-field-calendar { border-color: CanvasText; }
|
|
272
|
+
.sw-date-field-day[aria-current='date'] { border-color: CanvasText; }
|
|
273
|
+
.sw-date-field-day[aria-selected='true'] {
|
|
274
|
+
background: Highlight;
|
|
275
|
+
color: HighlightText;
|
|
276
|
+
forced-color-adjust: none;
|
|
277
|
+
}
|
|
67
278
|
}`;
|
|
68
279
|
}
|
|
280
|
+
export function cssDateFieldClasses() {
|
|
281
|
+
return `${fieldRules()}
|
|
282
|
+
|
|
283
|
+
${calendarRules()}
|
|
284
|
+
|
|
285
|
+
${adaptiveRules()}`;
|
|
286
|
+
}
|
|
69
287
|
export function dateFieldClassCatalog() {
|
|
70
288
|
return [
|
|
71
289
|
'sw-date-field',
|
|
72
290
|
'sw-date-field-label',
|
|
291
|
+
'sw-date-field-control',
|
|
73
292
|
'sw-date-field-input',
|
|
293
|
+
'sw-date-field-button',
|
|
294
|
+
'sw-date-field-glyph',
|
|
295
|
+
'sw-date-field-glyph-directional',
|
|
74
296
|
'sw-date-field-description',
|
|
75
297
|
'sw-date-field-error',
|
|
298
|
+
'sw-date-field-calendar',
|
|
299
|
+
'sw-date-field-header',
|
|
300
|
+
'sw-date-field-jump',
|
|
301
|
+
'sw-date-field-step',
|
|
302
|
+
'sw-date-field-grid',
|
|
303
|
+
'sw-date-field-day',
|
|
304
|
+
'sw-date-field-day-outside',
|
|
305
|
+
'sw-date-field-footer',
|
|
76
306
|
];
|
|
77
307
|
}
|
|
@@ -2,6 +2,7 @@ import { typographyVariants } from '@scalewing/tokens';
|
|
|
2
2
|
import { breakpointQuery } from './breakpoints.js';
|
|
3
3
|
import { badgeTones } from './css-data.js';
|
|
4
4
|
import { scrollRegionRules } from './css-scroll-region.js';
|
|
5
|
+
import { zIndex } from './stacking.js';
|
|
5
6
|
const caption = typographyVariants.caption;
|
|
6
7
|
const data = typographyVariants.data;
|
|
7
8
|
const label = typographyVariants.label;
|
|
@@ -81,7 +82,7 @@ ${scrollRegionRules('.sw-denomination-scroll')}
|
|
|
81
82
|
-webkit-backdrop-filter: blur(var(--sw-glass-blur)) saturate(var(--sw-glass-saturate));
|
|
82
83
|
inset-inline-start: 0;
|
|
83
84
|
position: sticky;
|
|
84
|
-
|
|
85
|
+
${zIndex('stickyCell')}
|
|
85
86
|
}
|
|
86
87
|
|
|
87
88
|
/*
|
|
@@ -1 +1,3 @@
|
|
|
1
|
+
/** The frame every native text control draws: fill, hairline border, radius. */
|
|
2
|
+
export declare const controlSurface = "background-color: var(--sw-glass-fill);\n border: 1px solid var(--sw-color-border);\n border-radius: var(--sw-radius-sm);\n color: inherit;\n font-family: inherit;\n font-size: inherit;\n padding-inline: var(--sw-control-md-padding-inline);";
|
|
1
3
|
export declare function cssDocumentCanvas(): string;
|
package/dist/css/css-document.js
CHANGED
|
@@ -10,7 +10,8 @@ const typedInputs = [
|
|
|
10
10
|
'input:not([type])',
|
|
11
11
|
'textarea',
|
|
12
12
|
].join(', ');
|
|
13
|
-
|
|
13
|
+
/** The frame every native text control draws: fill, hairline border, radius. */
|
|
14
|
+
export const controlSurface = `background-color: var(--sw-glass-fill);
|
|
14
15
|
border: 1px solid var(--sw-color-border);
|
|
15
16
|
border-radius: var(--sw-radius-sm);
|
|
16
17
|
color: inherit;
|
package/dist/css/css-field.js
CHANGED
|
@@ -1,5 +1,58 @@
|
|
|
1
1
|
import { typographyVariants } from '@scalewing/tokens';
|
|
2
|
+
import { controlSurface } from './css-document.js';
|
|
2
3
|
const caption = typographyVariants.caption;
|
|
4
|
+
/*
|
|
5
|
+
* A prefix or suffix sits inside the control frame: the wrapper draws the
|
|
6
|
+
* canvas control surface and the focus ring, and the native input inside it
|
|
7
|
+
* drops its own frame so the text and the value read as one control.
|
|
8
|
+
*/
|
|
9
|
+
function adornmentRules() {
|
|
10
|
+
return `.sw-field-adorned {
|
|
11
|
+
${controlSurface}
|
|
12
|
+
align-items: center;
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
cursor: text;
|
|
15
|
+
display: flex;
|
|
16
|
+
gap: var(--sw-space-1);
|
|
17
|
+
min-height: var(--sw-control-md-min-height);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
[data-theme] .sw-field-adorned > input {
|
|
21
|
+
align-self: stretch;
|
|
22
|
+
background: transparent;
|
|
23
|
+
border: 0;
|
|
24
|
+
border-radius: 0;
|
|
25
|
+
flex: 1 1 auto;
|
|
26
|
+
min-height: 0;
|
|
27
|
+
min-width: 0;
|
|
28
|
+
padding-inline: 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
[data-theme] .sw-field-adorned > input:focus-visible { outline: none; }
|
|
32
|
+
|
|
33
|
+
.sw-field-adorned:focus-within {
|
|
34
|
+
outline: var(--sw-focus-ring-width) solid var(--sw-color-accent);
|
|
35
|
+
outline-offset: var(--sw-focus-ring-offset);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.sw-field-prefix,
|
|
39
|
+
.sw-field-suffix {
|
|
40
|
+
color: var(--sw-color-muted);
|
|
41
|
+
flex: none;
|
|
42
|
+
user-select: none;
|
|
43
|
+
white-space: nowrap;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.sw-field-xs .sw-field-adorned {
|
|
47
|
+
font-size: ${caption.fontSize}px;
|
|
48
|
+
letter-spacing: ${caption.letterSpacing}px;
|
|
49
|
+
line-height: ${caption.lineHeight}px;
|
|
50
|
+
min-height: var(--sw-control-xs-min-height);
|
|
51
|
+
padding-inline: var(--sw-control-xs-padding-inline);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.sw-field-invalid .sw-field-adorned { border-color: var(--sw-color-danger); }`;
|
|
55
|
+
}
|
|
3
56
|
export function cssFieldClasses() {
|
|
4
57
|
return `.sw-field-required { color: var(--sw-color-danger); }
|
|
5
58
|
|
|
@@ -17,8 +70,12 @@ export function cssFieldClasses() {
|
|
|
17
70
|
border-color: var(--sw-color-danger);
|
|
18
71
|
}
|
|
19
72
|
|
|
73
|
+
${adornmentRules()}
|
|
74
|
+
|
|
20
75
|
@media (forced-colors: active) {
|
|
21
|
-
[data-theme] .sw-field-invalid :is(input, select, textarea)
|
|
76
|
+
[data-theme] .sw-field-invalid :is(input, select, textarea),
|
|
77
|
+
.sw-field-invalid .sw-field-adorned { border-color: Mark; }
|
|
78
|
+
.sw-field-prefix, .sw-field-suffix { color: CanvasText; }
|
|
22
79
|
.sw-field-error, .sw-field-required { color: Mark; }
|
|
23
80
|
}`;
|
|
24
81
|
}
|
|
@@ -29,5 +86,8 @@ export function fieldClassCatalog() {
|
|
|
29
86
|
'sw-field-description',
|
|
30
87
|
'sw-field-error',
|
|
31
88
|
'sw-field-invalid',
|
|
89
|
+
'sw-field-adorned',
|
|
90
|
+
'sw-field-prefix',
|
|
91
|
+
'sw-field-suffix',
|
|
32
92
|
];
|
|
33
93
|
}
|
package/dist/css/css-select.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { typographyVariants } from '@scalewing/tokens';
|
|
2
|
+
import { zIndex } from './stacking.js';
|
|
2
3
|
const caption = typographyVariants.caption;
|
|
3
4
|
const label = typographyVariants.label;
|
|
4
5
|
const chevronImage = `background-image:
|
|
@@ -88,7 +89,7 @@ export function cssSelectClasses() {
|
|
|
88
89
|
padding: var(--sw-space-1);
|
|
89
90
|
position: absolute;
|
|
90
91
|
width: max-content;
|
|
91
|
-
|
|
92
|
+
${zIndex('popup')}
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
.sw-select-option {
|
package/dist/css/css-tooltip.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { typographyVariants } from '@scalewing/tokens';
|
|
2
|
+
import { zIndex } from './stacking.js';
|
|
2
3
|
const caption = typographyVariants.caption;
|
|
3
4
|
export function cssTooltipClasses() {
|
|
4
5
|
return `.sw-tooltip-anchor {
|
|
@@ -21,7 +22,7 @@ export function cssTooltipClasses() {
|
|
|
21
22
|
padding: var(--sw-space-2);
|
|
22
23
|
position: absolute;
|
|
23
24
|
width: max-content;
|
|
24
|
-
|
|
25
|
+
${zIndex('popup')}
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
.sw-tooltip[hidden] { display: none; }
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const stackingOrder: {
|
|
2
|
+
readonly stickyCell: 1;
|
|
3
|
+
readonly bottomChrome: 2;
|
|
4
|
+
readonly popupHost: 3;
|
|
5
|
+
readonly topChrome: 4;
|
|
6
|
+
readonly popup: 10;
|
|
7
|
+
};
|
|
8
|
+
export type StackingLayer = keyof typeof stackingOrder;
|
|
9
|
+
export declare function zIndex(layer: StackingLayer): string;
|
|
10
|
+
export declare function cssPopupHostRules(): string;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The one stacking order of the generated stylesheet. Every generated
|
|
3
|
+
* `z-index` reads a layer from here, lowest first:
|
|
4
|
+
*
|
|
5
|
+
* 1. `stickyCell`: a sticky table header cell or row label over the cells
|
|
6
|
+
* that scroll under it.
|
|
7
|
+
* 2. `bottomChrome`: the sticky ActionBar over the page flow it follows.
|
|
8
|
+
* 3. `popupHost`: a glass surface (glass Card, Accordion) while it holds an
|
|
9
|
+
* open popup. Backdrop blur makes that surface its own stacking context, so
|
|
10
|
+
* its popup can only paint as high as the surface does; lifting the surface
|
|
11
|
+
* over the ActionBar keeps an open list tappable where the bar would cover
|
|
12
|
+
* it, and over the next surface in the flow.
|
|
13
|
+
* 4. `topChrome`: the sticky AppHeader, over a lifted surface that scrolls up
|
|
14
|
+
* under it (the header is the page's way back, and a popup opens downward).
|
|
15
|
+
* 5. `popup`: a popup outside any lifted surface (Select list, ActionMenu
|
|
16
|
+
* list, Tooltip, DateField calendar) over everything in the page.
|
|
17
|
+
*
|
|
18
|
+
* Dialog and Toast sit on the browser's top layer, above all of these.
|
|
19
|
+
*/
|
|
20
|
+
export const stackingOrder = {
|
|
21
|
+
stickyCell: 1,
|
|
22
|
+
bottomChrome: 2,
|
|
23
|
+
popupHost: 3,
|
|
24
|
+
topChrome: 4,
|
|
25
|
+
popup: 10,
|
|
26
|
+
};
|
|
27
|
+
export function zIndex(layer) {
|
|
28
|
+
return `z-index: ${stackingOrder[layer]};`;
|
|
29
|
+
}
|
|
30
|
+
const openPopups = [
|
|
31
|
+
'.sw-select-list',
|
|
32
|
+
'.sw-action-menu-list:not([hidden])',
|
|
33
|
+
'.sw-tooltip:not([hidden])',
|
|
34
|
+
// Rendered only while open; on the top layer where the popover API exists.
|
|
35
|
+
'.sw-date-field-calendar',
|
|
36
|
+
].join(', ');
|
|
37
|
+
const popupHosts = ['.sw-card-glass', '.sw-accordion'];
|
|
38
|
+
export function cssPopupHostRules() {
|
|
39
|
+
const selectors = popupHosts
|
|
40
|
+
.map((host) => `${host}:has(${openPopups})`)
|
|
41
|
+
.join(',\n');
|
|
42
|
+
return `/* Backdrop blur makes a glass surface its own stacking context, so it lifts while it holds an open popup (see stacking.ts). */
|
|
43
|
+
${selectors} {
|
|
44
|
+
position: relative;
|
|
45
|
+
${zIndex('popupHost')}
|
|
46
|
+
}`;
|
|
47
|
+
}
|
package/dist/css/stylesheet.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { cardVariants, darkTheme, lightTheme, typographyVariants, } from '@scalewing/tokens';
|
|
2
|
+
import { actionBarClassCatalog } from './css-action-bar.js';
|
|
2
3
|
import { actionMenuClassCatalog } from './css-action-menu.js';
|
|
3
4
|
import { accordionClassCatalog } from './css-accordion.js';
|
|
4
5
|
import { switchClassCatalog } from './css-switch.js';
|
|
@@ -17,6 +18,7 @@ import { gridClassCatalog } from './css-grid.js';
|
|
|
17
18
|
import { gridSpanClassCatalog } from './css-grid-span.js';
|
|
18
19
|
import { denominationGridClassCatalog } from './css-denomination-grid.js';
|
|
19
20
|
import { fieldClassCatalog } from './css-field.js';
|
|
21
|
+
import { boxBorderClassCatalog } from './css-box-border.js';
|
|
20
22
|
import { cssComponentClasses } from './css-components.js';
|
|
21
23
|
import { buttonClassCatalog } from './css-button.js';
|
|
22
24
|
import { chartClassCatalog } from './css-chart.js';
|
|
@@ -52,6 +54,7 @@ export function utilityClassCatalog() {
|
|
|
52
54
|
...accordionClassCatalog(),
|
|
53
55
|
...selectClassCatalog(),
|
|
54
56
|
...actionMenuClassCatalog(),
|
|
57
|
+
...actionBarClassCatalog(),
|
|
55
58
|
...switchClassCatalog(),
|
|
56
59
|
...dateFieldClassCatalog(),
|
|
57
60
|
...checkboxClassCatalog(),
|
|
@@ -70,6 +73,7 @@ export function utilityClassCatalog() {
|
|
|
70
73
|
...splitClassCatalog(),
|
|
71
74
|
...toastClassCatalog(),
|
|
72
75
|
...responsiveClassCatalog(),
|
|
76
|
+
...boxBorderClassCatalog(),
|
|
73
77
|
];
|
|
74
78
|
}
|
|
75
79
|
export { generatePaletteStylesheet, paletteStylesheetIds, } from './css-palettes.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type DateFieldLabels } from './date-field-labels.js';
|
|
2
|
+
/**
|
|
3
|
+
* The message a date entry reports through `setCustomValidity`, so a form
|
|
4
|
+
* will not submit while it shows something other than an allowed date, as
|
|
5
|
+
* a native date input's `badInput`, `rangeUnderflow` and `rangeOverflow`
|
|
6
|
+
* would block it. `parsed` is the date the text forms, '' when blank, or
|
|
7
|
+
* null when the text is not a date. Empty means valid; `required` covers a
|
|
8
|
+
* blank entry.
|
|
9
|
+
*/
|
|
10
|
+
export declare function dateEntryValidity(parsed: string | null, labels: Pick<DateFieldLabels, 'invalidEntry' | 'outOfRange'>, min?: string, max?: string): string;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { isOutsideDateRange } from './date-only.js';
|
|
2
|
+
/**
|
|
3
|
+
* The message a date entry reports through `setCustomValidity`, so a form
|
|
4
|
+
* will not submit while it shows something other than an allowed date, as
|
|
5
|
+
* a native date input's `badInput`, `rangeUnderflow` and `rangeOverflow`
|
|
6
|
+
* would block it. `parsed` is the date the text forms, '' when blank, or
|
|
7
|
+
* null when the text is not a date. Empty means valid; `required` covers a
|
|
8
|
+
* blank entry.
|
|
9
|
+
*/
|
|
10
|
+
export function dateEntryValidity(parsed, labels, min, max) {
|
|
11
|
+
if (parsed === null)
|
|
12
|
+
return labels.invalidEntry;
|
|
13
|
+
if (isOutsideDateRange(parsed, min, max))
|
|
14
|
+
return labels.outOfRange;
|
|
15
|
+
return '';
|
|
16
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type DateEntryPart = 'day' | 'month' | 'year';
|
|
2
|
+
/** How a locale writes a numeric date: field order and the separator. */
|
|
3
|
+
export type DateEntryPattern = {
|
|
4
|
+
order: readonly [DateEntryPart, DateEntryPart, DateEntryPart];
|
|
5
|
+
separator: string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Reads the numeric field order and separator from `Intl` for `locale`, for
|
|
9
|
+
* example month/day/year with "/" for en-US and day.month.year for de.
|
|
10
|
+
*/
|
|
11
|
+
export declare function dateEntryPattern(locale: string): DateEntryPattern;
|
|
12
|
+
/** Zero-padded, Latin digits in the pattern's order; empty for no date. */
|
|
13
|
+
export declare function formatDateEntry(value: string, pattern: DateEntryPattern): string;
|
|
14
|
+
/** A hint such as "MM/DD/YYYY" from the consumer's per-part letters. */
|
|
15
|
+
export declare function dateEntryPlaceholder(pattern: DateEntryPattern, letters: Record<DateEntryPart, string>): string;
|
|
16
|
+
/**
|
|
17
|
+
* Whether typed text is finished, so a date it forms can be committed while
|
|
18
|
+
* the person is still typing: eight bare digits, or three fields whose last
|
|
19
|
+
* one is at full width (four year digits, two for a trailing day or month).
|
|
20
|
+
* A shorter last field may still grow, as "2024-03-1" on the way to
|
|
21
|
+
* "2024-03-10", so it waits for blur or Enter instead.
|
|
22
|
+
*/
|
|
23
|
+
export declare function isCompleteDateEntry(text: string, pattern: DateEntryPattern): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Parses typed text in the pattern's order. Day and month take one or two
|
|
26
|
+
* digits, the year exactly four, and any non-digit run separates fields.
|
|
27
|
+
* Eight bare digits split by field width in the same order (MMDDYYYY for
|
|
28
|
+
* en-US). A four-digit first field reads as ISO year-month-day in every
|
|
29
|
+
* locale, since no locale starts a day or month with four digits. Returns
|
|
30
|
+
* the YYYY-MM-DD value, '' for blank text, or null when it is not a date.
|
|
31
|
+
*/
|
|
32
|
+
export declare function parseDateEntry(text: string, pattern: DateEntryPattern): string | null;
|