@duro-app/ui 0.32.0 → 0.34.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/dist/components/Table/FromTanstack.d.ts +45 -0
- package/dist/components/Table/FromTanstack.d.ts.map +1 -0
- package/dist/components/Table/SortChip.d.ts +28 -0
- package/dist/components/Table/SortChip.d.ts.map +1 -0
- package/dist/components/Table/Table.d.ts +49 -7
- package/dist/components/Table/Table.d.ts.map +1 -1
- package/dist/components/Table/Table.stories.d.ts +3 -0
- package/dist/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/components/Table/styles.css.d.ts +62 -5
- package/dist/components/Table/styles.css.d.ts.map +1 -1
- package/dist/components/Table/tanstack-augmentation.d.ts +13 -0
- package/dist/components/Table/tanstack-augmentation.d.ts.map +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2442 -2194
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/Table/FromTanstack.tsx +159 -0
- package/src/components/Table/SortChip.tsx +52 -0
- package/src/components/Table/Table.stories.tsx +254 -0
- package/src/components/Table/Table.tsx +259 -50
- package/src/components/Table/styles.css.ts +214 -16
- package/src/components/Table/tanstack-augmentation.ts +28 -0
- package/src/index.ts +5 -0
|
@@ -3,8 +3,50 @@ import {colors} from '@duro-app/tokens/tokens/colors.css'
|
|
|
3
3
|
import {spacing, radii} from '@duro-app/tokens/tokens/spacing.css'
|
|
4
4
|
import {typography} from '@duro-app/tokens/tokens/typography.css'
|
|
5
5
|
|
|
6
|
+
// Container-query thresholds. Picked for typical 5-7 column admin tables —
|
|
7
|
+
// see Table.stories.tsx "Responsive" for the visual reasoning. Defined
|
|
8
|
+
// once here so it's clear they're a design-system constant, not a magic
|
|
9
|
+
// number sprinkled across files.
|
|
10
|
+
const COMPACT_BP = '720px'
|
|
11
|
+
const STACK_BP = '440px'
|
|
12
|
+
|
|
6
13
|
export const styles = css.create({
|
|
7
|
-
//
|
|
14
|
+
// Outer wrapper that hosts the @container query. Wraps SortChip + Root
|
|
15
|
+
// + Pagination so all three react to the same width. Root itself does
|
|
16
|
+
// NOT carry containerType — keeping a single query target per Table.
|
|
17
|
+
//
|
|
18
|
+
// @deprecated Use Table.Root's sortChip/pagination slot props instead.
|
|
19
|
+
// This style backs the deprecated <Table.Container> wrapper.
|
|
20
|
+
container: {
|
|
21
|
+
containerType: 'inline-size',
|
|
22
|
+
display: 'flex',
|
|
23
|
+
flexDirection: 'column',
|
|
24
|
+
gap: spacing.sm,
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
// The same containment chrome, but applied by Root when responsive=true.
|
|
28
|
+
// Mirrors `container` so consumers don't need to wrap manually.
|
|
29
|
+
rootContainer: {
|
|
30
|
+
containerType: 'inline-size',
|
|
31
|
+
display: 'flex',
|
|
32
|
+
flexDirection: 'column',
|
|
33
|
+
gap: spacing.sm,
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
// Applied when Row receives an `onClick` handler. Cursor signals clickability;
|
|
37
|
+
// the :focus-visible outline meets WCAG 2.4.7 for keyboard navigation.
|
|
38
|
+
clickableRow: {
|
|
39
|
+
cursor: 'pointer',
|
|
40
|
+
outlineWidth: {
|
|
41
|
+
default: 0,
|
|
42
|
+
':focus-visible': 2,
|
|
43
|
+
},
|
|
44
|
+
outlineStyle: 'solid',
|
|
45
|
+
outlineColor: colors.accent,
|
|
46
|
+
outlineOffset: -2,
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
// Root — the single grid container for the table itself
|
|
8
50
|
root: {
|
|
9
51
|
display: 'grid',
|
|
10
52
|
borderWidth: 1,
|
|
@@ -17,9 +59,40 @@ export const styles = css.create({
|
|
|
17
59
|
color: colors.text,
|
|
18
60
|
},
|
|
19
61
|
|
|
20
|
-
//
|
|
62
|
+
// Stack-mode override: the Root's grid collapses to a single column so
|
|
63
|
+
// each Row spans full width and stacks vertically. Applied AFTER the
|
|
64
|
+
// dynamic gridColumns(template) so this rule wins inside the @container.
|
|
65
|
+
rootResponsive: {
|
|
66
|
+
gridTemplateColumns: {
|
|
67
|
+
default: null,
|
|
68
|
+
[`@container (max-width: ${STACK_BP})`]: '1fr',
|
|
69
|
+
},
|
|
70
|
+
// The card-list look needs the outer border to disappear in stack
|
|
71
|
+
// mode — each row paints its own border.
|
|
72
|
+
borderWidth: {
|
|
73
|
+
default: 1,
|
|
74
|
+
[`@container (max-width: ${STACK_BP})`]: 0,
|
|
75
|
+
},
|
|
76
|
+
backgroundColor: {
|
|
77
|
+
default: colors.bgCard,
|
|
78
|
+
[`@container (max-width: ${STACK_BP})`]: 'transparent',
|
|
79
|
+
},
|
|
80
|
+
overflow: {
|
|
81
|
+
default: 'hidden',
|
|
82
|
+
[`@container (max-width: ${STACK_BP})`]: 'visible',
|
|
83
|
+
},
|
|
84
|
+
rowGap: {
|
|
85
|
+
default: 0,
|
|
86
|
+
[`@container (max-width: ${STACK_BP})`]: spacing.sm,
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
// Header group — hidden entirely in stack mode
|
|
21
91
|
header: {
|
|
22
|
-
display:
|
|
92
|
+
display: {
|
|
93
|
+
default: 'grid',
|
|
94
|
+
[`@container (max-width: ${STACK_BP})`]: 'none',
|
|
95
|
+
},
|
|
23
96
|
gridColumn: '1 / -1',
|
|
24
97
|
gridTemplateColumns: 'subgrid',
|
|
25
98
|
backgroundColor: colors.bgCard,
|
|
@@ -32,43 +105,148 @@ export const styles = css.create({
|
|
|
32
105
|
gridTemplateColumns: 'subgrid',
|
|
33
106
|
},
|
|
34
107
|
|
|
35
|
-
// Row — spans all columns
|
|
108
|
+
// Row — spans all columns. In stack mode its template flips to 1fr so
|
|
109
|
+
// children stack as grid items in a single column (we keep grid context
|
|
110
|
+
// so cells with `gridColumn` overrides still compute).
|
|
36
111
|
row: {
|
|
37
112
|
display: 'grid',
|
|
38
113
|
gridColumn: '1 / -1',
|
|
39
|
-
gridTemplateColumns:
|
|
40
|
-
|
|
114
|
+
gridTemplateColumns: {
|
|
115
|
+
default: 'subgrid',
|
|
116
|
+
[`@container (max-width: ${STACK_BP})`]: '1fr',
|
|
117
|
+
},
|
|
118
|
+
borderBottomWidth: {
|
|
119
|
+
default: 1,
|
|
120
|
+
[`@container (max-width: ${STACK_BP})`]: 0,
|
|
121
|
+
},
|
|
41
122
|
borderBottomStyle: 'solid',
|
|
42
123
|
borderBottomColor: colors.border,
|
|
43
124
|
},
|
|
44
125
|
bodyRow: {
|
|
45
126
|
backgroundColor: {
|
|
46
127
|
default: 'transparent',
|
|
128
|
+
[`@container (max-width: ${STACK_BP})`]: colors.bgCard,
|
|
47
129
|
':hover': colors.bgCardHover,
|
|
48
130
|
},
|
|
49
131
|
transitionProperty: 'background-color',
|
|
50
132
|
transitionDuration: '150ms',
|
|
51
133
|
transitionTimingFunction: 'ease',
|
|
134
|
+
// Stack-mode card chrome
|
|
135
|
+
padding: {
|
|
136
|
+
default: 0,
|
|
137
|
+
[`@container (max-width: ${STACK_BP})`]: spacing.sm,
|
|
138
|
+
},
|
|
139
|
+
borderRadius: {
|
|
140
|
+
default: 0,
|
|
141
|
+
[`@container (max-width: ${STACK_BP})`]: radii.sm,
|
|
142
|
+
},
|
|
143
|
+
borderWidth: {
|
|
144
|
+
default: 0,
|
|
145
|
+
[`@container (max-width: ${STACK_BP})`]: 1,
|
|
146
|
+
},
|
|
147
|
+
borderStyle: 'solid',
|
|
148
|
+
borderColor: colors.border,
|
|
52
149
|
},
|
|
53
150
|
|
|
54
|
-
// Header cell
|
|
151
|
+
// Header cell — keeps headers on a single line in compact mode
|
|
55
152
|
headerCell: {
|
|
56
153
|
fontWeight: typography.fontWeightSemibold,
|
|
57
154
|
color: colors.textMuted,
|
|
58
155
|
textAlign: 'start',
|
|
156
|
+
whiteSpace: {
|
|
157
|
+
default: 'normal',
|
|
158
|
+
[`@container (max-width: ${COMPACT_BP})`]: 'nowrap',
|
|
159
|
+
},
|
|
59
160
|
},
|
|
60
161
|
|
|
61
|
-
// Body cell
|
|
162
|
+
// Body cell. In compact mode: nowrap + truncate. In stack mode:
|
|
163
|
+
// becomes a 2-column grid for label / value.
|
|
62
164
|
cell: {
|
|
63
165
|
color: colors.text,
|
|
64
|
-
display:
|
|
166
|
+
display: {
|
|
167
|
+
default: 'flex',
|
|
168
|
+
[`@container (max-width: ${STACK_BP})`]: 'grid',
|
|
169
|
+
},
|
|
65
170
|
alignItems: 'center',
|
|
171
|
+
minWidth: {
|
|
172
|
+
default: 'auto',
|
|
173
|
+
[`@container (max-width: ${COMPACT_BP})`]: 0,
|
|
174
|
+
},
|
|
175
|
+
overflow: {
|
|
176
|
+
default: 'visible',
|
|
177
|
+
[`@container (max-width: ${COMPACT_BP})`]: 'hidden',
|
|
178
|
+
},
|
|
179
|
+
textOverflow: {
|
|
180
|
+
default: 'clip',
|
|
181
|
+
[`@container (max-width: ${COMPACT_BP})`]: 'ellipsis',
|
|
182
|
+
},
|
|
183
|
+
whiteSpace: {
|
|
184
|
+
default: 'normal',
|
|
185
|
+
[`@container (max-width: ${COMPACT_BP})`]: 'nowrap',
|
|
186
|
+
[`@container (max-width: ${STACK_BP})`]: 'normal',
|
|
187
|
+
},
|
|
188
|
+
gridTemplateColumns: {
|
|
189
|
+
default: null,
|
|
190
|
+
[`@container (max-width: ${STACK_BP})`]: '1fr 2fr',
|
|
191
|
+
},
|
|
192
|
+
gap: {
|
|
193
|
+
default: 0,
|
|
194
|
+
[`@container (max-width: ${STACK_BP})`]: spacing.sm,
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
|
|
198
|
+
// Label rendered as a real <span> inside each cell. Display:none in
|
|
199
|
+
// default/compact, shown only in stack — matches StyleX guidance to
|
|
200
|
+
// prefer real elements over ::before/::after for non-shadow-DOM cases.
|
|
201
|
+
cellLabel: {
|
|
202
|
+
display: {
|
|
203
|
+
default: 'none',
|
|
204
|
+
[`@container (max-width: ${STACK_BP})`]: 'block',
|
|
205
|
+
},
|
|
206
|
+
color: colors.textMuted,
|
|
207
|
+
fontWeight: typography.fontWeightMedium,
|
|
208
|
+
fontSize: typography.fontSizeXs,
|
|
209
|
+
},
|
|
210
|
+
|
|
211
|
+
// Actions cell. In default/compact behaves like any cell. In stack
|
|
212
|
+
// mode: full-width footer of the card, right-aligned, with a top
|
|
213
|
+
// separator. Label span is suppressed in JSX (Cell does not render it
|
|
214
|
+
// when isActions=true).
|
|
215
|
+
cellActions: {
|
|
216
|
+
gridTemplateColumns: {
|
|
217
|
+
default: null,
|
|
218
|
+
[`@container (max-width: ${STACK_BP})`]: '1fr',
|
|
219
|
+
},
|
|
220
|
+
justifyContent: {
|
|
221
|
+
default: null,
|
|
222
|
+
[`@container (max-width: ${STACK_BP})`]: 'flex-end',
|
|
223
|
+
},
|
|
224
|
+
marginTop: {
|
|
225
|
+
default: 0,
|
|
226
|
+
[`@container (max-width: ${STACK_BP})`]: spacing.sm,
|
|
227
|
+
},
|
|
228
|
+
paddingTop: {
|
|
229
|
+
default: null,
|
|
230
|
+
[`@container (max-width: ${STACK_BP})`]: spacing.sm,
|
|
231
|
+
},
|
|
232
|
+
borderTopWidth: {
|
|
233
|
+
default: 0,
|
|
234
|
+
[`@container (max-width: ${STACK_BP})`]: 1,
|
|
235
|
+
},
|
|
236
|
+
borderTopStyle: 'solid',
|
|
237
|
+
borderTopColor: colors.border,
|
|
66
238
|
},
|
|
67
239
|
|
|
68
240
|
// Size: sm
|
|
69
241
|
cellSm: {
|
|
70
|
-
paddingTop:
|
|
71
|
-
|
|
242
|
+
paddingTop: {
|
|
243
|
+
default: spacing.xs,
|
|
244
|
+
[`@container (max-width: ${COMPACT_BP})`]: spacing.xs,
|
|
245
|
+
},
|
|
246
|
+
paddingBottom: {
|
|
247
|
+
default: spacing.xs,
|
|
248
|
+
[`@container (max-width: ${COMPACT_BP})`]: spacing.xs,
|
|
249
|
+
},
|
|
72
250
|
paddingLeft: spacing.sm,
|
|
73
251
|
paddingRight: spacing.sm,
|
|
74
252
|
fontSize: typography.fontSizeXs,
|
|
@@ -77,22 +255,33 @@ export const styles = css.create({
|
|
|
77
255
|
cellMd: {
|
|
78
256
|
paddingTop: spacing.sm,
|
|
79
257
|
paddingBottom: spacing.sm,
|
|
80
|
-
paddingLeft:
|
|
81
|
-
|
|
258
|
+
paddingLeft: {
|
|
259
|
+
default: spacing.md,
|
|
260
|
+
[`@container (max-width: ${COMPACT_BP})`]: spacing.sm,
|
|
261
|
+
},
|
|
262
|
+
paddingRight: {
|
|
263
|
+
default: spacing.md,
|
|
264
|
+
[`@container (max-width: ${COMPACT_BP})`]: spacing.sm,
|
|
265
|
+
},
|
|
82
266
|
fontSize: typography.fontSizeSm,
|
|
83
267
|
},
|
|
84
268
|
|
|
85
|
-
// Variant: striped (even body rows)
|
|
269
|
+
// Variant: striped (even body rows). Suppressed in stack — cards have
|
|
270
|
+
// their own surface and zebra-striping reads as a bug there.
|
|
86
271
|
stripedEven: {
|
|
87
272
|
backgroundColor: {
|
|
88
273
|
default: colors.bgCardHover,
|
|
274
|
+
[`@container (max-width: ${STACK_BP})`]: colors.bgCard,
|
|
89
275
|
':hover': colors.bgCardHover,
|
|
90
276
|
},
|
|
91
277
|
},
|
|
92
278
|
|
|
93
|
-
// Variant: bordered (cells get side borders)
|
|
279
|
+
// Variant: bordered (cells get side borders). Suppressed in stack.
|
|
94
280
|
borderedCell: {
|
|
95
|
-
borderRightWidth:
|
|
281
|
+
borderRightWidth: {
|
|
282
|
+
default: 1,
|
|
283
|
+
[`@container (max-width: ${STACK_BP})`]: 0,
|
|
284
|
+
},
|
|
96
285
|
borderRightStyle: 'solid',
|
|
97
286
|
borderRightColor: colors.border,
|
|
98
287
|
},
|
|
@@ -100,6 +289,15 @@ export const styles = css.create({
|
|
|
100
289
|
borderRightWidth: 0,
|
|
101
290
|
},
|
|
102
291
|
|
|
292
|
+
// SortChip — visible only in stack mode
|
|
293
|
+
sortChip: {
|
|
294
|
+
display: {
|
|
295
|
+
default: 'none',
|
|
296
|
+
[`@container (max-width: ${STACK_BP})`]: 'inline-flex',
|
|
297
|
+
},
|
|
298
|
+
alignSelf: 'flex-start',
|
|
299
|
+
},
|
|
300
|
+
|
|
103
301
|
// Dynamic: grid columns applied on Root
|
|
104
302
|
gridColumns: (template: string) => ({
|
|
105
303
|
gridTemplateColumns: template,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Side-effect-only module: registers `@duro-app/ui`'s additions to
|
|
2
|
+
// TanStack's `ColumnMeta` so consumers can write
|
|
3
|
+
// meta: { stackLabel: 'X', isActions: true }
|
|
4
|
+
// on column defs and have it type-check, regardless of whether they
|
|
5
|
+
// import from Table/FromTanstack in that particular file.
|
|
6
|
+
//
|
|
7
|
+
// `index.ts` re-exports this module so the augmentation registers as
|
|
8
|
+
// soon as any file in the consumer's TS program imports from
|
|
9
|
+
// `@duro-app/ui`. Keeping the augmentation in a standalone file (instead
|
|
10
|
+
// of co-located with `FromTanstack.tsx`) also keeps it from being
|
|
11
|
+
// tree-shaken out of the published types.
|
|
12
|
+
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
14
|
+
declare module '@tanstack/react-table' {
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
16
|
+
interface ColumnMeta<TData extends unknown, TValue> {
|
|
17
|
+
/** Override the stack-mode label when columnDef.header is JSX (icon + text, etc). */
|
|
18
|
+
stackLabel?: string
|
|
19
|
+
/**
|
|
20
|
+
* Marks this column as the actions column. In stack mode the cells
|
|
21
|
+
* render as a full-width footer instead of a labelled key/value row.
|
|
22
|
+
*/
|
|
23
|
+
isActions?: boolean
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Empty export so this file is treated as a module by TS and ts-up/vite.
|
|
28
|
+
export {}
|
package/src/index.ts
CHANGED
|
@@ -46,6 +46,11 @@ export {
|
|
|
46
46
|
export {Tag, type TagVariant, type TagSize} from './components/Tag/Tag'
|
|
47
47
|
export {TagGroup} from './components/TagGroup/TagGroup'
|
|
48
48
|
export {Table, type TableVariant, type TableSize} from './components/Table/Table'
|
|
49
|
+
// Side-effect import registers our augmentation of TanStack's ColumnMeta
|
|
50
|
+
// (stackLabel / isActions). Standalone module so the augmentation lands
|
|
51
|
+
// whenever this package is in a consumer's TS program, even if FromTanstack
|
|
52
|
+
// itself isn't imported.
|
|
53
|
+
import './components/Table/tanstack-augmentation'
|
|
49
54
|
// TanStack Table: consumers install @tanstack/react-table directly and use
|
|
50
55
|
// Table.Pagination, Table.SortIndicator, Table.ColumnFilter for styled integration
|
|
51
56
|
export {Tabs} from './components/Tabs/Tabs'
|