@scattered-light/loomiere-base-ui 0.6.1 → 0.7.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.
Files changed (100) hide show
  1. package/README.md +135 -5
  2. package/dist/chunk-JUUPOOQQ.js +3723 -0
  3. package/dist/chunk-JUUPOOQQ.js.map +1 -0
  4. package/dist/chunk-M7KJASGK.js +802 -0
  5. package/dist/chunk-M7KJASGK.js.map +1 -0
  6. package/dist/chunk-Y2CPBMFJ.js +147 -0
  7. package/dist/chunk-Y2CPBMFJ.js.map +1 -0
  8. package/dist/custom/collection/index.d.ts +540 -0
  9. package/dist/custom/collection/index.js +1489 -0
  10. package/dist/custom/collection/index.js.map +1 -0
  11. package/dist/custom/index.d.ts +5 -0
  12. package/dist/custom/index.js +4 -0
  13. package/dist/custom/index.js.map +1 -0
  14. package/dist/design-system/components/Badge/README.md +35 -0
  15. package/dist/design-system/components/Badge/preview.html +19 -0
  16. package/dist/design-system/components/Collection/README.md +14 -0
  17. package/dist/design-system/components/CollectionPagination/README.md +15 -0
  18. package/dist/design-system/components/CollectionToolbar/README.md +29 -0
  19. package/dist/design-system/components/DataList/README.md +39 -0
  20. package/dist/design-system/components/DataList/preview.html +475 -0
  21. package/dist/design-system/components/DataTable/README.md +41 -0
  22. package/dist/design-system/components/DataTable/preview.html +475 -0
  23. package/dist/design-system/components/DatePicker/README.md +55 -0
  24. package/dist/design-system/components/DatePicker/preview.html +475 -0
  25. package/dist/design-system/components/EditableList/README.md +33 -0
  26. package/dist/design-system/components/EditableList/preview.html +475 -0
  27. package/dist/design-system/components/EmptyState/README.md +60 -0
  28. package/dist/design-system/components/EmptyState/preview.html +475 -0
  29. package/dist/design-system/components/ListDetail/README.md +43 -0
  30. package/dist/design-system/components/ListDetail/preview.html +475 -0
  31. package/dist/design-system/components/MoneyField/README.md +52 -0
  32. package/dist/design-system/components/MoneyField/preview.html +475 -0
  33. package/dist/design-system/components/Splitter/README.md +42 -0
  34. package/dist/design-system/components/Splitter/preview.html +475 -0
  35. package/dist/design-system/components/Table/README.md +2 -1
  36. package/dist/design-system/components/Table/preview.html +1 -1
  37. package/dist/design-system/components/bundle.js +7 -5
  38. package/dist/design-system/components/index.d.ts +3 -21
  39. package/dist/design-system/components/styles.css +2349 -186
  40. package/dist/index-ChJXlxzq.d.ts +809 -0
  41. package/dist/index.d.ts +3 -21
  42. package/dist/index.js +176 -891
  43. package/dist/index.js.map +1 -1
  44. package/dist/styles/components/Accordion.css +1 -1
  45. package/dist/styles/components/AlertDialog.css +1 -1
  46. package/dist/styles/components/Autocomplete.css +1 -1
  47. package/dist/styles/components/Avatar.css +1 -1
  48. package/dist/styles/components/Button.css +1 -1
  49. package/dist/styles/components/Checkbox.css +1 -1
  50. package/dist/styles/components/CheckboxGroup.css +1 -1
  51. package/dist/styles/components/Collapsible.css +1 -1
  52. package/dist/styles/components/Combobox.css +1 -1
  53. package/dist/styles/components/ContextMenu.css +1 -1
  54. package/dist/styles/components/Dialog.css +1 -1
  55. package/dist/styles/components/Drawer.css +1 -1
  56. package/dist/styles/components/Field.css +1 -1
  57. package/dist/styles/components/Fieldset.css +1 -1
  58. package/dist/styles/components/Form.css +1 -1
  59. package/dist/styles/components/Input.css +1 -1
  60. package/dist/styles/components/Menu.css +1 -1
  61. package/dist/styles/components/Menubar.css +1 -1
  62. package/dist/styles/components/Meter.css +1 -1
  63. package/dist/styles/components/NavigationMenu.css +1 -1
  64. package/dist/styles/components/NumberField.css +1 -1
  65. package/dist/styles/components/OTPField.css +1 -1
  66. package/dist/styles/components/Popover.css +1 -1
  67. package/dist/styles/components/PreviewCard.css +1 -1
  68. package/dist/styles/components/Progress.css +1 -1
  69. package/dist/styles/components/Radio.css +1 -1
  70. package/dist/styles/components/ScrollArea.css +1 -1
  71. package/dist/styles/components/Select.css +1 -1
  72. package/dist/styles/components/Separator.css +1 -1
  73. package/dist/styles/components/Slider.css +1 -1
  74. package/dist/styles/components/Switch.css +1 -1
  75. package/dist/styles/components/Tabs.css +1 -1
  76. package/dist/styles/components/Toast.css +1 -1
  77. package/dist/styles/components/Toggle.css +1 -1
  78. package/dist/styles/components/ToggleGroup.css +1 -1
  79. package/dist/styles/components/Toolbar.css +1 -1
  80. package/dist/styles/components/Tooltip.css +1 -1
  81. package/dist/styles/custom/Badge.css +104 -0
  82. package/dist/styles/custom/Collection.css +15 -0
  83. package/dist/styles/custom/CollectionPagination.css +24 -0
  84. package/dist/styles/custom/CollectionToolbar.css +140 -0
  85. package/dist/styles/custom/DataList.css +123 -0
  86. package/dist/styles/custom/DataTable.css +120 -0
  87. package/dist/styles/custom/DatePicker.css +572 -0
  88. package/dist/styles/custom/EditableList.css +98 -0
  89. package/dist/styles/custom/EmptyState.css +255 -0
  90. package/dist/styles/custom/ListDetail.css +126 -0
  91. package/dist/styles/custom/MoneyField.css +344 -0
  92. package/dist/styles/custom/Splitter.css +207 -0
  93. package/dist/styles/{components → custom}/Table.css +31 -4
  94. package/dist/styles/index.css +12 -2
  95. package/dist/styles/reset/accessibility.css +1 -1
  96. package/dist/styles/reset/reset-accessibility.css +1 -1
  97. package/dist/styles/reset/reset-tailwind.css +1 -1
  98. package/dist/styles/reset/reset.css +1 -1
  99. package/dist/styles/tailwind.css +12 -2
  100. package/package.json +35 -7
@@ -0,0 +1,344 @@
1
+ /* @scattered-light/loomiere-base-ui 0.7.1 · 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.1 · 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.6.1 · styles for @base-ui/react 1.9.0 */
1
+ /* @scattered-light/loomiere-base-ui 0.7.1 · 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" (or
7
- * data-selected) for selection; cells take data-align="end" for numbers.
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
+ }
@@ -1,4 +1,4 @@
1
- /* @scattered-light/loomiere-base-ui 0.6.1 · styles for @base-ui/react 1.9.0 */
1
+ /* @scattered-light/loomiere-base-ui 0.7.1 · 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.6.1 · styles for @base-ui/react 1.9.0 */
1
+ /* @scattered-light/loomiere-base-ui 0.7.1 · 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.6.1 · styles for @base-ui/react 1.9.0 */
1
+ /* @scattered-light/loomiere-base-ui 0.7.1 · 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 */
@@ -1,4 +1,4 @@
1
- /* @scattered-light/loomiere-base-ui 0.6.1 · styles for @base-ui/react 1.9.0 */
1
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
2
2
  /* CSS Reset - Mojave Theme */
3
3
 
4
4
  /* ============================================
@@ -1,4 +1,4 @@
1
- /* @scattered-light/loomiere-base-ui 0.6.1 · styles for @base-ui/react 1.9.0 */
1
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
2
2
  /* CSS Reset - Mojave Theme */
3
3
 
4
4
  /* ============================================
@@ -1,4 +1,4 @@
1
- /* @scattered-light/loomiere-base-ui 0.6.1 · styles for @base-ui/react 1.9.0 */
1
+ /* @scattered-light/loomiere-base-ui 0.7.1 · 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);