@maestro-js/components 1.0.0-alpha.19 → 1.0.0-alpha.2
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/commands/add.ts +1 -16
- package/dist/components.json +1 -1
- package/dist/index.js +1 -14
- package/package.json +5 -5
- package/registry.json +790 -598
- package/scripts/build.ts +4 -11
- package/src/components/alert-dialog.tsx +3 -3
- package/src/components/avatar.tsx +1 -1
- package/src/components/button-link.tsx +0 -3
- package/src/components/button.tsx +0 -4
- package/src/components/checkbox.tsx +7 -7
- package/src/components/chip.tsx +7 -7
- package/src/components/container.tsx +3 -3
- package/src/components/dialog.tsx +7 -21
- package/src/components/disclosure.tsx +1 -1
- package/src/components/drawer.tsx +5 -19
- package/src/components/form.tsx +5 -27
- package/src/components/helpers/form-field.tsx +8 -7
- package/src/components/helpers/get-button-classes.ts +23 -23
- package/src/components/helpers/headless-button.tsx +1 -1
- package/src/components/inline-alert.tsx +3 -3
- package/src/components/labeled-value.tsx +2 -2
- package/src/components/menu.tsx +26 -60
- package/src/components/month-day-input.tsx +1 -2
- package/src/components/multiselect.tsx +70 -74
- package/src/components/radio.tsx +8 -8
- package/src/components/select.tsx +8 -9
- package/src/components/stepper.tsx +6 -6
- package/src/components/switch.tsx +7 -7
- package/src/components/tabs.tsx +1 -1
- package/src/components/tag-field.tsx +3 -3
- package/src/components/text-area.tsx +1 -1
- package/src/components/text-field.tsx +1 -4
- package/src/components/toast.tsx +6 -6
- package/src/components/toggle-button-group.tsx +2 -2
- package/src/utils/icons.d.ts +1 -2
- package/src/utils/use-tab-indicator.ts +9 -9
- package/src/components/date-range.tsx +0 -138
- package/src/components/optional-link.tsx +0 -15
- package/src/components/table/headless-templated-row-table.ts +0 -550
- package/src/components/table/index.tsx +0 -41
- package/src/components/table/server-table.ts +0 -143
- package/src/components/table/table-actions.tsx +0 -76
- package/src/components/table/table-container.tsx +0 -173
- package/src/components/table/table-container.type-test.ts +0 -155
- package/src/components/table/table-filters/date-range-filter.tsx +0 -227
- package/src/components/table/table-filters/select-filter.tsx +0 -211
- package/src/components/table/table-filters/sort.tsx +0 -85
- package/src/components/table/table-primitives.tsx +0 -226
- package/src/components/table/table-toolbar.tsx +0 -300
- package/src/components/table/table-types.ts +0 -61
- package/src/components/table/use-client-table.ts +0 -157
- package/src/components/table/use-client-table.type-test.ts +0 -217
- package/src/components/table/use-server-table.ts +0 -192
- package/src/components/table/use-server-table.type-test.ts +0 -174
- package/src/utils/use-query-state.ts +0 -626
|
@@ -1,550 +0,0 @@
|
|
|
1
|
-
import { matchSorter, type MatchSorterOptions } from 'match-sorter'
|
|
2
|
-
|
|
3
|
-
export declare namespace HeadlessTemplatedRowTable {
|
|
4
|
-
type RowData = Record<string, any>
|
|
5
|
-
|
|
6
|
-
type Feature<
|
|
7
|
-
TData extends RowData,
|
|
8
|
-
FeatureState extends Record<string, any>,
|
|
9
|
-
FeatureOptions extends Record<string, any>,
|
|
10
|
-
FeatureExtras extends Record<string, any>
|
|
11
|
-
> = (<
|
|
12
|
-
TableState extends Record<string, any>,
|
|
13
|
-
TableOptions extends Record<string, any>,
|
|
14
|
-
TableExtras extends Record<string, any>
|
|
15
|
-
>(
|
|
16
|
-
table: Table<TData, TableState, TableOptions, TableExtras>
|
|
17
|
-
) => void) & {
|
|
18
|
-
['~feature']: {
|
|
19
|
-
state: FeatureState
|
|
20
|
-
options: FeatureOptions
|
|
21
|
-
extras: FeatureExtras
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
type FeatureBase<TData extends RowData> = Feature<TData, {}, {}, {}>
|
|
26
|
-
|
|
27
|
-
type ExtractFeatureChanges<F extends FeatureBase<RowData>> =
|
|
28
|
-
F extends Feature<infer FTData, infer FState, infer FOptions, infer FExtras>
|
|
29
|
-
? {
|
|
30
|
-
TData: FTData
|
|
31
|
-
State: FState
|
|
32
|
-
Options: FOptions
|
|
33
|
-
Extras: FExtras
|
|
34
|
-
}
|
|
35
|
-
: never
|
|
36
|
-
|
|
37
|
-
type ExtractAllFeatureChanges<Features extends FeatureBase<RowData>[]> = Features extends [
|
|
38
|
-
infer F extends FeatureBase<RowData>,
|
|
39
|
-
...infer Rest extends FeatureBase<RowData>[]
|
|
40
|
-
]
|
|
41
|
-
? ExtractFeatureChanges<F> & ExtractAllFeatureChanges<Rest>
|
|
42
|
-
: {
|
|
43
|
-
TData: RowData
|
|
44
|
-
State: {}
|
|
45
|
-
Options: {}
|
|
46
|
-
Extras: {}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
type ApplyFeature<T extends TableBase<RowData>, F extends FeatureBase<RowData>> =
|
|
50
|
-
T extends Table<infer TData, infer State, infer Options, infer Extras>
|
|
51
|
-
? F extends Feature<infer FTData, infer FState, infer FOptions, infer FExtras>
|
|
52
|
-
? Table<TData & FTData, State & FState, Options & FOptions, Extras & FExtras>
|
|
53
|
-
: never
|
|
54
|
-
: never
|
|
55
|
-
|
|
56
|
-
type ApplyFeatures<T extends TableBase<RowData>, Features extends FeatureBase<RowData>[]> = Features extends [
|
|
57
|
-
infer F extends FeatureBase<RowData>,
|
|
58
|
-
...infer Rest extends FeatureBase<RowData>[]
|
|
59
|
-
]
|
|
60
|
-
? ApplyFeatures<ApplyFeature<T, F>, Rest>
|
|
61
|
-
: T
|
|
62
|
-
|
|
63
|
-
type TableOptions<TData extends RowData, Features extends FeatureBase<TData>[]> = {
|
|
64
|
-
rows: TData[]
|
|
65
|
-
features: [...Features]
|
|
66
|
-
initialState?: Partial<ExtractAllFeatureChanges<Features>['State']>
|
|
67
|
-
state?: Partial<ExtractAllFeatureChanges<Features>['State']>
|
|
68
|
-
} & ExtractAllFeatureChanges<Features>['Options']
|
|
69
|
-
|
|
70
|
-
type Table<
|
|
71
|
-
TData extends RowData,
|
|
72
|
-
State extends Record<string, any>,
|
|
73
|
-
Options extends Record<string, any>,
|
|
74
|
-
Extras extends Record<string, any>
|
|
75
|
-
> = {
|
|
76
|
-
getRows(): TData[]
|
|
77
|
-
setRows(rows: TData[]): void
|
|
78
|
-
getOptions(): Options & { state?: Partial<State>; initialState?: Partial<State> }
|
|
79
|
-
setOptions(options: Options): void
|
|
80
|
-
state: State
|
|
81
|
-
setState(update: State | ((previous: State) => State)): void
|
|
82
|
-
subscribe: (onStoreChange: () => void) => () => void
|
|
83
|
-
} & Extras
|
|
84
|
-
|
|
85
|
-
type TableBase<TData extends RowData> = Table<TData, {}, {}, {}>
|
|
86
|
-
|
|
87
|
-
type ReactTable<
|
|
88
|
-
TData extends RowData,
|
|
89
|
-
Features extends FeatureBase<TData>[] = []
|
|
90
|
-
> = HeadlessTemplatedRowTable.ApplyFeatures<HeadlessTemplatedRowTable.TableBase<TData>, Features>
|
|
91
|
-
|
|
92
|
-
type FilterPredicate<
|
|
93
|
-
TData extends RowData,
|
|
94
|
-
Name extends string = string,
|
|
95
|
-
Value = Name extends keyof TData ? TData[Name] : any
|
|
96
|
-
> = (row: TData, value: Value, name: string) => boolean
|
|
97
|
-
|
|
98
|
-
type FilterConfig<TData extends RowData, FC extends Record<string, any> = Record<string, any>> = {
|
|
99
|
-
[K in keyof FC & string]: FilterPredicate<TData, K>
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
type ExtractFilterValue<C extends FilterPredicate<any, any, any>> = Parameters<C>[1]
|
|
103
|
-
|
|
104
|
-
type FilterState<TData extends RowData, Config extends FilterConfig<TData>> = {
|
|
105
|
-
[key in keyof Config]: ExtractFilterValue<Config[key]> | null | undefined
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
type SortComparator<TData extends RowData, Name extends string = string> = (
|
|
109
|
-
row1: TData,
|
|
110
|
-
row2: TData,
|
|
111
|
-
name: string
|
|
112
|
-
) => number
|
|
113
|
-
|
|
114
|
-
type SortConfig<TData extends RowData, SC extends Record<string, any> = Record<string, any>> = {
|
|
115
|
-
[K in keyof SC & string]: SortComparator<TData, K>
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
type SortState<Config extends Record<string, SortComparator<any, any>>> = (keyof Config & string) | null
|
|
119
|
-
|
|
120
|
-
type PaginationState = { limit: number; skip: number }
|
|
121
|
-
|
|
122
|
-
type FilterFeature<TData extends RowData, Config extends FilterConfig<TData>> = Feature<
|
|
123
|
-
TData,
|
|
124
|
-
{ filters: FilterState<TData, Config> },
|
|
125
|
-
{
|
|
126
|
-
manualFiltering?: boolean
|
|
127
|
-
onFiltersChange?: (
|
|
128
|
-
val: FilterState<TData, Config> | ((prev: FilterState<TData, Config>) => FilterState<TData, Config>)
|
|
129
|
-
) => void
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
getFilterConfig(): { [key in keyof Config]: ExtractFilterValue<Config[key]> }
|
|
133
|
-
setFilters: (
|
|
134
|
-
val: FilterState<TData, Config> | ((prev: FilterState<TData, Config>) => FilterState<TData, Config>)
|
|
135
|
-
) => void
|
|
136
|
-
}
|
|
137
|
-
>
|
|
138
|
-
|
|
139
|
-
type SearchFeature<TData extends RowData> = Feature<
|
|
140
|
-
TData,
|
|
141
|
-
{ search: string },
|
|
142
|
-
{
|
|
143
|
-
manualSearch?: boolean
|
|
144
|
-
onSearchChange?: (val: string | ((prev: string) => string)) => void
|
|
145
|
-
},
|
|
146
|
-
{
|
|
147
|
-
setSearch: (val: string | ((prev: string) => string)) => void
|
|
148
|
-
}
|
|
149
|
-
>
|
|
150
|
-
|
|
151
|
-
type SortFeature<TData extends RowData, Config extends SortConfig<TData>> = Feature<
|
|
152
|
-
TData,
|
|
153
|
-
{ sort: SortState<Config> },
|
|
154
|
-
{
|
|
155
|
-
manualSort?: boolean
|
|
156
|
-
onSortChange?: (val: SortState<Config> | ((prev: SortState<Config>) => SortState<Config>)) => void
|
|
157
|
-
},
|
|
158
|
-
{
|
|
159
|
-
getSortConfig(): { [key in keyof Config]: null }
|
|
160
|
-
setSort: (val: SortState<Config> | ((prev: SortState<Config>) => SortState<Config>)) => void
|
|
161
|
-
}
|
|
162
|
-
>
|
|
163
|
-
|
|
164
|
-
type PaginationFeature<TData extends RowData> = Feature<
|
|
165
|
-
TData,
|
|
166
|
-
{ pagination: PaginationState },
|
|
167
|
-
{
|
|
168
|
-
manualPagination?: boolean
|
|
169
|
-
onPaginationChange?: (val: PaginationState | ((prev: PaginationState) => PaginationState)) => void
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
setPagination: (val: PaginationState | ((prev: PaginationState) => PaginationState)) => void
|
|
173
|
-
getPrePaginationRows(): TData[]
|
|
174
|
-
}
|
|
175
|
-
>
|
|
176
|
-
|
|
177
|
-
type RowSelectionFeature<TData extends RowData> = Feature<
|
|
178
|
-
TData,
|
|
179
|
-
{ rowSelection: Set<string> },
|
|
180
|
-
{
|
|
181
|
-
onRowSelectionChange?: (val: Set<string>) => void
|
|
182
|
-
},
|
|
183
|
-
{
|
|
184
|
-
toggleRowSelection: (row: TData) => void
|
|
185
|
-
toggleAllRowSelection: () => void
|
|
186
|
-
isRowSelected: (row: TData) => boolean
|
|
187
|
-
clearRowSelection: () => void
|
|
188
|
-
}
|
|
189
|
-
>
|
|
190
|
-
|
|
191
|
-
type RowCountFeature<TData extends RowData> = Feature<TData, {}, { rowCount?: number }, { getRowCount(): number }>
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
export const HeadlessTemplatedRowTable = {
|
|
195
|
-
createTable,
|
|
196
|
-
filtering,
|
|
197
|
-
search,
|
|
198
|
-
sort,
|
|
199
|
-
pagination,
|
|
200
|
-
rowSelection,
|
|
201
|
-
rowCount
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// ============================================================
|
|
205
|
-
// createTable
|
|
206
|
-
// ============================================================
|
|
207
|
-
|
|
208
|
-
function createTable<
|
|
209
|
-
TData extends HeadlessTemplatedRowTable.RowData,
|
|
210
|
-
Features extends HeadlessTemplatedRowTable.FeatureBase<TData>[]
|
|
211
|
-
>(
|
|
212
|
-
initialState: HeadlessTemplatedRowTable.TableOptions<TData, Features>
|
|
213
|
-
): HeadlessTemplatedRowTable.ApplyFeatures<HeadlessTemplatedRowTable.TableBase<TData>, Features> {
|
|
214
|
-
let rows = initialState.rows
|
|
215
|
-
let { rows: _rows, features: _features, ...options } = initialState
|
|
216
|
-
|
|
217
|
-
const getRows = () => rows
|
|
218
|
-
const getOptions = () => options
|
|
219
|
-
|
|
220
|
-
function setRows(updatedRows: TData[]) {
|
|
221
|
-
if (rows !== updatedRows) {
|
|
222
|
-
rows = updatedRows
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
function setOptions(updatedOptions: Omit<HeadlessTemplatedRowTable.TableOptions<TData, Features>, 'rows' | 'features'>) {
|
|
226
|
-
options = { ...options, ...updatedOptions }
|
|
227
|
-
if (updatedOptions.state) {
|
|
228
|
-
table.state = { ...table.state, ...updatedOptions.state }
|
|
229
|
-
}
|
|
230
|
-
subscription.notify()
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
const subscription = createSubscription()
|
|
234
|
-
let flushing = false
|
|
235
|
-
let pendingNotify = false
|
|
236
|
-
|
|
237
|
-
function setState<S>(val: S | ((previous: S) => S)) {
|
|
238
|
-
if (typeof val === 'function') {
|
|
239
|
-
// @ts-expect-error
|
|
240
|
-
table.state = val(table.state)
|
|
241
|
-
} else {
|
|
242
|
-
// @ts-expect-error
|
|
243
|
-
table.state = val
|
|
244
|
-
}
|
|
245
|
-
if (flushing) {
|
|
246
|
-
pendingNotify = true
|
|
247
|
-
return
|
|
248
|
-
}
|
|
249
|
-
flushing = true
|
|
250
|
-
subscription.notify()
|
|
251
|
-
let flushCount = 0
|
|
252
|
-
while (pendingNotify) {
|
|
253
|
-
if (++flushCount > 100) {
|
|
254
|
-
console.warn('Table setState: exceeded 100 flush iterations — possible infinite notification loop')
|
|
255
|
-
pendingNotify = false
|
|
256
|
-
break
|
|
257
|
-
}
|
|
258
|
-
pendingNotify = false
|
|
259
|
-
subscription.notify()
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
flushing = false
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
const table: HeadlessTemplatedRowTable.TableBase<TData> = {
|
|
266
|
-
getRows,
|
|
267
|
-
setRows,
|
|
268
|
-
getOptions,
|
|
269
|
-
setOptions,
|
|
270
|
-
state: {},
|
|
271
|
-
setState,
|
|
272
|
-
subscribe: subscription.subscribe
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
initialState.features.forEach((feature) => feature(table))
|
|
276
|
-
|
|
277
|
-
// @ts-expect-error
|
|
278
|
-
return table
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
// ============================================================
|
|
282
|
-
// Client Filtering
|
|
283
|
-
// ============================================================
|
|
284
|
-
|
|
285
|
-
type FilterFeature<
|
|
286
|
-
TData extends HeadlessTemplatedRowTable.RowData,
|
|
287
|
-
Config extends HeadlessTemplatedRowTable.FilterConfig<TData>
|
|
288
|
-
> = HeadlessTemplatedRowTable.FilterFeature<TData, Config>
|
|
289
|
-
|
|
290
|
-
function filtering<
|
|
291
|
-
TData extends HeadlessTemplatedRowTable.RowData,
|
|
292
|
-
Config extends HeadlessTemplatedRowTable.FilterConfig<TData>
|
|
293
|
-
>(filterConfig: Config): FilterFeature<TData, Config> {
|
|
294
|
-
const filterKeys = Object.keys(filterConfig) as (keyof Config extends string ? keyof Config : never)[]
|
|
295
|
-
const defaultFilterState = Object.fromEntries(filterKeys.map((key) => [key, null]))
|
|
296
|
-
const tableFilterConfig = defaultFilterState as { [key in keyof Config]: null }
|
|
297
|
-
|
|
298
|
-
return defineFeature<TData, FilterFeature<TData, Config>>((table) => {
|
|
299
|
-
table.state.filters = {
|
|
300
|
-
...defaultFilterState,
|
|
301
|
-
...table.getOptions().initialState?.['filters']
|
|
302
|
-
} as HeadlessTemplatedRowTable.FilterState<TData, Config>
|
|
303
|
-
|
|
304
|
-
const prevGetFilterConfig = table['getFilterConfig']
|
|
305
|
-
table.getFilterConfig = () => ({ ...(prevGetFilterConfig?.() ?? {}), ...tableFilterConfig })
|
|
306
|
-
|
|
307
|
-
table.setFilters = (val) => {
|
|
308
|
-
const onFiltersChange = table.getOptions().onFiltersChange
|
|
309
|
-
if (onFiltersChange) onFiltersChange(val)
|
|
310
|
-
else
|
|
311
|
-
table.setState((prev) => ({
|
|
312
|
-
...prev,
|
|
313
|
-
filters: typeof val === 'function' ? val(prev.filters) : val
|
|
314
|
-
}))
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
const applyFilters = memo((rows: TData[], filters: HeadlessTemplatedRowTable.FilterState<TData, Config>) =>
|
|
318
|
-
rows.filter((row) =>
|
|
319
|
-
filterKeys.every((f) => {
|
|
320
|
-
const value = filters[f]
|
|
321
|
-
if (value == null) return true
|
|
322
|
-
return filterConfig[f]!(row, value, f)
|
|
323
|
-
})
|
|
324
|
-
)
|
|
325
|
-
)
|
|
326
|
-
|
|
327
|
-
const originalGetRows = table.getRows
|
|
328
|
-
table.getRows = () => {
|
|
329
|
-
if (table.getOptions().manualFiltering) return originalGetRows()
|
|
330
|
-
return applyFilters(originalGetRows(), table.state.filters)
|
|
331
|
-
}
|
|
332
|
-
})
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// ============================================================
|
|
336
|
-
// Client Search
|
|
337
|
-
// ============================================================
|
|
338
|
-
|
|
339
|
-
type SearchFeature<TData extends HeadlessTemplatedRowTable.RowData> = HeadlessTemplatedRowTable.SearchFeature<TData>
|
|
340
|
-
|
|
341
|
-
function search<TData extends HeadlessTemplatedRowTable.RowData>(options: MatchSorterOptions<TData>): SearchFeature<TData> {
|
|
342
|
-
return defineFeature<TData, SearchFeature<TData>>((table) => {
|
|
343
|
-
const applySearch = memo((rows: TData[], query: string) => {
|
|
344
|
-
return query ? query.split(' ').reduce((results, term) => matchSorter(results, term, options), rows) : rows
|
|
345
|
-
})
|
|
346
|
-
|
|
347
|
-
table.state.search = (table.getOptions().initialState?.['search'] as string) ?? ''
|
|
348
|
-
|
|
349
|
-
table.setSearch = (val) => {
|
|
350
|
-
const onSearchChange = table.getOptions().onSearchChange
|
|
351
|
-
if (onSearchChange) onSearchChange(val)
|
|
352
|
-
else table.setState((prev) => ({ ...prev, search: typeof val === 'function' ? val(prev.search) : val }))
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
const originalGetRows = table.getRows
|
|
356
|
-
table.getRows = () => {
|
|
357
|
-
if (table.getOptions().manualSearch) return originalGetRows()
|
|
358
|
-
return applySearch(originalGetRows(), table.state.search)
|
|
359
|
-
}
|
|
360
|
-
})
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// ============================================================
|
|
364
|
-
// Client Sort
|
|
365
|
-
// ============================================================
|
|
366
|
-
|
|
367
|
-
type SortFeature<
|
|
368
|
-
TData extends HeadlessTemplatedRowTable.RowData,
|
|
369
|
-
Config extends HeadlessTemplatedRowTable.SortConfig<TData>
|
|
370
|
-
> = HeadlessTemplatedRowTable.SortFeature<TData, Config>
|
|
371
|
-
|
|
372
|
-
function sort<TData extends HeadlessTemplatedRowTable.RowData, Config extends HeadlessTemplatedRowTable.SortConfig<TData>>(
|
|
373
|
-
config: Config,
|
|
374
|
-
defaultSort?: HeadlessTemplatedRowTable.SortState<Config>
|
|
375
|
-
): SortFeature<TData, Config> {
|
|
376
|
-
const tableSortConfig = Object.fromEntries(Object.keys(config).map((f) => [f, null])) as {
|
|
377
|
-
[key in keyof Config]: null
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
return defineFeature<TData, SortFeature<TData, Config>>((table) => {
|
|
381
|
-
table.state.sort =
|
|
382
|
-
(table.getOptions().initialState?.['sort'] as HeadlessTemplatedRowTable.SortState<Config>) ?? defaultSort ?? null
|
|
383
|
-
|
|
384
|
-
const prevGetSortConfig = table['getSortConfig']
|
|
385
|
-
table.getSortConfig = () => ({ ...(prevGetSortConfig?.() ?? {}), ...tableSortConfig })
|
|
386
|
-
|
|
387
|
-
table.setSort = (val) => {
|
|
388
|
-
const onSortChange = table.getOptions().onSortChange
|
|
389
|
-
if (onSortChange) onSortChange(val)
|
|
390
|
-
else table.setState((prev) => ({ ...prev, sort: typeof val === 'function' ? val(prev.sort) : val }))
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
const applySort = memo((rows: TData[], sort: HeadlessTemplatedRowTable.SortState<Config>) =>
|
|
394
|
-
sort && config[sort] ? [...rows].sort((a, b) => config[sort]!(a, b, sort)) : rows
|
|
395
|
-
)
|
|
396
|
-
|
|
397
|
-
const originalGetRows = table.getRows
|
|
398
|
-
table.getRows = () => {
|
|
399
|
-
if (table.getOptions().manualSort) return originalGetRows()
|
|
400
|
-
return applySort(originalGetRows(), table.state.sort)
|
|
401
|
-
}
|
|
402
|
-
})
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
// ============================================================
|
|
406
|
-
// Client Pagination
|
|
407
|
-
// ============================================================
|
|
408
|
-
|
|
409
|
-
type PaginationFeature<TData extends HeadlessTemplatedRowTable.RowData> = HeadlessTemplatedRowTable.PaginationFeature<TData>
|
|
410
|
-
|
|
411
|
-
function pagination<TData extends HeadlessTemplatedRowTable.RowData>(defaultLimit: number): PaginationFeature<TData> {
|
|
412
|
-
return defineFeature<TData, PaginationFeature<TData>>((table) => {
|
|
413
|
-
table.state.pagination = (table.getOptions().initialState?.[
|
|
414
|
-
'pagination'
|
|
415
|
-
] as HeadlessTemplatedRowTable.PaginationState) ?? {
|
|
416
|
-
limit: defaultLimit,
|
|
417
|
-
skip: 0
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
table.setPagination = (val) => {
|
|
421
|
-
const onPaginationChange = table.getOptions().onPaginationChange
|
|
422
|
-
if (onPaginationChange) onPaginationChange(val)
|
|
423
|
-
else table.setState((prev) => ({ ...prev, pagination: typeof val === 'function' ? val(prev.pagination) : val }))
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
const originalGetRows = table.getRows
|
|
427
|
-
table.getPrePaginationRows = originalGetRows
|
|
428
|
-
table.getRows = () => {
|
|
429
|
-
if (table.getOptions().manualPagination) return originalGetRows()
|
|
430
|
-
const { skip, limit } = table.state.pagination
|
|
431
|
-
return originalGetRows().slice(skip, skip + limit)
|
|
432
|
-
}
|
|
433
|
-
})
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
// ============================================================
|
|
437
|
-
// Client Row Selection
|
|
438
|
-
// ============================================================
|
|
439
|
-
|
|
440
|
-
type RowSelectionFeature<TData extends HeadlessTemplatedRowTable.RowData> =
|
|
441
|
-
HeadlessTemplatedRowTable.RowSelectionFeature<TData>
|
|
442
|
-
|
|
443
|
-
function rowSelection<TData extends HeadlessTemplatedRowTable.RowData>(
|
|
444
|
-
getRowId: (row: TData) => string
|
|
445
|
-
): RowSelectionFeature<TData> {
|
|
446
|
-
return defineFeature<TData, RowSelectionFeature<TData>>((table) => {
|
|
447
|
-
table.state.rowSelection = (table.getOptions().initialState?.['rowSelection'] as Set<string>) ?? new Set<string>()
|
|
448
|
-
|
|
449
|
-
const getSelection = () => table.state.rowSelection
|
|
450
|
-
const setSelection = (next: Set<string>) => {
|
|
451
|
-
const onRowSelectionChange = table.getOptions().onRowSelectionChange
|
|
452
|
-
if (onRowSelectionChange) onRowSelectionChange(next)
|
|
453
|
-
else table.setState((prev) => ({ ...prev, rowSelection: next }))
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
table.toggleRowSelection = (row: TData) => {
|
|
457
|
-
const id = getRowId(row)
|
|
458
|
-
const next = new Set(getSelection())
|
|
459
|
-
if (next.has(id)) next.delete(id)
|
|
460
|
-
else next.add(id)
|
|
461
|
-
setSelection(next)
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
table.toggleAllRowSelection = () => {
|
|
465
|
-
const rows = table.getRows()
|
|
466
|
-
const rowIds = new Set(rows.map(getRowId))
|
|
467
|
-
const allSelected = rowIds.size > 0 && [...rowIds].every((id) => getSelection().has(id))
|
|
468
|
-
setSelection(allSelected ? new Set<string>() : rowIds)
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
table.isRowSelected = (row: TData) => {
|
|
472
|
-
return getSelection().has(getRowId(row))
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
table.clearRowSelection = () => {
|
|
476
|
-
setSelection(new Set<string>())
|
|
477
|
-
}
|
|
478
|
-
})
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
// ============================================================
|
|
482
|
-
// Row Count
|
|
483
|
-
// ============================================================
|
|
484
|
-
|
|
485
|
-
type RowCountFeature<TData extends HeadlessTemplatedRowTable.RowData> = HeadlessTemplatedRowTable.RowCountFeature<TData>
|
|
486
|
-
|
|
487
|
-
function rowCount<TData extends HeadlessTemplatedRowTable.RowData>(): RowCountFeature<TData> {
|
|
488
|
-
return defineFeature<TData, RowCountFeature<TData>>((table) => {
|
|
489
|
-
table.getRowCount = () => {
|
|
490
|
-
return (
|
|
491
|
-
table.getOptions().rowCount ??
|
|
492
|
-
('getPrePaginationRows' in table ? table.getPrePaginationRows().length : table.getRows().length)
|
|
493
|
-
)
|
|
494
|
-
}
|
|
495
|
-
})
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
// ============================================================
|
|
499
|
-
// Helpers
|
|
500
|
-
// ============================================================
|
|
501
|
-
|
|
502
|
-
function memo<TArgs extends any[], TResult>(fn: (...args: TArgs) => TResult): (...args: TArgs) => TResult {
|
|
503
|
-
let lastArgs: TArgs | undefined
|
|
504
|
-
let lastResult: TResult
|
|
505
|
-
|
|
506
|
-
return (...args: TArgs) => {
|
|
507
|
-
if (lastArgs && args.length === lastArgs.length && args.every((arg, i) => arg === lastArgs![i])) {
|
|
508
|
-
return lastResult
|
|
509
|
-
}
|
|
510
|
-
lastArgs = args
|
|
511
|
-
lastResult = fn(...args)
|
|
512
|
-
return lastResult
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
function createSubscription(callback?: () => void) {
|
|
517
|
-
type Subscriber = () => void
|
|
518
|
-
const subscribers = new Set<Subscriber>(callback ? [callback] : [])
|
|
519
|
-
function subscribe(onStoreChange: () => void) {
|
|
520
|
-
subscribers.add(onStoreChange)
|
|
521
|
-
function unsubscribe() {
|
|
522
|
-
subscribers.delete(onStoreChange)
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
return unsubscribe
|
|
526
|
-
}
|
|
527
|
-
function notify() {
|
|
528
|
-
subscribers.forEach((s) => s())
|
|
529
|
-
}
|
|
530
|
-
return { subscribe, notify }
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
function defineFeature<
|
|
534
|
-
TData extends HeadlessTemplatedRowTable.RowData,
|
|
535
|
-
F extends HeadlessTemplatedRowTable.Feature<TData, {}, {}, {}>
|
|
536
|
-
>(
|
|
537
|
-
callback: <
|
|
538
|
-
TableState extends Record<string, any>,
|
|
539
|
-
TableOptions extends Record<string, any>,
|
|
540
|
-
TableExtras extends Record<string, any>
|
|
541
|
-
>(
|
|
542
|
-
table: HeadlessTemplatedRowTable.ApplyFeature<
|
|
543
|
-
HeadlessTemplatedRowTable.Table<TData, TableState, TableOptions, TableExtras>,
|
|
544
|
-
F
|
|
545
|
-
>
|
|
546
|
-
) => void
|
|
547
|
-
): F {
|
|
548
|
-
// @ts-expect-error
|
|
549
|
-
return (table) => callback(table)
|
|
550
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { createServerTable } from './server-table'
|
|
2
|
-
import { TableContainer } from './table-container'
|
|
3
|
-
import { TableSelectFilter } from './table-filters/select-filter'
|
|
4
|
-
import { TableSelectSort } from './table-filters/sort'
|
|
5
|
-
import {
|
|
6
|
-
TableBody,
|
|
7
|
-
TableCell,
|
|
8
|
-
TableDescription,
|
|
9
|
-
TableFooter,
|
|
10
|
-
TableMain,
|
|
11
|
-
TableRow,
|
|
12
|
-
TableTitle,
|
|
13
|
-
TableTitleLink
|
|
14
|
-
} from './table-primitives'
|
|
15
|
-
import { TableActions, TableHeader, TableSearch } from './table-toolbar'
|
|
16
|
-
import { TableActionButton, TableMenu, TableSelectionActions, TableSelectionAction } from './table-actions'
|
|
17
|
-
import { useClientTable } from './use-client-table'
|
|
18
|
-
import { useServerTable } from './use-server-table'
|
|
19
|
-
|
|
20
|
-
export const Table = Object.assign(TableContainer, {
|
|
21
|
-
useClientTable,
|
|
22
|
-
useServerTable,
|
|
23
|
-
createServerTable,
|
|
24
|
-
Main: TableMain,
|
|
25
|
-
Search: TableSearch,
|
|
26
|
-
Body: TableBody,
|
|
27
|
-
Row: TableRow,
|
|
28
|
-
Cell: TableCell,
|
|
29
|
-
Header: TableHeader,
|
|
30
|
-
Footer: TableFooter,
|
|
31
|
-
Title: TableTitle,
|
|
32
|
-
TitleLink: TableTitleLink,
|
|
33
|
-
Description: TableDescription,
|
|
34
|
-
SelectFilter: TableSelectFilter,
|
|
35
|
-
SelectSort: TableSelectSort,
|
|
36
|
-
ActionButton: TableActionButton,
|
|
37
|
-
Menu: TableMenu,
|
|
38
|
-
SelectionActions: TableSelectionActions,
|
|
39
|
-
SelectionAction: TableSelectionAction,
|
|
40
|
-
Actions: TableActions
|
|
41
|
-
})
|