@scattered-light/loomiere-base-ui 0.6.0 → 0.7.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/README.md +135 -5
- package/dist/chunk-JUUPOOQQ.js +3723 -0
- package/dist/chunk-JUUPOOQQ.js.map +1 -0
- package/dist/chunk-M7KJASGK.js +802 -0
- package/dist/chunk-M7KJASGK.js.map +1 -0
- package/dist/chunk-Y2CPBMFJ.js +147 -0
- package/dist/chunk-Y2CPBMFJ.js.map +1 -0
- package/dist/custom/collection/index.d.ts +534 -0
- package/dist/custom/collection/index.js +1471 -0
- package/dist/custom/collection/index.js.map +1 -0
- package/dist/custom/index.d.ts +5 -0
- package/dist/custom/index.js +4 -0
- package/dist/custom/index.js.map +1 -0
- package/dist/design-system/components/Badge/README.md +35 -0
- package/dist/design-system/components/Badge/preview.html +19 -0
- package/dist/design-system/components/Collection/README.md +14 -0
- package/dist/design-system/components/CollectionPagination/README.md +15 -0
- package/dist/design-system/components/CollectionToolbar/README.md +24 -0
- package/dist/design-system/components/DataList/README.md +39 -0
- package/dist/design-system/components/DataList/preview.html +475 -0
- package/dist/design-system/components/DataTable/README.md +41 -0
- package/dist/design-system/components/DataTable/preview.html +475 -0
- package/dist/design-system/components/DatePicker/README.md +55 -0
- package/dist/design-system/components/DatePicker/preview.html +475 -0
- package/dist/design-system/components/EditableList/README.md +33 -0
- package/dist/design-system/components/EditableList/preview.html +475 -0
- package/dist/design-system/components/EmptyState/README.md +60 -0
- package/dist/design-system/components/EmptyState/preview.html +475 -0
- package/dist/design-system/components/ListDetail/README.md +43 -0
- package/dist/design-system/components/ListDetail/preview.html +475 -0
- package/dist/design-system/components/MoneyField/README.md +52 -0
- package/dist/design-system/components/MoneyField/preview.html +475 -0
- package/dist/design-system/components/Splitter/README.md +42 -0
- package/dist/design-system/components/Splitter/preview.html +475 -0
- package/dist/design-system/components/Table/README.md +2 -1
- package/dist/design-system/components/Table/preview.html +1 -1
- package/dist/design-system/components/bundle.js +7 -5
- package/dist/design-system/components/index.d.ts +3 -21
- package/dist/design-system/components/styles.css +2266 -186
- package/dist/index-ChJXlxzq.d.ts +809 -0
- package/dist/index.d.ts +3 -21
- package/dist/index.js +176 -891
- package/dist/index.js.map +1 -1
- package/dist/styles/components/Accordion.css +1 -1
- package/dist/styles/components/AlertDialog.css +1 -1
- package/dist/styles/components/Autocomplete.css +1 -1
- package/dist/styles/components/Avatar.css +1 -1
- package/dist/styles/components/Button.css +1 -1
- package/dist/styles/components/Checkbox.css +1 -1
- package/dist/styles/components/CheckboxGroup.css +1 -1
- package/dist/styles/components/Collapsible.css +1 -1
- package/dist/styles/components/Combobox.css +1 -1
- package/dist/styles/components/ContextMenu.css +1 -1
- package/dist/styles/components/Dialog.css +1 -1
- package/dist/styles/components/Drawer.css +1 -1
- package/dist/styles/components/Field.css +1 -1
- package/dist/styles/components/Fieldset.css +1 -1
- package/dist/styles/components/Form.css +1 -1
- package/dist/styles/components/Input.css +1 -1
- package/dist/styles/components/Menu.css +1 -1
- package/dist/styles/components/Menubar.css +1 -1
- package/dist/styles/components/Meter.css +1 -1
- package/dist/styles/components/NavigationMenu.css +1 -1
- package/dist/styles/components/NumberField.css +1 -1
- package/dist/styles/components/OTPField.css +1 -1
- package/dist/styles/components/Popover.css +1 -1
- package/dist/styles/components/PreviewCard.css +1 -1
- package/dist/styles/components/Progress.css +1 -1
- package/dist/styles/components/Radio.css +1 -1
- package/dist/styles/components/ScrollArea.css +1 -1
- package/dist/styles/components/Select.css +1 -1
- package/dist/styles/components/Separator.css +1 -1
- package/dist/styles/components/Slider.css +1 -1
- package/dist/styles/components/Switch.css +1 -1
- package/dist/styles/components/Tabs.css +1 -1
- package/dist/styles/components/Toast.css +1 -1
- package/dist/styles/components/Toggle.css +1 -1
- package/dist/styles/components/ToggleGroup.css +1 -1
- package/dist/styles/components/Toolbar.css +1 -1
- package/dist/styles/components/Tooltip.css +1 -1
- package/dist/styles/custom/Badge.css +104 -0
- package/dist/styles/custom/Collection.css +15 -0
- package/dist/styles/custom/CollectionPagination.css +24 -0
- package/dist/styles/custom/CollectionToolbar.css +57 -0
- package/dist/styles/custom/DataList.css +123 -0
- package/dist/styles/custom/DataTable.css +120 -0
- package/dist/styles/custom/DatePicker.css +572 -0
- package/dist/styles/custom/EditableList.css +98 -0
- package/dist/styles/custom/EmptyState.css +255 -0
- package/dist/styles/custom/ListDetail.css +126 -0
- package/dist/styles/custom/MoneyField.css +344 -0
- package/dist/styles/custom/Splitter.css +207 -0
- package/dist/styles/{components → custom}/Table.css +31 -4
- package/dist/styles/index.css +12 -2
- package/dist/styles/reset/accessibility.css +1 -1
- package/dist/styles/reset/reset-accessibility.css +1 -1
- package/dist/styles/reset/reset-tailwind.css +1 -1
- package/dist/styles/reset/reset.css +1 -1
- package/dist/styles/tailwind.css +12 -2
- package/package.json +36 -8
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
/* @scattered-light/loomiere-base-ui 0.7.0 · styles for @base-ui/react 1.9.0 */
|
|
2
|
+
/* Money field
|
|
3
|
+
*
|
|
4
|
+
* An amount of money, built on Number field. The value is an integer in minor units
|
|
5
|
+
* (cents, yen, fils) so 0.1 + 0.2 and 1.005 * 100 cannot drift, and so the number matches
|
|
6
|
+
* what a payment API sends. Number field counts in major units; Money field converts at
|
|
7
|
+
* the edge and rounds half away from zero. The default maximum is 10^15 - 1 minor
|
|
8
|
+
* units, so the major amount stays inside 15 significant digits. Changing currency
|
|
9
|
+
* keeps the number the person typed and re-rounds it to the new currency's digits
|
|
10
|
+
* (12.50 USD becomes 13 JPY). There is no exchange rate. When the app
|
|
11
|
+
* controls both the value and the currency, it decides whether to apply that rounding:
|
|
12
|
+
* onValueChange still reports the re-rounded minor units.
|
|
13
|
+
*
|
|
14
|
+
* Keyboard is Number field's: ArrowUp and ArrowDown step one major unit, Shift steps 100
|
|
15
|
+
* major units, Alt steps one minor unit, Home and End jump to the minimum and maximum.
|
|
16
|
+
* The currency symbol is not in the text, so the caret does not fight it. A fixed symbol
|
|
17
|
+
* is aria-hidden; the currency name is in the input's accessible description. A picker
|
|
18
|
+
* is its own tab stop, before the input when the locale puts the symbol first and after
|
|
19
|
+
* it when the locale puts the symbol last.
|
|
20
|
+
*
|
|
21
|
+
* State on the root: data-currency (USD), data-affix (start or end), data-affix-kind
|
|
22
|
+
* (symbol or picker), data-negative (below zero; set data-color on the field to color
|
|
23
|
+
* it, never on by default), data-align (start or end),
|
|
24
|
+
* data-size (xs, sm, md, lg), data-readonly, plus data-invalid, data-disabled,
|
|
25
|
+
* data-focused and data-scrubbing.
|
|
26
|
+
*
|
|
27
|
+
* The affix (symbol or picker) is drawn inside the field so it can later be lifted into
|
|
28
|
+
* a general Input affix for units, https://, or @. Position comes from the locale, with
|
|
29
|
+
* logical properties so RTL mirrors it. The group, not the input, carries the field
|
|
30
|
+
* border, hover, focus halo, invalid edge and disabled fill, so the affix reads as part
|
|
31
|
+
* of the field.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/* ============================================
|
|
35
|
+
FIELD
|
|
36
|
+
============================================ */
|
|
37
|
+
|
|
38
|
+
.MoneyField {
|
|
39
|
+
display: inline-flex;
|
|
40
|
+
flex-direction: column;
|
|
41
|
+
gap: var(--sl-field-gap);
|
|
42
|
+
width: 100%;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.MoneyFieldGroup {
|
|
46
|
+
box-sizing: border-box;
|
|
47
|
+
color: var(--sl-field-color);
|
|
48
|
+
background: var(--sl-field-background);
|
|
49
|
+
border: var(--sl-field-border-width) solid var(--sl-field-border-color);
|
|
50
|
+
border-radius: var(--sl-field-radius);
|
|
51
|
+
transition: var(--sl-field-transition);
|
|
52
|
+
outline: none;
|
|
53
|
+
font-family: var(--sl-font-body-base-font-family);
|
|
54
|
+
font-size: var(--sl-font-body-base-font-size);
|
|
55
|
+
font-weight: var(--sl-font-body-base-font-weight);
|
|
56
|
+
line-height: var(--sl-font-body-base-line-height);
|
|
57
|
+
letter-spacing: var(--sl-font-body-base-letter-spacing);
|
|
58
|
+
display: flex;
|
|
59
|
+
align-items: stretch;
|
|
60
|
+
width: 100%;
|
|
61
|
+
height: var(--sl-control-height-md);
|
|
62
|
+
padding: 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.MoneyField[data-size='xs'] .MoneyFieldGroup {
|
|
66
|
+
font-family: var(--sl-font-body-minimize-font-family);
|
|
67
|
+
font-size: var(--sl-font-body-minimize-font-size);
|
|
68
|
+
font-weight: var(--sl-font-body-minimize-font-weight);
|
|
69
|
+
line-height: var(--sl-font-body-minimize-line-height);
|
|
70
|
+
letter-spacing: var(--sl-font-body-minimize-letter-spacing);
|
|
71
|
+
height: var(--sl-control-height-xs);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.MoneyField[data-size='sm'] .MoneyFieldGroup {
|
|
75
|
+
font-family: var(--sl-font-body-condense-font-family);
|
|
76
|
+
font-size: var(--sl-font-body-condense-font-size);
|
|
77
|
+
font-weight: var(--sl-font-body-condense-font-weight);
|
|
78
|
+
line-height: var(--sl-font-body-condense-line-height);
|
|
79
|
+
letter-spacing: var(--sl-font-body-condense-letter-spacing);
|
|
80
|
+
height: var(--sl-control-height-sm);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.MoneyField[data-size='lg'] .MoneyFieldGroup {
|
|
84
|
+
font-family: var(--sl-font-body-magnify-font-family);
|
|
85
|
+
font-size: var(--sl-font-body-magnify-font-size);
|
|
86
|
+
font-weight: var(--sl-font-body-magnify-font-weight);
|
|
87
|
+
line-height: var(--sl-font-body-magnify-line-height);
|
|
88
|
+
letter-spacing: var(--sl-font-body-magnify-letter-spacing);
|
|
89
|
+
height: var(--sl-control-height-lg);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.MoneyFieldGroup .MoneyFieldInput,
|
|
93
|
+
.MoneyFieldAffix,
|
|
94
|
+
.MoneyFieldGroup .MoneyFieldCurrencyTrigger {
|
|
95
|
+
font: inherit;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.MoneyFieldGroup .MoneyFieldInput {
|
|
99
|
+
flex: 1;
|
|
100
|
+
min-inline-size: 0;
|
|
101
|
+
height: auto;
|
|
102
|
+
border: 0;
|
|
103
|
+
border-radius: 0;
|
|
104
|
+
background: transparent;
|
|
105
|
+
box-shadow: none;
|
|
106
|
+
outline: none;
|
|
107
|
+
font-variant-numeric: tabular-nums;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.MoneyFieldGroup .MoneyFieldInput:hover,
|
|
111
|
+
.MoneyFieldGroup .MoneyFieldInput:focus,
|
|
112
|
+
.MoneyField[data-invalid] .MoneyFieldInput,
|
|
113
|
+
.MoneyField[data-invalid] .MoneyFieldInput:focus,
|
|
114
|
+
.MoneyField[data-disabled] .MoneyFieldInput {
|
|
115
|
+
border-color: transparent;
|
|
116
|
+
background: transparent;
|
|
117
|
+
box-shadow: none;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/* A symbol brings its own padding. A picker has a divider, so the amount keeps its inset. */
|
|
121
|
+
.MoneyField[data-affix-kind='symbol'][data-affix='start'] .MoneyFieldInput {
|
|
122
|
+
padding-inline-start: 0;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.MoneyField[data-affix-kind='symbol'][data-affix='end']:not([data-steppers]) .MoneyFieldInput {
|
|
126
|
+
padding-inline-end: 0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/* Number field always pads for its steppers. Those buttons are absent unless asked for. */
|
|
130
|
+
.MoneyField:not([data-steppers]) .MoneyFieldInput {
|
|
131
|
+
padding-inline-end: var(--sl-control-padding-inline);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.MoneyField[data-size='xs']:not([data-steppers]) .MoneyFieldInput {
|
|
135
|
+
padding-inline-end: var(--sl-control-padding-inline-xs);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.MoneyField[data-size='sm']:not([data-steppers]) .MoneyFieldInput {
|
|
139
|
+
padding-inline-end: var(--sl-control-padding-inline-sm);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.MoneyField[data-size='lg']:not([data-steppers]) .MoneyFieldInput {
|
|
143
|
+
padding-inline-end: var(--sl-control-padding-inline-lg);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.MoneyField[data-align='end'] .MoneyFieldInput {
|
|
147
|
+
text-align: end;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.MoneyField[data-align='start'] .MoneyFieldInput {
|
|
151
|
+
text-align: start;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.MoneyFieldGroup:hover:not(:focus-within) {
|
|
155
|
+
border-color: var(--sl-field-border-color-hover);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.MoneyFieldGroup:focus-within,
|
|
159
|
+
.MoneyField[data-focused] .MoneyFieldGroup {
|
|
160
|
+
border-color: var(--sl-field-border-color-focus);
|
|
161
|
+
box-shadow: var(--sl-field-shadow-focus);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.MoneyField[data-invalid] .MoneyFieldGroup {
|
|
165
|
+
border-color: var(--sl-field-border-color-error);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.MoneyField[data-invalid] .MoneyFieldGroup:focus-within,
|
|
169
|
+
.MoneyField[data-invalid][data-focused] .MoneyFieldGroup {
|
|
170
|
+
border-color: var(--sl-field-border-color-error);
|
|
171
|
+
box-shadow: var(--sl-field-shadow-focus-error);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.MoneyField[data-disabled] .MoneyFieldGroup {
|
|
175
|
+
background: var(--sl-field-background-disabled);
|
|
176
|
+
cursor: not-allowed;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.MoneyField[data-readonly] .MoneyFieldInput {
|
|
180
|
+
cursor: default;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/* The palette is the one on the field. An ancestor data-color does not recolor a balance. */
|
|
184
|
+
.MoneyField[data-negative][data-color] .MoneyFieldInput {
|
|
185
|
+
color: var(--sl-scope-fg);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.MoneyField[data-scrubbing] .MoneyFieldInput {
|
|
189
|
+
cursor: ns-resize;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/* The sign toggle is for coarse pointers: an iOS decimal keypad has no minus key. */
|
|
193
|
+
.MoneyFieldSign {
|
|
194
|
+
display: none;
|
|
195
|
+
align-self: center;
|
|
196
|
+
flex: none;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@media (pointer: coarse) {
|
|
200
|
+
.MoneyFieldSign {
|
|
201
|
+
display: inline-flex;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* ============================================
|
|
206
|
+
AFFIX
|
|
207
|
+
============================================ */
|
|
208
|
+
|
|
209
|
+
.MoneyFieldAffix {
|
|
210
|
+
display: inline-flex;
|
|
211
|
+
align-items: center;
|
|
212
|
+
flex: none;
|
|
213
|
+
padding-inline: var(--sl-control-padding-inline);
|
|
214
|
+
color: var(--sl-field-affix-color);
|
|
215
|
+
user-select: none;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.MoneyField[data-size='xs'] .MoneyFieldAffix {
|
|
219
|
+
padding-inline: var(--sl-control-padding-inline-xs);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.MoneyField[data-size='sm'] .MoneyFieldAffix {
|
|
223
|
+
padding-inline: var(--sl-control-padding-inline-sm);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.MoneyField[data-size='lg'] .MoneyFieldAffix {
|
|
227
|
+
padding-inline: var(--sl-control-padding-inline-lg);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/* ============================================
|
|
231
|
+
CURRENCY SELECT
|
|
232
|
+
============================================ */
|
|
233
|
+
|
|
234
|
+
.MoneyFieldCurrency {
|
|
235
|
+
display: flex;
|
|
236
|
+
align-self: stretch;
|
|
237
|
+
flex: none;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.MoneyFieldCurrencyTrigger {
|
|
241
|
+
display: inline-flex;
|
|
242
|
+
align-items: center;
|
|
243
|
+
align-self: stretch;
|
|
244
|
+
flex: none;
|
|
245
|
+
gap: var(--sl-space-1);
|
|
246
|
+
height: auto;
|
|
247
|
+
min-height: 0;
|
|
248
|
+
padding-inline: var(--sl-control-padding-inline);
|
|
249
|
+
border: 0;
|
|
250
|
+
border-radius: 0;
|
|
251
|
+
background: transparent;
|
|
252
|
+
box-shadow: none;
|
|
253
|
+
color: var(--sl-field-affix-color);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.MoneyField[data-size='xs'] .MoneyFieldCurrencyTrigger {
|
|
257
|
+
padding-inline: var(--sl-control-padding-inline-xs);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.MoneyField[data-size='sm'] .MoneyFieldCurrencyTrigger {
|
|
261
|
+
padding-inline: var(--sl-control-padding-inline-sm);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.MoneyField[data-size='lg'] .MoneyFieldCurrencyTrigger {
|
|
265
|
+
padding-inline: var(--sl-control-padding-inline-lg);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.MoneyField[data-affix='start'] .MoneyFieldCurrency {
|
|
269
|
+
border-inline-end: var(--sl-field-border-width) solid var(--sl-field-border-color);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.MoneyField[data-affix='end'] .MoneyFieldCurrency {
|
|
273
|
+
border-inline-start: var(--sl-field-border-width) solid var(--sl-field-border-color);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.MoneyFieldCurrencyTrigger:hover,
|
|
277
|
+
.MoneyFieldCurrencyTrigger:focus,
|
|
278
|
+
.MoneyFieldCurrencyTrigger[data-popup-open],
|
|
279
|
+
.MoneyFieldCurrencyTrigger[aria-expanded='true'] {
|
|
280
|
+
border-color: transparent;
|
|
281
|
+
background: transparent;
|
|
282
|
+
box-shadow: none;
|
|
283
|
+
color: var(--sl-text-primary);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/* The group halo says the field is focused. This says the picker, not the amount, has the caret. */
|
|
287
|
+
.MoneyFieldCurrencyTrigger:focus-visible {
|
|
288
|
+
outline: var(--sl-focus-outline);
|
|
289
|
+
outline-offset: var(--sl-focus-outline-offset-inset);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/* The picker is its own field, so it does not take the amount's label. */
|
|
293
|
+
.MoneyFieldCurrencyField,
|
|
294
|
+
.MoneyFieldGroup .ComboboxRoot {
|
|
295
|
+
display: contents;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.MoneyFieldCurrencyIcon {
|
|
299
|
+
width: var(--sl-icon-size-base);
|
|
300
|
+
height: var(--sl-icon-size-base);
|
|
301
|
+
font-size: var(--sl-icon-size-base);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.MoneyField[data-size='xs'] .MoneyFieldCurrencyIcon {
|
|
305
|
+
width: var(--sl-icon-size-minimize);
|
|
306
|
+
height: var(--sl-icon-size-minimize);
|
|
307
|
+
font-size: var(--sl-icon-size-minimize);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.MoneyField[data-size='sm'] .MoneyFieldCurrencyIcon {
|
|
311
|
+
width: var(--sl-icon-size-condense);
|
|
312
|
+
height: var(--sl-icon-size-condense);
|
|
313
|
+
font-size: var(--sl-icon-size-condense);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.MoneyField[data-size='lg'] .MoneyFieldCurrencyIcon {
|
|
317
|
+
width: var(--sl-icon-size-magnify);
|
|
318
|
+
height: var(--sl-icon-size-magnify);
|
|
319
|
+
font-size: var(--sl-icon-size-magnify);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.MoneyFieldCurrencyPopup {
|
|
323
|
+
min-inline-size: var(--sl-money-field-picker-min-inline-size);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.MoneyFieldCurrencyItem {
|
|
327
|
+
display: flex;
|
|
328
|
+
align-items: center;
|
|
329
|
+
justify-content: space-between;
|
|
330
|
+
gap: var(--sl-space-4);
|
|
331
|
+
width: 100%;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
.MoneyFieldCurrencySymbol {
|
|
335
|
+
color: var(--sl-text-secondary);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.MoneyFieldCurrencyPopup .ComboboxInput {
|
|
339
|
+
font-family: var(--sl-font-body-base-font-family);
|
|
340
|
+
font-size: var(--sl-font-body-base-font-size);
|
|
341
|
+
font-weight: var(--sl-font-body-base-font-weight);
|
|
342
|
+
line-height: var(--sl-font-body-base-line-height);
|
|
343
|
+
letter-spacing: var(--sl-font-body-base-letter-spacing);
|
|
344
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/* @scattered-light/loomiere-base-ui 0.7.0 · styles for @base-ui/react 1.9.0 */
|
|
2
|
+
/* Splitter
|
|
3
|
+
*
|
|
4
|
+
* Two or more panels and a handle between them. Not a Base UI part. It follows the
|
|
5
|
+
* window splitter pattern: the handle is a separator you drag or move with the arrow
|
|
6
|
+
* keys. Each panel's size is --sl-splitter-panel-size, so a drag can update the line
|
|
7
|
+
* without rendering the tree again. The parent gives the root its height.
|
|
8
|
+
*
|
|
9
|
+
* One panel has no size and fills what the others leave (the last panel, when every
|
|
10
|
+
* panel has a size). Px and percent mix, so a workstation can pin its sides in pixels
|
|
11
|
+
* while a list keeps a percent.
|
|
12
|
+
*
|
|
13
|
+
* Arrow keys move one key step, 5% of the splitter; Shift uses the larger step.
|
|
14
|
+
* Home and End jump to that panel's min and max. Enter collapses a collapsible panel
|
|
15
|
+
* and restores the size it had. Double-click resets to the default size. In RTL,
|
|
16
|
+
* Left and Right swap. A panel collapsed to nothing is hidden, so its contents leave
|
|
17
|
+
* the tab order.
|
|
18
|
+
*
|
|
19
|
+
* data-orientation is on the root, the panel and the handle. data-dragging is on the
|
|
20
|
+
* root and the handle while the pointer is down. data-collapsed is on a collapsed
|
|
21
|
+
* panel and on the handle that resizes it. data-disabled is on the handle. data-grip
|
|
22
|
+
* draws the grip. data-fill marks the panel that takes the leftover space.
|
|
23
|
+
*
|
|
24
|
+
* The line is one stroke. The part you grab sits on the next panel's inline-start,
|
|
25
|
+
* not centered, so it does not cover the previous panel's scrollbar. A fine pointer
|
|
26
|
+
* gets a11y.min-target (24px). A coarse pointer gets the 44px touch target. The
|
|
27
|
+
* focus ring is drawn on that grab area: a ring around the 1px line reads as a
|
|
28
|
+
* second hairline. Collapse animates with duration.normal. A drag does not animate.
|
|
29
|
+
* Reduced motion is the shared reset, which finishes every transition at once.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
.Splitter {
|
|
33
|
+
display: flex;
|
|
34
|
+
width: 100%;
|
|
35
|
+
height: 100%;
|
|
36
|
+
min-width: 0;
|
|
37
|
+
min-height: 0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.Splitter[data-orientation='horizontal'] {
|
|
41
|
+
flex-direction: row;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.Splitter[data-orientation='vertical'] {
|
|
45
|
+
flex-direction: column;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.Splitter[data-dragging] .SplitterPanel {
|
|
49
|
+
transition: none;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.SplitterPanel {
|
|
53
|
+
--sl-splitter-panel-size: auto;
|
|
54
|
+
position: relative;
|
|
55
|
+
box-sizing: border-box;
|
|
56
|
+
min-width: 0;
|
|
57
|
+
min-height: 0;
|
|
58
|
+
overflow: hidden;
|
|
59
|
+
flex: 0 0 var(--sl-splitter-panel-size);
|
|
60
|
+
transition:
|
|
61
|
+
flex-basis var(--sl-duration-normal) var(--sl-easing-default),
|
|
62
|
+
width var(--sl-duration-normal) var(--sl-easing-default),
|
|
63
|
+
height var(--sl-duration-normal) var(--sl-easing-default);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.SplitterPanel[data-orientation='horizontal'] {
|
|
67
|
+
width: var(--sl-splitter-panel-size);
|
|
68
|
+
height: auto;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.SplitterPanel[data-orientation='vertical'] {
|
|
72
|
+
height: var(--sl-splitter-panel-size);
|
|
73
|
+
width: auto;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.SplitterPanel[data-orientation='horizontal'][data-fill]:not([data-collapsed]) {
|
|
77
|
+
flex: 1 1 auto;
|
|
78
|
+
width: auto;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.SplitterPanel[data-orientation='vertical'][data-fill]:not([data-collapsed]) {
|
|
82
|
+
flex: 1 1 auto;
|
|
83
|
+
height: auto;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* A ScrollArea thumb still stacks above the grab area, for a bar that lives in the
|
|
87
|
+
next panel, under the part of the hit area that crosses the line. */
|
|
88
|
+
.SplitterPanel .ScrollAreaScrollbar {
|
|
89
|
+
z-index: 2;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.SplitterHandle {
|
|
93
|
+
position: relative;
|
|
94
|
+
flex: none;
|
|
95
|
+
box-sizing: border-box;
|
|
96
|
+
border: 0;
|
|
97
|
+
padding: 0;
|
|
98
|
+
background: transparent;
|
|
99
|
+
touch-action: none;
|
|
100
|
+
color: var(--sl-border-default);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.SplitterHandle[data-orientation='horizontal'] {
|
|
104
|
+
width: var(--sl-splitter-handle-size);
|
|
105
|
+
height: auto;
|
|
106
|
+
align-self: stretch;
|
|
107
|
+
cursor: col-resize;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.SplitterHandle[data-orientation='vertical'] {
|
|
111
|
+
height: var(--sl-splitter-handle-size);
|
|
112
|
+
width: auto;
|
|
113
|
+
align-self: stretch;
|
|
114
|
+
cursor: row-resize;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.SplitterHandle::before,
|
|
118
|
+
.SplitterHandle::after {
|
|
119
|
+
content: '';
|
|
120
|
+
position: absolute;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.SplitterHandle::before {
|
|
124
|
+
left: 50%;
|
|
125
|
+
top: 50%;
|
|
126
|
+
transform: translate(-50%, -50%);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.SplitterHandle[data-orientation='horizontal']::before {
|
|
130
|
+
width: var(--sl-splitter-handle-size);
|
|
131
|
+
height: 100%;
|
|
132
|
+
background: var(--sl-border-default);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.SplitterHandle[data-orientation='vertical']::before {
|
|
136
|
+
height: var(--sl-splitter-handle-size);
|
|
137
|
+
width: 100%;
|
|
138
|
+
background: var(--sl-border-default);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/* The grab area starts on the line and extends into the next panel. The previous
|
|
142
|
+
panel keeps its scrollbar, which sits on its inline-end, against this line. */
|
|
143
|
+
.SplitterHandle[data-orientation='horizontal']::after {
|
|
144
|
+
inset-inline-start: 0;
|
|
145
|
+
top: 0;
|
|
146
|
+
bottom: 0;
|
|
147
|
+
width: var(--sl-a11y-min-target);
|
|
148
|
+
z-index: 1;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.SplitterHandle[data-orientation='vertical']::after {
|
|
152
|
+
inset-block-start: 0;
|
|
153
|
+
left: 0;
|
|
154
|
+
right: 0;
|
|
155
|
+
height: var(--sl-a11y-min-target);
|
|
156
|
+
z-index: 1;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
@media (pointer: coarse) {
|
|
160
|
+
.SplitterHandle[data-orientation='horizontal']::after {
|
|
161
|
+
width: var(--sl-splitter-handle-hit-size);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.SplitterHandle[data-orientation='vertical']::after {
|
|
165
|
+
height: var(--sl-splitter-handle-hit-size);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.SplitterHandle:hover::before,
|
|
170
|
+
.SplitterHandle[data-dragging]::before,
|
|
171
|
+
.SplitterHandle[data-collapsed]::before {
|
|
172
|
+
background: var(--sl-border-strong);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* The dot edge (45% to 50%) is the shape of the grip, not a size token. */
|
|
176
|
+
/* The dots sit on the line, at the start of the grab area, not in its middle. */
|
|
177
|
+
.SplitterHandle[data-orientation='horizontal'][data-grip]::after {
|
|
178
|
+
background:
|
|
179
|
+
radial-gradient(circle, var(--sl-border-strong) 45%, transparent 50%) inline-start calc(50% - var(--sl-splitter-grip-size) * 2) / var(--sl-splitter-grip-size) var(--sl-splitter-grip-size) no-repeat,
|
|
180
|
+
radial-gradient(circle, var(--sl-border-strong) 45%, transparent 50%) inline-start center / var(--sl-splitter-grip-size) var(--sl-splitter-grip-size) no-repeat,
|
|
181
|
+
radial-gradient(circle, var(--sl-border-strong) 45%, transparent 50%) inline-start calc(50% + var(--sl-splitter-grip-size) * 2) / var(--sl-splitter-grip-size) var(--sl-splitter-grip-size) no-repeat;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.SplitterHandle[data-orientation='vertical'][data-grip]::after {
|
|
185
|
+
background:
|
|
186
|
+
radial-gradient(circle, var(--sl-border-strong) 45%, transparent 50%) calc(50% - var(--sl-splitter-grip-size) * 2) block-start / var(--sl-splitter-grip-size) var(--sl-splitter-grip-size) no-repeat,
|
|
187
|
+
radial-gradient(circle, var(--sl-border-strong) 45%, transparent 50%) center block-start / var(--sl-splitter-grip-size) var(--sl-splitter-grip-size) no-repeat,
|
|
188
|
+
radial-gradient(circle, var(--sl-border-strong) 45%, transparent 50%) calc(50% + var(--sl-splitter-grip-size) * 2) block-start / var(--sl-splitter-grip-size) var(--sl-splitter-grip-size) no-repeat;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.SplitterHandle:focus {
|
|
192
|
+
outline: none;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.SplitterHandle:focus-visible::after {
|
|
196
|
+
outline: var(--sl-focus-outline);
|
|
197
|
+
outline-offset: var(--sl-focus-outline-offset);
|
|
198
|
+
box-shadow: 0 0 0 var(--sl-focus-halo-spread) var(--sl-focus-halo-color);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.SplitterHandle[data-disabled] {
|
|
202
|
+
cursor: not-allowed;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.SplitterHandle[data-disabled]::before {
|
|
206
|
+
background: var(--sl-border-default);
|
|
207
|
+
}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
/* @scattered-light/loomiere-base-ui 0.
|
|
1
|
+
/* @scattered-light/loomiere-base-ui 0.7.0 · styles for @base-ui/react 1.9.0 */
|
|
2
2
|
/* Table - Mojave Theme
|
|
3
3
|
*
|
|
4
4
|
* Base UI has no table, so this styles the native <table class="Table"> elements with the
|
|
5
5
|
* table concept (tokens/semantic/table.json), the same tokens the AG Grid themes read: a small
|
|
6
|
-
* hand-built table and a full grid look alike. Rows answer to aria-selected="true"
|
|
7
|
-
*
|
|
6
|
+
* hand-built table and a full grid look alike. Rows answer to aria-selected="true",
|
|
7
|
+
* aria-current="true" (the row whose detail is open) or data-selected; cells take
|
|
8
|
+
* data-align="end" for numbers.
|
|
9
|
+
*
|
|
10
|
+
* An empty body keeps the header and the column widths: one cell spanning the columns,
|
|
11
|
+
* `<tr><td data-empty colSpan={n}><EmptyState size="compact" … /></td></tr>`. A cell with
|
|
12
|
+
* only text still uses this rule's padding. A cell whose child is an EmptyState lets the
|
|
13
|
+
* empty state pad itself. The empty row does not take the row hover.
|
|
8
14
|
*/
|
|
9
15
|
|
|
10
16
|
.Table {
|
|
@@ -111,6 +117,17 @@
|
|
|
111
117
|
color: var(--sl-item-color-selected);
|
|
112
118
|
}
|
|
113
119
|
|
|
120
|
+
/* The open row keeps a fill, and a bar on the inline start so it is not only a color. */
|
|
121
|
+
.Table tbody tr[aria-current='true'] > * {
|
|
122
|
+
background: var(--sl-table-row-current);
|
|
123
|
+
color: var(--sl-table-color);
|
|
124
|
+
box-shadow: inset var(--sl-stroke-strong) 0 0 0 var(--sl-border-accent);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
[dir='rtl'] .Table tbody tr[aria-current='true'] > * {
|
|
128
|
+
box-shadow: inset calc(var(--sl-stroke-strong) * -1) 0 0 0 var(--sl-border-accent);
|
|
129
|
+
}
|
|
130
|
+
|
|
114
131
|
/* Footer: totals on the tray band */
|
|
115
132
|
.Table tfoot td {
|
|
116
133
|
font-family: var(--sl-font-subtitle-condense-font-family);
|
|
@@ -130,7 +147,8 @@
|
|
|
130
147
|
z-index: var(--sl-z-index-docked);
|
|
131
148
|
}
|
|
132
149
|
|
|
133
|
-
/* Empty state: one cell spanning the columns
|
|
150
|
+
/* Empty state: one cell spanning the columns. Plain text keeps the old padding.
|
|
151
|
+
An EmptyState brings its own, and its title stays the normal text color on hover. */
|
|
134
152
|
.Table td[data-empty] {
|
|
135
153
|
height: auto;
|
|
136
154
|
padding-block: var(--sl-space-10);
|
|
@@ -138,7 +156,16 @@
|
|
|
138
156
|
text-align: center;
|
|
139
157
|
}
|
|
140
158
|
|
|
159
|
+
.Table td[data-empty]:has(> .EmptyState) {
|
|
160
|
+
padding: 0;
|
|
161
|
+
color: inherit;
|
|
162
|
+
}
|
|
163
|
+
|
|
141
164
|
.Table tbody tr:has(> td[data-empty]):hover > * {
|
|
142
165
|
background: transparent;
|
|
143
166
|
color: var(--sl-text-tertiary);
|
|
144
167
|
}
|
|
168
|
+
|
|
169
|
+
.Table tbody tr:has(> td[data-empty] > .EmptyState):hover > * {
|
|
170
|
+
color: inherit;
|
|
171
|
+
}
|
package/dist/styles/index.css
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* @scattered-light/loomiere-base-ui 0.
|
|
1
|
+
/* @scattered-light/loomiere-base-ui 0.7.0 · styles for @base-ui/react 1.9.0 */
|
|
2
2
|
/* Loomiere for Base UI: component styles. Brand-free: every value is a --sl- variable from a
|
|
3
3
|
Loomiere theme. Load the theme first:
|
|
4
4
|
@import '<your theme>/tokens.css';
|
|
@@ -44,10 +44,20 @@
|
|
|
44
44
|
@import './components/Separator.css';
|
|
45
45
|
@import './components/Slider.css';
|
|
46
46
|
@import './components/Switch.css';
|
|
47
|
-
@import './components/Table.css';
|
|
48
47
|
@import './components/Tabs.css';
|
|
49
48
|
@import './components/Toast.css';
|
|
50
49
|
@import './components/Toggle.css';
|
|
51
50
|
@import './components/ToggleGroup.css';
|
|
52
51
|
@import './components/Toolbar.css';
|
|
53
52
|
@import './components/Tooltip.css';
|
|
53
|
+
|
|
54
|
+
/* Custom components: not Base UI parts. Built from existing concepts and tokens. */
|
|
55
|
+
@import './custom/Badge.css';
|
|
56
|
+
@import './custom/DatePicker.css';
|
|
57
|
+
@import './custom/MoneyField.css';
|
|
58
|
+
@import './custom/ListDetail.css';
|
|
59
|
+
@import './custom/Splitter.css';
|
|
60
|
+
@import './custom/EmptyState.css';
|
|
61
|
+
@import './custom/Table.css';
|
|
62
|
+
@import './custom/Collection.css';
|
|
63
|
+
@import './custom/EditableList.css';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* @scattered-light/loomiere-base-ui 0.
|
|
1
|
+
/* @scattered-light/loomiere-base-ui 0.7.0 · styles for @base-ui/react 1.9.0 */
|
|
2
2
|
/* Focus, invalid, contrast — requires theme tokens (after theme-accessibility.css). */
|
|
3
3
|
|
|
4
4
|
:focus-visible {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* @scattered-light/loomiere-base-ui 0.
|
|
1
|
+
/* @scattered-light/loomiere-base-ui 0.7.0 · styles for @base-ui/react 1.9.0 */
|
|
2
2
|
/* Accessibility — base rules (no theme color dependencies). Theme-specific focus/invalid: accessibility-theme.css */
|
|
3
3
|
|
|
4
4
|
/* Remove default focus; keyboard focus styled in accessibility-theme.css */
|
package/dist/styles/tailwind.css
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* @scattered-light/loomiere-base-ui 0.
|
|
1
|
+
/* @scattered-light/loomiere-base-ui 0.7.0 · styles for @base-ui/react 1.9.0 */
|
|
2
2
|
/* Loomiere for Base UI: component styles for Tailwind CSS v4. Load Tailwind and the theme first:
|
|
3
3
|
@import 'tailwindcss';
|
|
4
4
|
@import '<your theme>/tokens.css';
|
|
@@ -47,10 +47,20 @@
|
|
|
47
47
|
@import './components/Separator.css' layer(components);
|
|
48
48
|
@import './components/Slider.css' layer(components);
|
|
49
49
|
@import './components/Switch.css' layer(components);
|
|
50
|
-
@import './components/Table.css' layer(components);
|
|
51
50
|
@import './components/Tabs.css' layer(components);
|
|
52
51
|
@import './components/Toast.css' layer(components);
|
|
53
52
|
@import './components/Toggle.css' layer(components);
|
|
54
53
|
@import './components/ToggleGroup.css' layer(components);
|
|
55
54
|
@import './components/Toolbar.css' layer(components);
|
|
56
55
|
@import './components/Tooltip.css' layer(components);
|
|
56
|
+
|
|
57
|
+
/* Custom components: not Base UI parts. Built from existing concepts and tokens. */
|
|
58
|
+
@import './custom/Badge.css' layer(components);
|
|
59
|
+
@import './custom/DatePicker.css' layer(components);
|
|
60
|
+
@import './custom/MoneyField.css' layer(components);
|
|
61
|
+
@import './custom/ListDetail.css' layer(components);
|
|
62
|
+
@import './custom/Splitter.css' layer(components);
|
|
63
|
+
@import './custom/EmptyState.css' layer(components);
|
|
64
|
+
@import './custom/Table.css' layer(components);
|
|
65
|
+
@import './custom/Collection.css' layer(components);
|
|
66
|
+
@import './custom/EditableList.css' layer(components);
|