@stealthscale/component-tables 0.1.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/LICENSE +21 -0
- package/README.md +520 -0
- package/dist/cyclonedx/bom.json +1 -0
- package/dist/index.d.ts +867 -0
- package/dist/index.js +6001 -0
- package/dist/recipe-DKCE3olL.js +488 -0
- package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
- package/dist/theme.d.ts +11 -0
- package/dist/theme.js +16 -0
- package/package.json +91 -0
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
import { CONTROL_INSET_END, CONTROL_INSET_START, defineSlotRecipe, dense } from "@stealthscale/theme/authoring";
|
|
2
|
+
//#region src/data-table/properties.ts
|
|
3
|
+
/**
|
|
4
|
+
* Names the custom properties the collections table's rows and cells state, which the data table's
|
|
5
|
+
* recipes read and set.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Custom property of a row's fill, which the collections table's rows state and paint.
|
|
9
|
+
*/
|
|
10
|
+
const ROW_FILL = "--table-row-fill";
|
|
11
|
+
/**
|
|
12
|
+
* Custom property of the ink the collections table's rows rule their cells in.
|
|
13
|
+
*/
|
|
14
|
+
const RULE_INK = "--table-rule";
|
|
15
|
+
/**
|
|
16
|
+
* Custom property of the width of the rule under the collections table's rows.
|
|
17
|
+
*/
|
|
18
|
+
const RULE_WIDTH = "--table-rule-width";
|
|
19
|
+
/**
|
|
20
|
+
* Custom property of a cell's inline inset at the table's size, which the collections table's
|
|
21
|
+
* cells state and an editor's control starts its text at.
|
|
22
|
+
*/
|
|
23
|
+
const CELL_INSET = "--table-cell-inset";
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/data-table/gridded.ts
|
|
26
|
+
/**
|
|
27
|
+
* Styles a grid's cells and the editor over a cell: the selected fill, the line along the
|
|
28
|
+
* selection's outer edges, the focus ring, the unsaved mark, the editor's control and the reason a
|
|
29
|
+
* value was refused.
|
|
30
|
+
*
|
|
31
|
+
* @remarks
|
|
32
|
+
* In a grid a selected cell fills with the palette's subtle role over its row, a line in the
|
|
33
|
+
* palette's solid runs along the selection's outer edges, and the cell with the tab stop rings
|
|
34
|
+
* its edge inside while it has keyboard focus. An open editor covers its cell. The cell's content
|
|
35
|
+
* remains under it, hidden, so the cell keeps its size. The editor's control fills the cell with
|
|
36
|
+
* square corners and starts its text at the cell's inline inset less its edge, where the cell's
|
|
37
|
+
* text starts, and ends it there in a column of figures. The reason a value was refused is placed
|
|
38
|
+
* under the cell in the error inks, over the rows below, or above the cell in a body's last row,
|
|
39
|
+
* so the scroller never clips it. It is as wide as its words up to `sizes.xs`, from the cell's
|
|
40
|
+
* end in a column of figures. A cell with an unsaved change marks its inline start with a bar in
|
|
41
|
+
* the warning palette's solid, `CanvasText` under forced colours.
|
|
42
|
+
*/
|
|
43
|
+
/**
|
|
44
|
+
* Styles a cell of a grid: the selected fill, the line along the selection's outer edges, the
|
|
45
|
+
* unsaved mark, and the focus ring inside the cell with the tab stop.
|
|
46
|
+
*
|
|
47
|
+
* @remarks
|
|
48
|
+
* A selected cell paints the fill it states over its row, as a pinned cell paints its row's fill
|
|
49
|
+
* over the panel. The line is a box over the cell, as wide as the indicator on each side
|
|
50
|
+
* `data-edges` lists, in the palette's solid, which is at least 3:1 against the panel. Each side
|
|
51
|
+
* reads its own custom property, so no rule depends on the order of another. Under forced colours
|
|
52
|
+
* a selected cell fills with `Highlight` over `Canvas`, and its text, its rule, its line and its
|
|
53
|
+
* focus ring take `HighlightText`. A cell whose editor is open shows no line and takes no forced
|
|
54
|
+
* fill. Its editor covers the cell with a field in the forced colours of every field.
|
|
55
|
+
*/
|
|
56
|
+
const GRIDDED = {
|
|
57
|
+
"&:is([data-edges], [data-editing], [data-unsaved]):not([data-pinned])": { position: "relative" },
|
|
58
|
+
"&[aria-selected=true]": {
|
|
59
|
+
backgroundImage: `linear-gradient(var(${ROW_FILL}), var(${ROW_FILL}))`,
|
|
60
|
+
[ROW_FILL]: "colors.colorPalette.subtle"
|
|
61
|
+
},
|
|
62
|
+
"&[aria-selected=true]:not([data-editing])": { _highContrast: {
|
|
63
|
+
"& *": { color: "HighlightText" },
|
|
64
|
+
backgroundColor: "Canvas",
|
|
65
|
+
color: "HighlightText",
|
|
66
|
+
focusRingColor: "HighlightText",
|
|
67
|
+
forcedColorAdjust: "none",
|
|
68
|
+
[ROW_FILL]: "Highlight",
|
|
69
|
+
[RULE_INK]: "HighlightText"
|
|
70
|
+
} },
|
|
71
|
+
"&[data-edges]": { _after: {
|
|
72
|
+
_highContrast: { borderColor: "HighlightText" },
|
|
73
|
+
borderBlockEndWidth: "var(--edge-block-end, 0)",
|
|
74
|
+
borderBlockStartWidth: "var(--edge-block-start, 0)",
|
|
75
|
+
borderColor: "colorPalette.solid",
|
|
76
|
+
borderInlineEndWidth: "var(--edge-inline-end, 0)",
|
|
77
|
+
borderInlineStartWidth: "var(--edge-inline-start, 0)",
|
|
78
|
+
borderStyle: "solid",
|
|
79
|
+
content: "\"\"",
|
|
80
|
+
inset: "0",
|
|
81
|
+
pointerEvents: "none",
|
|
82
|
+
position: "absolute"
|
|
83
|
+
} },
|
|
84
|
+
"&[data-edges~=block-end]": { "--edge-block-end": "borderWidths.indicator" },
|
|
85
|
+
"&[data-edges~=block-start]": { "--edge-block-start": "borderWidths.indicator" },
|
|
86
|
+
"&[data-edges~=inline-end]": { "--edge-inline-end": "borderWidths.indicator" },
|
|
87
|
+
"&[data-edges~=inline-start]": { "--edge-inline-start": "borderWidths.indicator" },
|
|
88
|
+
"&[data-editing]": { _after: { display: "none" } },
|
|
89
|
+
"&[data-unsaved]": { _before: {
|
|
90
|
+
_highContrast: {
|
|
91
|
+
background: "CanvasText",
|
|
92
|
+
forcedColorAdjust: "none"
|
|
93
|
+
},
|
|
94
|
+
background: "warning.solid",
|
|
95
|
+
content: "\"\"",
|
|
96
|
+
inlineSize: "{borderWidths.indicator}",
|
|
97
|
+
insetBlock: "0",
|
|
98
|
+
insetInlineStart: "0",
|
|
99
|
+
pointerEvents: "none",
|
|
100
|
+
position: "absolute"
|
|
101
|
+
} },
|
|
102
|
+
"&[tabindex]": {
|
|
103
|
+
_focusVisible: { outlineOffset: "calc({borderWidths.ring} * -1)" },
|
|
104
|
+
focusRingColor: "colorPalette.focusRing",
|
|
105
|
+
focusVisibleRing: "inside"
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Styles the editor over a cell: a flex box over the cell's padding box, whose control fills it
|
|
110
|
+
* with square corners and starts its text where the cell's text starts.
|
|
111
|
+
*/
|
|
112
|
+
const EDITOR = {
|
|
113
|
+
"[data-numeric] > &": { "& input": { textAlign: "end" } },
|
|
114
|
+
"& > :first-child": {
|
|
115
|
+
borderRadius: "none",
|
|
116
|
+
[CONTROL_INSET_END]: `calc(var(${CELL_INSET}) - {borderWidths.control})`,
|
|
117
|
+
[CONTROL_INSET_START]: `calc(var(${CELL_INSET}) - {borderWidths.control})`,
|
|
118
|
+
flex: "1",
|
|
119
|
+
maxBlockSize: "full",
|
|
120
|
+
minBlockSize: "full",
|
|
121
|
+
minInlineSize: "0"
|
|
122
|
+
},
|
|
123
|
+
display: "flex",
|
|
124
|
+
inset: "0",
|
|
125
|
+
position: "absolute"
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Styles the reason a value was refused: a box in the error inks under the cell, above it in a
|
|
129
|
+
* body's last row, as wide as its words up to `sizes.xs`.
|
|
130
|
+
*/
|
|
131
|
+
const EDITOR_ERROR = {
|
|
132
|
+
"[data-numeric] > * > &": {
|
|
133
|
+
insetInlineEnd: "0",
|
|
134
|
+
insetInlineStart: "auto"
|
|
135
|
+
},
|
|
136
|
+
background: "bg.panel",
|
|
137
|
+
borderColor: "border.error",
|
|
138
|
+
borderRadius: "l2",
|
|
139
|
+
borderStyle: "solid",
|
|
140
|
+
borderWidth: "hairline",
|
|
141
|
+
color: "fg.error",
|
|
142
|
+
inlineSize: "max-content",
|
|
143
|
+
insetBlockStart: "100%",
|
|
144
|
+
insetInlineStart: "0",
|
|
145
|
+
marginBlockStart: dense("{spacing.gap.xs}"),
|
|
146
|
+
maxInlineSize: "xs",
|
|
147
|
+
paddingBlock: dense("{spacing.gap.xs}"),
|
|
148
|
+
paddingInline: dense("{spacing.inset.xs}"),
|
|
149
|
+
position: "absolute",
|
|
150
|
+
textStyle: "body.sm",
|
|
151
|
+
"tr:last-child > * > * > &": {
|
|
152
|
+
insetBlockEnd: "100%",
|
|
153
|
+
insetBlockStart: "auto",
|
|
154
|
+
marginBlockEnd: dense("{spacing.gap.xs}"),
|
|
155
|
+
marginBlockStart: "0"
|
|
156
|
+
},
|
|
157
|
+
zIndex: "3"
|
|
158
|
+
};
|
|
159
|
+
//#endregion
|
|
160
|
+
//#region src/data-table/recipe.ts
|
|
161
|
+
/**
|
|
162
|
+
* Recipe for the parts a data table adds around the collections table: the column that stacks the
|
|
163
|
+
* table and its controls, the row of a header's name and its column actions, the indicators in a
|
|
164
|
+
* header and a row, the resize separator, the cells of a pinned column, the widths of a sized
|
|
165
|
+
* table, and words that render only for assistive technology.
|
|
166
|
+
*
|
|
167
|
+
* @remarks
|
|
168
|
+
* The table's own look (its surface, rules, stripes and sizes) is the collections table's recipe,
|
|
169
|
+
* which `DataTable.Table` passes its axes to. The sort indicator is the caller's glyph, pointing
|
|
170
|
+
* up. It turns half a circle for a descending sort. On a sortable column that is not sorted it is
|
|
171
|
+
* transparent until the pointer is over the sort button or the button has keyboard focus. The
|
|
172
|
+
* expand indicator is the caller's glyph, pointing to the inline end, and turns a quarter while
|
|
173
|
+
* the row's detail is open. A pinned column's cells stick at `--pin-offset` from their region's
|
|
174
|
+
* edge on the panel under their row's fill, and the column at a region's edge rules its side next
|
|
175
|
+
* to the scrolling columns. A sized table is as wide as `--table-size`, each column as wide as
|
|
176
|
+
* its `--column-size`, and its scroller as wide as the table and never wider than its room. A
|
|
177
|
+
* header with column actions lays its name and the actions out in an inline row, which the header
|
|
178
|
+
* aligns as it aligns its name, so the actions follow the name, or precede it in a column of
|
|
179
|
+
* figures, where the header renders them first. The actions take a negative block margin of half
|
|
180
|
+
* the difference between an `xs` button and a line, so a header with actions is as tall as one
|
|
181
|
+
* without. A range filter lays its two fields out side by side, and a value filter writes each
|
|
182
|
+
* value's count in the muted ink with tabular figures. The column manager stacks its list over
|
|
183
|
+
* its reset button, which keeps its own width. The page size select follows its label in a row,
|
|
184
|
+
* the label in the muted ink at the small body size. A body row that ends a region of rows
|
|
185
|
+
* another region follows, such as the last row pinned to the top, rules its end at the indicator
|
|
186
|
+
* width. A cell whose rows span ends on the body's last row takes no rule before a footer, as the
|
|
187
|
+
* last row's cells do. The search field is at most `sizes.xs` wide. A resize separator is centred
|
|
188
|
+
* on its column's end, and the last column's is inside the table's end, so the table overflows
|
|
189
|
+
* nothing. Its line is transparent at rest and takes the palette's solid under the pointer, with
|
|
190
|
+
* keyboard focus and while it resizes, `Highlight` under forced colours. In a windowed table a
|
|
191
|
+
* group of pinned rows sticks on the panel over the rows that scroll: the top group under the
|
|
192
|
+
* header at `--table-head-size`, the bottom group at the viewport's end. A spacer row is as tall
|
|
193
|
+
* as `--spacer-size`, and its cell has no padding. A row with a tab stop, in a table with levels,
|
|
194
|
+
* rings its edge inside while it has keyboard focus. A cell that leads with a row's toggle lays
|
|
195
|
+
* the toggle and its content out in a row, indented `spacing.6` for each of `--row-depth` levels.
|
|
196
|
+
* A button in a body cell, a row's toggle, a detail button or a pin toggle, is in a box as wide
|
|
197
|
+
* as an `xs` button with the same negative block margin, so a row with a button is as tall as one
|
|
198
|
+
* without. A checkbox of the select column is in a box one line tall that centres it, so a row or
|
|
199
|
+
* a header with a checkbox is as tall as one without. A `Code` chip in a cell aligns to the
|
|
200
|
+
* bottom of the cell's text, so a small chip keeps its row's height. A grid's cells, the editor
|
|
201
|
+
* over a cell and the reason a value was refused take `GRIDDED`, `EDITOR` and `EDITOR_ERROR`, and
|
|
202
|
+
* an open editor's cell content is hidden under it.
|
|
203
|
+
*/
|
|
204
|
+
/**
|
|
205
|
+
* Styles an indicator that turns: a box around the caller's glyph that turns at the press pace,
|
|
206
|
+
* at once under reduced motion.
|
|
207
|
+
*/
|
|
208
|
+
const TURNING = {
|
|
209
|
+
_motionReduce: { transitionDuration: "0s" },
|
|
210
|
+
alignItems: "center",
|
|
211
|
+
display: "inline-flex",
|
|
212
|
+
flexShrink: "0",
|
|
213
|
+
transitionDuration: "press",
|
|
214
|
+
transitionProperty: "opacity, rotate",
|
|
215
|
+
transitionTimingFunction: "press"
|
|
216
|
+
};
|
|
217
|
+
/**
|
|
218
|
+
* Styles the cells of a pinned column: sticky at the offset, the panel under the row's fill, and
|
|
219
|
+
* a rule in the row's ink at the side of the region's edge.
|
|
220
|
+
*
|
|
221
|
+
* @remarks
|
|
222
|
+
* The row's fill is its stripe, its hover fill or its selected fill, so a pinned cell matches
|
|
223
|
+
* its row and hides the figures scrolled under it. Under forced colours a selected row's fill is
|
|
224
|
+
* `Highlight` and its ink `HighlightText`. A pinned cell paints `Canvas` under it, the row's own
|
|
225
|
+
* composite, because Chromium's `Highlight` is 80% opaque.
|
|
226
|
+
*/
|
|
227
|
+
const PINNED = {
|
|
228
|
+
"&[data-pinned]": {
|
|
229
|
+
backgroundColor: "bg.panel",
|
|
230
|
+
backgroundImage: `linear-gradient(var(${ROW_FILL}), var(${ROW_FILL}))`,
|
|
231
|
+
position: "sticky",
|
|
232
|
+
"tr[aria-selected=true] > &": { _highContrast: { backgroundColor: "Canvas" } },
|
|
233
|
+
zIndex: "1"
|
|
234
|
+
},
|
|
235
|
+
"&[data-pinned=end]": { insetInlineEnd: "var(--pin-offset)" },
|
|
236
|
+
"&[data-pinned=end][data-pinned-edge]": {
|
|
237
|
+
borderInlineStartColor: `var(${RULE_INK}, {colors.border})`,
|
|
238
|
+
borderInlineStartWidth: "indicator"
|
|
239
|
+
},
|
|
240
|
+
"&[data-pinned=start]": { insetInlineStart: "var(--pin-offset)" },
|
|
241
|
+
"&[data-pinned=start][data-pinned-edge]": {
|
|
242
|
+
borderInlineEndColor: `var(${RULE_INK}, {colors.border})`,
|
|
243
|
+
borderInlineEndWidth: "indicator"
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
/**
|
|
247
|
+
* Styles the cells of a column that fits its content: as narrow as the content while the table
|
|
248
|
+
* lays out its columns by their content, where a column declaration sizes a sized table's.
|
|
249
|
+
*/
|
|
250
|
+
const FIT = { "&[data-fit]": { inlineSize: "0" } };
|
|
251
|
+
/**
|
|
252
|
+
* Styles a cell whose rows span ends on the body's last row: before a footer it takes no rule, as
|
|
253
|
+
* the collections table's last row does, because the footer rules its own start.
|
|
254
|
+
*/
|
|
255
|
+
const SPAN_END = { "&[data-span-end]": { "tbody:has(+ tfoot) > tr > &": { [RULE_WIDTH]: "0" } } };
|
|
256
|
+
/**
|
|
257
|
+
* Aligns typography's `Code` chip in a cell to the bottom of the cell's text.
|
|
258
|
+
*
|
|
259
|
+
* @remarks
|
|
260
|
+
* A chip at `sm` then keeps its row at 41px, and its text's middle is within a third of a pixel
|
|
261
|
+
* of the next cell's text in Firefox and Chromium. A chip at `md` is as tall as the line and
|
|
262
|
+
* makes a 42px row.
|
|
263
|
+
*/
|
|
264
|
+
const CHIP = { "& .code": { verticalAlign: "text-bottom" } };
|
|
265
|
+
/**
|
|
266
|
+
* Height of the smallest button, which an action or a toggle in a line of text is.
|
|
267
|
+
*/
|
|
268
|
+
const BUTTON = dense("{sizes.control.xs}");
|
|
269
|
+
/**
|
|
270
|
+
* Styles the box around a button in a line of text with a negative block margin of half the
|
|
271
|
+
* difference between the button and the line, so the line keeps its height.
|
|
272
|
+
*/
|
|
273
|
+
const ONE_LINE = { marginBlock: `calc((1lh - ${BUTTON}) / 2)` };
|
|
274
|
+
/**
|
|
275
|
+
* Defines the data table recipe.
|
|
276
|
+
*/
|
|
277
|
+
const recipe = defineSlotRecipe({
|
|
278
|
+
base: {
|
|
279
|
+
actions: {
|
|
280
|
+
...ONE_LINE,
|
|
281
|
+
alignItems: "center",
|
|
282
|
+
display: "flex",
|
|
283
|
+
flexShrink: "0"
|
|
284
|
+
},
|
|
285
|
+
branch: {
|
|
286
|
+
alignItems: "center",
|
|
287
|
+
display: "flex",
|
|
288
|
+
gap: dense("{spacing.gap.xs}"),
|
|
289
|
+
paddingInlineStart: `calc(var(--row-depth, 0) * ${dense("{spacing.6}")})`
|
|
290
|
+
},
|
|
291
|
+
cell: {
|
|
292
|
+
...PINNED,
|
|
293
|
+
...FIT,
|
|
294
|
+
...SPAN_END,
|
|
295
|
+
...CHIP,
|
|
296
|
+
...GRIDDED
|
|
297
|
+
},
|
|
298
|
+
column: { inlineSize: "var(--column-size)" },
|
|
299
|
+
columnHeader: {
|
|
300
|
+
...PINNED,
|
|
301
|
+
...FIT,
|
|
302
|
+
"&[data-resizable]:not([data-pinned])": { position: "relative" }
|
|
303
|
+
},
|
|
304
|
+
count: {
|
|
305
|
+
color: "fg.muted",
|
|
306
|
+
fontVariantNumeric: "tabular-nums"
|
|
307
|
+
},
|
|
308
|
+
covered: { visibility: "hidden" },
|
|
309
|
+
editor: EDITOR,
|
|
310
|
+
editorError: EDITOR_ERROR,
|
|
311
|
+
expandIndicator: {
|
|
312
|
+
...TURNING,
|
|
313
|
+
_open: { rotate: "90deg" },
|
|
314
|
+
_rtl: {
|
|
315
|
+
_open: { rotate: "90deg" },
|
|
316
|
+
rotate: "180deg"
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
frame: { "&[data-sized]": {
|
|
320
|
+
inlineSize: "fit-content",
|
|
321
|
+
maxInlineSize: "full"
|
|
322
|
+
} },
|
|
323
|
+
heading: {
|
|
324
|
+
alignItems: "center",
|
|
325
|
+
display: "inline-flex",
|
|
326
|
+
gap: dense("{spacing.gap.xs}"),
|
|
327
|
+
verticalAlign: "middle"
|
|
328
|
+
},
|
|
329
|
+
manager: {
|
|
330
|
+
display: "flex",
|
|
331
|
+
flexDirection: "column",
|
|
332
|
+
gap: dense("{spacing.gap.sm}")
|
|
333
|
+
},
|
|
334
|
+
pageSize: {
|
|
335
|
+
alignItems: "center",
|
|
336
|
+
display: "inline-flex",
|
|
337
|
+
gap: dense("{spacing.gap.sm}")
|
|
338
|
+
},
|
|
339
|
+
pageSizeLabel: {
|
|
340
|
+
color: "fg.muted",
|
|
341
|
+
textStyle: "body.sm",
|
|
342
|
+
whiteSpace: "nowrap"
|
|
343
|
+
},
|
|
344
|
+
panel: { inlineSize: "60" },
|
|
345
|
+
range: {
|
|
346
|
+
display: "grid",
|
|
347
|
+
gap: dense("{spacing.gap.sm}"),
|
|
348
|
+
gridTemplateColumns: "repeat(2, minmax(0, 1fr))"
|
|
349
|
+
},
|
|
350
|
+
region: {
|
|
351
|
+
"&[data-pinned=bottom]": { insetBlockEnd: "0" },
|
|
352
|
+
"&[data-pinned=top]": { insetBlockStart: "var(--table-head-size)" },
|
|
353
|
+
backgroundColor: "bg.panel",
|
|
354
|
+
position: "sticky",
|
|
355
|
+
zIndex: "2"
|
|
356
|
+
},
|
|
357
|
+
reset: { alignSelf: "flex-end" },
|
|
358
|
+
resizer: {
|
|
359
|
+
_after: {
|
|
360
|
+
background: "transparent",
|
|
361
|
+
content: "\"\"",
|
|
362
|
+
forcedColorAdjust: "none",
|
|
363
|
+
inlineSize: "{borderWidths.indicator}",
|
|
364
|
+
insetBlock: "0",
|
|
365
|
+
insetInlineStart: "50%",
|
|
366
|
+
marginInlineStart: "calc({borderWidths.indicator} / -2)",
|
|
367
|
+
position: "absolute"
|
|
368
|
+
},
|
|
369
|
+
"&:is(:hover, :focus-visible, [data-resizing])": { _after: {
|
|
370
|
+
_highContrast: { background: "Highlight" },
|
|
371
|
+
background: "colorPalette.solid"
|
|
372
|
+
} },
|
|
373
|
+
background: "transparent",
|
|
374
|
+
blockSize: "full",
|
|
375
|
+
borderStyle: "none",
|
|
376
|
+
cursor: "resizeColumn",
|
|
377
|
+
focusVisibleRing: "inside",
|
|
378
|
+
inlineSize: "3",
|
|
379
|
+
insetBlock: "0",
|
|
380
|
+
insetInlineEnd: "calc({sizes.3} / -2)",
|
|
381
|
+
margin: "0",
|
|
382
|
+
position: "absolute",
|
|
383
|
+
"th:last-child > &": {
|
|
384
|
+
_after: {
|
|
385
|
+
insetInlineStart: "calc(100% - {borderWidths.indicator})",
|
|
386
|
+
marginInlineStart: "0"
|
|
387
|
+
},
|
|
388
|
+
insetInlineEnd: "0"
|
|
389
|
+
},
|
|
390
|
+
touchAction: "none",
|
|
391
|
+
userSelect: "none",
|
|
392
|
+
zIndex: "1"
|
|
393
|
+
},
|
|
394
|
+
root: {
|
|
395
|
+
display: "flex",
|
|
396
|
+
flexDirection: "column",
|
|
397
|
+
gap: dense("{spacing.gap.md}"),
|
|
398
|
+
minInlineSize: "0"
|
|
399
|
+
},
|
|
400
|
+
row: {
|
|
401
|
+
"&[data-region-end]": { [RULE_WIDTH]: "borderWidths.indicator" },
|
|
402
|
+
"&[tabindex]": {
|
|
403
|
+
_focusVisible: { outlineOffset: "calc({borderWidths.ring} * -1)" },
|
|
404
|
+
focusRingColor: "colorPalette.focusRing",
|
|
405
|
+
focusVisibleRing: "inside"
|
|
406
|
+
}
|
|
407
|
+
},
|
|
408
|
+
rowHeader: {
|
|
409
|
+
...PINNED,
|
|
410
|
+
...FIT,
|
|
411
|
+
...SPAN_END,
|
|
412
|
+
...CHIP,
|
|
413
|
+
...GRIDDED
|
|
414
|
+
},
|
|
415
|
+
search: { maxInlineSize: "xs" },
|
|
416
|
+
selectBox: {
|
|
417
|
+
alignItems: "center",
|
|
418
|
+
blockSize: "1lh",
|
|
419
|
+
display: "flex"
|
|
420
|
+
},
|
|
421
|
+
sortIndicator: {
|
|
422
|
+
...TURNING,
|
|
423
|
+
"&[data-direction=descending]": { rotate: "180deg" },
|
|
424
|
+
"&[data-direction=none]": {
|
|
425
|
+
"*:is(:hover, :focus-visible) > &": { opacity: "muted" },
|
|
426
|
+
opacity: "0"
|
|
427
|
+
}
|
|
428
|
+
},
|
|
429
|
+
spacer: {
|
|
430
|
+
"& > td": { padding: "0" },
|
|
431
|
+
blockSize: "var(--spacer-size)"
|
|
432
|
+
},
|
|
433
|
+
table: { "&[data-sized]": { inlineSize: "var(--table-size)" } },
|
|
434
|
+
toggle: {
|
|
435
|
+
...ONE_LINE,
|
|
436
|
+
display: "flex",
|
|
437
|
+
flexShrink: "0",
|
|
438
|
+
inlineSize: BUTTON,
|
|
439
|
+
justifyContent: "center"
|
|
440
|
+
},
|
|
441
|
+
value: { alignSelf: "stretch" },
|
|
442
|
+
valueLabel: {
|
|
443
|
+
display: "flex",
|
|
444
|
+
flex: "1",
|
|
445
|
+
gap: dense("{spacing.gap.md}"),
|
|
446
|
+
justifyContent: "space-between"
|
|
447
|
+
},
|
|
448
|
+
visuallyHidden: { srOnly: true }
|
|
449
|
+
},
|
|
450
|
+
className: "data-table",
|
|
451
|
+
jsx: [/^DataTable\.\w+$/u],
|
|
452
|
+
slots: [
|
|
453
|
+
"root",
|
|
454
|
+
"frame",
|
|
455
|
+
"table",
|
|
456
|
+
"column",
|
|
457
|
+
"columnHeader",
|
|
458
|
+
"heading",
|
|
459
|
+
"actions",
|
|
460
|
+
"region",
|
|
461
|
+
"row",
|
|
462
|
+
"spacer",
|
|
463
|
+
"rowHeader",
|
|
464
|
+
"cell",
|
|
465
|
+
"covered",
|
|
466
|
+
"editor",
|
|
467
|
+
"editorError",
|
|
468
|
+
"branch",
|
|
469
|
+
"toggle",
|
|
470
|
+
"selectBox",
|
|
471
|
+
"search",
|
|
472
|
+
"panel",
|
|
473
|
+
"range",
|
|
474
|
+
"value",
|
|
475
|
+
"valueLabel",
|
|
476
|
+
"count",
|
|
477
|
+
"manager",
|
|
478
|
+
"reset",
|
|
479
|
+
"pageSize",
|
|
480
|
+
"pageSizeLabel",
|
|
481
|
+
"sortIndicator",
|
|
482
|
+
"expandIndicator",
|
|
483
|
+
"resizer",
|
|
484
|
+
"visuallyHidden"
|
|
485
|
+
]
|
|
486
|
+
});
|
|
487
|
+
//#endregion
|
|
488
|
+
export { recipe as t };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __exportAll = (all, no_symbols) => {
|
|
4
|
+
let target = {};
|
|
5
|
+
for (var name in all) __defProp(target, name, {
|
|
6
|
+
get: all[name],
|
|
7
|
+
enumerable: true
|
|
8
|
+
});
|
|
9
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
10
|
+
return target;
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
export { __exportAll as t };
|
package/dist/theme.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/theme.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Registers every recipe in the package in the preset an application's style compiler installs.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* The list is written by hand. `theme.spec.ts` fails when a recipe file is missing from it, so no
|
|
7
|
+
* generator writes it.
|
|
8
|
+
*/
|
|
9
|
+
declare const _default: import("@stealthscale/theme/authoring").Preset;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { _default as default };
|
package/dist/theme.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { t as recipe } from "./recipe-DKCE3olL.js";
|
|
2
|
+
import { definePreset } from "@stealthscale/theme/authoring";
|
|
3
|
+
//#region src/theme.ts
|
|
4
|
+
/**
|
|
5
|
+
* Registers every recipe in the package in the preset an application's style compiler installs.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* The list is written by hand. `theme.spec.ts` fails when a recipe file is missing from it, so no
|
|
9
|
+
* generator writes it.
|
|
10
|
+
*/
|
|
11
|
+
var theme_default = definePreset({
|
|
12
|
+
name: "@stealthscale/component-tables",
|
|
13
|
+
theme: { extend: { slotRecipes: { dataTable: recipe } } }
|
|
14
|
+
});
|
|
15
|
+
//#endregion
|
|
16
|
+
export { theme_default as default };
|
package/package.json
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stealthscale/component-tables",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Renders records in data tables over TanStack Table: sorting, filtering, selection, pages, column sizes and pins, rows with levels, windowed rows, pivots and editable grids.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"components",
|
|
7
|
+
"data-table",
|
|
8
|
+
"grid",
|
|
9
|
+
"react",
|
|
10
|
+
"table"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://github.com/stealth-scale/scale/tree/main/components/tables#readme",
|
|
13
|
+
"bugs": "https://github.com/stealth-scale/scale/issues",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/stealth-scale/scale.git",
|
|
18
|
+
"directory": "components/tables"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"LICENSE",
|
|
23
|
+
"README.md"
|
|
24
|
+
],
|
|
25
|
+
"type": "module",
|
|
26
|
+
"sideEffects": false,
|
|
27
|
+
"imports": {
|
|
28
|
+
"#*": "./src/*"
|
|
29
|
+
},
|
|
30
|
+
"exports": {
|
|
31
|
+
".": "./dist/index.js",
|
|
32
|
+
"./theme": "./dist/theme.js",
|
|
33
|
+
"./package.json": "./package.json"
|
|
34
|
+
},
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@stealthscale/component-actions": "^0.1.0",
|
|
40
|
+
"@stealthscale/component-collections": "^0.0.1",
|
|
41
|
+
"@stealthscale/component-data": "^0.1.0",
|
|
42
|
+
"@stealthscale/component-disclosure": "^0.1.0",
|
|
43
|
+
"@stealthscale/component-feedback": "^0.1.0",
|
|
44
|
+
"@stealthscale/component-forms": "^0.1.0",
|
|
45
|
+
"@stealthscale/component-navigation": "^0.1.0",
|
|
46
|
+
"@tanstack/react-table": "^9.2",
|
|
47
|
+
"@tanstack/react-virtual": "^3.14"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@arethetypeswrong/core": "^0.18",
|
|
51
|
+
"@stealthscale/component-a11y": "^0.1.0",
|
|
52
|
+
"@stealthscale/component-primitives": "^0.1.0",
|
|
53
|
+
"@stealthscale/hooks": "^0.1.0",
|
|
54
|
+
"@stealthscale/provider-locale": "^0.1.0",
|
|
55
|
+
"@stealthscale/theme": "^0.3.0",
|
|
56
|
+
"@stealthscale/vite-config": "^0.6.0",
|
|
57
|
+
"@stealthscale/vite-config-i18n": "^0.1.0",
|
|
58
|
+
"@stealthscale/vite-config-react": "^0.8.0",
|
|
59
|
+
"@stealthscale/vite-config-specimen": "^0.1.0",
|
|
60
|
+
"@stealthscale/vite-config-theme": "^0.1.0",
|
|
61
|
+
"@stealthscale/vite-config-typescript": "^0.3.0",
|
|
62
|
+
"@testing-library/react": "^16.3",
|
|
63
|
+
"@types/react": "^19.3",
|
|
64
|
+
"@types/react-dom": "^19.3",
|
|
65
|
+
"happy-dom": "^20.14",
|
|
66
|
+
"lucide-react": "^1.48",
|
|
67
|
+
"oxc-transform-react": "^0.151",
|
|
68
|
+
"publint": "^0.3",
|
|
69
|
+
"react": "^19.3",
|
|
70
|
+
"react-dom": "^19.3",
|
|
71
|
+
"typescript": "^7.0",
|
|
72
|
+
"vitest": "5.0.1"
|
|
73
|
+
},
|
|
74
|
+
"peerDependencies": {
|
|
75
|
+
"@stealthscale/component-a11y": "^0.1.0",
|
|
76
|
+
"@stealthscale/component-primitives": "^0.1.0",
|
|
77
|
+
"@stealthscale/hooks": "^0.1.0",
|
|
78
|
+
"@stealthscale/provider-locale": "^0.1.0",
|
|
79
|
+
"@stealthscale/theme": "^0.3.0",
|
|
80
|
+
"react": "^19.3",
|
|
81
|
+
"react-dom": "^19.3"
|
|
82
|
+
},
|
|
83
|
+
"engines": {
|
|
84
|
+
"node": ">=26.0.0"
|
|
85
|
+
},
|
|
86
|
+
"scripts": {
|
|
87
|
+
"build": "vp pack",
|
|
88
|
+
"check": "vp check",
|
|
89
|
+
"test": "vp test"
|
|
90
|
+
}
|
|
91
|
+
}
|