@dxos/react-ui-table 0.4.9 → 0.4.10-main.05b9ab6
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/lib/browser/index.mjs +786 -367
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/ColumnMenu/ColumnMenu.d.ts +19 -0
- package/dist/types/src/components/ColumnMenu/ColumnMenu.d.ts.map +1 -0
- package/dist/types/src/components/{ColumnMenu.stories.d.ts → ColumnMenu/ColumnMenu.stories.d.ts} +10 -2
- package/dist/types/src/components/ColumnMenu/ColumnMenu.stories.d.ts.map +1 -0
- package/dist/types/src/components/ColumnMenu/ColumnSettingsForm.d.ts +11 -0
- package/dist/types/src/components/ColumnMenu/ColumnSettingsForm.d.ts.map +1 -0
- package/dist/types/src/components/ColumnMenu/index.d.ts +3 -0
- package/dist/types/src/components/ColumnMenu/index.d.ts.map +1 -0
- package/dist/types/src/components/Table/Table.d.ts +17 -4
- package/dist/types/src/components/Table/Table.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts +35 -1
- package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/TableBody.d.ts.map +1 -1
- package/dist/types/src/components/Table/TableRootContext.d.ts +17 -0
- package/dist/types/src/components/Table/TableRootContext.d.ts.map +1 -0
- package/dist/types/src/components/Table/index.d.ts +1 -0
- package/dist/types/src/components/Table/index.d.ts.map +1 -1
- package/dist/types/src/components/Table/props.d.ts +2 -3
- package/dist/types/src/components/Table/props.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/helpers.d.ts +4 -0
- package/dist/types/src/helpers.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +5 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -0
- package/dist/types/src/hooks/useColumnSizing.d.ts +12 -0
- package/dist/types/src/hooks/useColumnSizing.d.ts.map +1 -0
- package/dist/types/src/hooks/useColumnSorting.d.ts +9 -0
- package/dist/types/src/hooks/useColumnSorting.d.ts.map +1 -0
- package/dist/types/src/hooks/usePinLastRow.d.ts +3 -0
- package/dist/types/src/hooks/usePinLastRow.d.ts.map +1 -0
- package/dist/types/src/hooks/useRowSelection.d.ts +7 -0
- package/dist/types/src/hooks/useRowSelection.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +2 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/schema/SchemaToTable.stories.d.ts +11 -0
- package/dist/types/src/schema/SchemaToTable.stories.d.ts.map +1 -0
- package/dist/types/src/schema/index.d.ts +3 -0
- package/dist/types/src/schema/index.d.ts.map +1 -0
- package/dist/types/src/schema/schema.d.ts +5 -0
- package/dist/types/src/schema/schema.d.ts.map +1 -0
- package/dist/types/src/schema/schema.test.d.ts +2 -0
- package/dist/types/src/schema/schema.test.d.ts.map +1 -0
- package/dist/types/src/schema/schemaToColumns.d.ts +4 -0
- package/dist/types/src/schema/schemaToColumns.d.ts.map +1 -0
- package/dist/types/src/{schema.d.ts → schema/types.d.ts} +1 -1
- package/dist/types/src/schema/types.d.ts.map +1 -0
- package/dist/types/src/theme.d.ts +1 -0
- package/dist/types/src/theme.d.ts.map +1 -1
- package/package.json +22 -16
- package/src/components/ColumnMenu/ColumnMenu.stories.tsx +127 -0
- package/src/components/ColumnMenu/ColumnMenu.tsx +168 -0
- package/src/components/ColumnMenu/ColumnSettingsForm.tsx +214 -0
- package/src/components/ColumnMenu/index.ts +6 -0
- package/src/components/Table/Table.stories.tsx +260 -59
- package/src/components/Table/Table.tsx +82 -107
- package/src/components/Table/TableBody.tsx +12 -2
- package/src/components/Table/TableRootContext.ts +39 -0
- package/src/components/Table/index.ts +1 -0
- package/src/components/Table/props.ts +17 -24
- package/src/components/index.ts +1 -1
- package/src/helpers.tsx +32 -8
- package/src/hooks/index.ts +8 -0
- package/src/hooks/useColumnSizing.ts +45 -0
- package/src/hooks/useColumnSorting.ts +54 -0
- package/src/hooks/usePinLastRow.ts +64 -0
- package/src/hooks/useRowSelection.ts +39 -0
- package/src/index.ts +3 -1
- package/src/schema/SchemaToTable.stories.tsx +71 -0
- package/src/schema/index.ts +6 -0
- package/src/schema/schema.test.ts +148 -0
- package/src/schema/schema.ts +92 -0
- package/src/schema/schemaToColumns.ts +48 -0
- package/src/theme.ts +3 -2
- package/dist/types/src/components/ColumnMenu.d.ts +0 -13
- package/dist/types/src/components/ColumnMenu.d.ts.map +0 -1
- package/dist/types/src/components/ColumnMenu.stories.d.ts.map +0 -1
- package/dist/types/src/components/SortButton.d.ts +0 -8
- package/dist/types/src/components/SortButton.d.ts.map +0 -1
- package/dist/types/src/schema.d.ts.map +0 -1
- package/src/components/ColumnMenu.stories.tsx +0 -46
- package/src/components/ColumnMenu.tsx +0 -248
- package/src/components/SortButton.tsx +0 -34
- /package/src/{schema.ts → schema/types.ts} +0 -0
|
@@ -5,12 +5,13 @@
|
|
|
5
5
|
import '@dxosTheme';
|
|
6
6
|
|
|
7
7
|
import { Plugs, PlugsConnected } from '@phosphor-icons/react';
|
|
8
|
-
import React, { useCallback, useEffect, useMemo,
|
|
8
|
+
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
9
9
|
|
|
10
|
-
import
|
|
10
|
+
import { create } from '@dxos/echo-schema';
|
|
11
|
+
import { registerSignalRuntime } from '@dxos/echo-signals/react';
|
|
11
12
|
import { PublicKey } from '@dxos/keys';
|
|
12
13
|
import { faker } from '@dxos/random';
|
|
13
|
-
import {
|
|
14
|
+
import { Button, DensityProvider } from '@dxos/react-ui';
|
|
14
15
|
import { withTheme } from '@dxos/storybook-utils';
|
|
15
16
|
import { range } from '@dxos/util';
|
|
16
17
|
|
|
@@ -35,7 +36,7 @@ faker.seed(911);
|
|
|
35
36
|
const createItems = (count: number) =>
|
|
36
37
|
range(count).map(
|
|
37
38
|
() =>
|
|
38
|
-
|
|
39
|
+
create<Item>({
|
|
39
40
|
publicKey: PublicKey.random(),
|
|
40
41
|
name: faker.commerce.productName(),
|
|
41
42
|
count: faker.datatype.boolean({ probability: 0.9 }) ? faker.number.int({ min: 0, max: 10_000 }) : undefined,
|
|
@@ -115,9 +116,19 @@ const makeColumns = (onUpdate?: ValueUpdater<Item, any>): TableColumnDef<Item, a
|
|
|
115
116
|
// Tests
|
|
116
117
|
//
|
|
117
118
|
|
|
119
|
+
const MinimalTable = (props: any) => {
|
|
120
|
+
return (
|
|
121
|
+
<Table.Root>
|
|
122
|
+
<Table.Viewport classNames='fixed inset-0 overflow-auto'>
|
|
123
|
+
<Table.Table<any> {...props} />
|
|
124
|
+
</Table.Viewport>
|
|
125
|
+
</Table.Root>
|
|
126
|
+
);
|
|
127
|
+
};
|
|
128
|
+
|
|
118
129
|
export default {
|
|
119
130
|
title: 'react-ui-table/Table',
|
|
120
|
-
component:
|
|
131
|
+
component: MinimalTable,
|
|
121
132
|
args: {
|
|
122
133
|
header: true,
|
|
123
134
|
keyAccessor: (item: Item) => item.publicKey.toHex(),
|
|
@@ -186,7 +197,6 @@ export const Empty = {
|
|
|
186
197
|
|
|
187
198
|
export const Dynamic = {
|
|
188
199
|
render: () => {
|
|
189
|
-
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
190
200
|
const [items, setItems] = useState<Item[]>(createItems(50));
|
|
191
201
|
|
|
192
202
|
useEffect(() => {
|
|
@@ -204,26 +214,27 @@ export const Dynamic = {
|
|
|
204
214
|
const columns = useMemo(() => makeColumns(), []);
|
|
205
215
|
|
|
206
216
|
return (
|
|
207
|
-
<
|
|
208
|
-
<Table
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
217
|
+
<Table.Root>
|
|
218
|
+
<Table.Viewport classNames='fixed inset-0 overflow-auto'>
|
|
219
|
+
<Table.Table<Item>
|
|
220
|
+
role='grid'
|
|
221
|
+
rowsSelectable='multi'
|
|
222
|
+
keyAccessor={(row) => row.publicKey.toHex()}
|
|
223
|
+
columns={columns}
|
|
224
|
+
data={items}
|
|
225
|
+
fullWidth
|
|
226
|
+
stickyHeader
|
|
227
|
+
border
|
|
228
|
+
pinLastRow
|
|
229
|
+
/>
|
|
230
|
+
</Table.Viewport>
|
|
231
|
+
</Table.Root>
|
|
220
232
|
);
|
|
221
233
|
},
|
|
222
234
|
};
|
|
223
235
|
|
|
224
236
|
export const Editable = {
|
|
225
237
|
render: () => {
|
|
226
|
-
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
227
238
|
const [items, setItems] = useState<Item[]>(createItems(200));
|
|
228
239
|
|
|
229
240
|
const onUpdate: ValueUpdater<Item, any> = useCallback(
|
|
@@ -234,18 +245,106 @@ export const Editable = {
|
|
|
234
245
|
const columns = useMemo(() => makeColumns(onUpdate), [onUpdate]);
|
|
235
246
|
|
|
236
247
|
return (
|
|
237
|
-
<
|
|
238
|
-
<Table
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
248
|
+
<Table.Root>
|
|
249
|
+
<Table.Viewport classNames='fixed inset-0 overflow-auto'>
|
|
250
|
+
<Table.Table<Item>
|
|
251
|
+
role='grid'
|
|
252
|
+
rowsSelectable='multi'
|
|
253
|
+
keyAccessor={(row) => row.publicKey.toHex()}
|
|
254
|
+
columns={columns}
|
|
255
|
+
data={items}
|
|
256
|
+
fullWidth
|
|
257
|
+
stickyHeader
|
|
258
|
+
border
|
|
259
|
+
pinLastRow
|
|
260
|
+
/>
|
|
261
|
+
</Table.Viewport>
|
|
262
|
+
</Table.Root>
|
|
263
|
+
);
|
|
264
|
+
},
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
export const PinnedLastRow = {
|
|
268
|
+
render: () => {
|
|
269
|
+
const [items, setItems] = useState<Item[]>(createItems(200));
|
|
270
|
+
|
|
271
|
+
const onUpdate: ValueUpdater<Item, any> = useCallback(
|
|
272
|
+
(item, prop, value) => setItems((items) => updateItems(items, item.publicKey, prop, value)),
|
|
273
|
+
[setItems],
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
const columns = useMemo(() => makeColumns(onUpdate), [onUpdate]);
|
|
277
|
+
|
|
278
|
+
return (
|
|
279
|
+
<Table.Root>
|
|
280
|
+
<Table.Viewport classNames='fixed inset-0 overflow-auto'>
|
|
281
|
+
<Table.Table<Item>
|
|
282
|
+
role='grid'
|
|
283
|
+
rowsSelectable='multi'
|
|
284
|
+
keyAccessor={(row) => row.publicKey.toHex()}
|
|
285
|
+
columns={columns}
|
|
286
|
+
data={items}
|
|
287
|
+
fullWidth
|
|
288
|
+
stickyHeader
|
|
289
|
+
border
|
|
290
|
+
pinLastRow
|
|
291
|
+
/>
|
|
292
|
+
</Table.Viewport>
|
|
293
|
+
</Table.Root>
|
|
294
|
+
);
|
|
295
|
+
},
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
export const InsertDelete = {
|
|
299
|
+
render: () => {
|
|
300
|
+
const [items, setItems] = useState<Item[]>(createItems(10));
|
|
301
|
+
|
|
302
|
+
const onUpdate: ValueUpdater<Item, any> = useCallback(
|
|
303
|
+
(item, prop, value) => setItems((items) => updateItems(items, item.publicKey, prop, value)),
|
|
304
|
+
[setItems],
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
const columns = useMemo(() => makeColumns(onUpdate), [onUpdate]);
|
|
308
|
+
|
|
309
|
+
const onInsertFirst = () => {
|
|
310
|
+
setItems((items) => [...createItems(1), ...items]);
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
const onInsertLast = () => {
|
|
314
|
+
setItems((items) => [...items, ...createItems(1)]);
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
const onDeleteFirst = () => {
|
|
318
|
+
setItems(([_first, ...rest]) => rest);
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
const onDeleteLast = () => {
|
|
322
|
+
setItems((items) => [...items.slice(0, items.length - 1)]);
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
return (
|
|
326
|
+
<div>
|
|
327
|
+
<div className='flex flex-row gap-2'>
|
|
328
|
+
<Button onClick={onInsertFirst}>Insert first</Button>
|
|
329
|
+
<Button onClick={onInsertLast}>Insert last</Button>
|
|
330
|
+
<Button onClick={onDeleteFirst}>Delete first</Button>
|
|
331
|
+
<Button onClick={onDeleteLast}>Delete last</Button>
|
|
332
|
+
</div>
|
|
333
|
+
<Table.Root>
|
|
334
|
+
<Table.Viewport classNames='fixed inset-0 overflow-auto'>
|
|
335
|
+
<Table.Table<Item>
|
|
336
|
+
role='grid'
|
|
337
|
+
rowsSelectable='multi'
|
|
338
|
+
keyAccessor={(row) => row.publicKey.toHex()}
|
|
339
|
+
columns={columns}
|
|
340
|
+
data={items}
|
|
341
|
+
fullWidth
|
|
342
|
+
stickyHeader
|
|
343
|
+
border
|
|
344
|
+
pinLastRow
|
|
345
|
+
/>
|
|
346
|
+
</Table.Viewport>
|
|
347
|
+
</Table.Root>
|
|
249
348
|
</div>
|
|
250
349
|
);
|
|
251
350
|
},
|
|
@@ -253,7 +352,6 @@ export const Editable = {
|
|
|
253
352
|
|
|
254
353
|
export const Resizable = {
|
|
255
354
|
render: () => {
|
|
256
|
-
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
257
355
|
const [items, setItems] = useState<Item[]>(createItems(10));
|
|
258
356
|
|
|
259
357
|
const onUpdate: ValueUpdater<Item, any> = useCallback(
|
|
@@ -262,25 +360,24 @@ export const Resizable = {
|
|
|
262
360
|
);
|
|
263
361
|
|
|
264
362
|
return (
|
|
265
|
-
<
|
|
266
|
-
<Table
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
</
|
|
363
|
+
<Table.Root>
|
|
364
|
+
<Table.Viewport classNames='fixed inset-0 overflow-auto'>
|
|
365
|
+
<Table.Table<Item>
|
|
366
|
+
rowsSelectable='multi'
|
|
367
|
+
keyAccessor={(row) => row.publicKey.toHex()}
|
|
368
|
+
columns={makeColumns(onUpdate)}
|
|
369
|
+
data={items}
|
|
370
|
+
fullWidth
|
|
371
|
+
stickyHeader
|
|
372
|
+
/>
|
|
373
|
+
</Table.Viewport>
|
|
374
|
+
</Table.Root>
|
|
277
375
|
);
|
|
278
376
|
},
|
|
279
377
|
};
|
|
280
378
|
|
|
281
379
|
export const TenThousandRows = {
|
|
282
380
|
render: () => {
|
|
283
|
-
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
284
381
|
const [items, setItems] = useState<Item[]>(createItems(10000));
|
|
285
382
|
|
|
286
383
|
const onUpdate: ValueUpdater<Item, any> = useCallback(
|
|
@@ -291,19 +388,123 @@ export const TenThousandRows = {
|
|
|
291
388
|
const columns = useMemo(() => makeColumns(onUpdate), [onUpdate]);
|
|
292
389
|
|
|
293
390
|
return (
|
|
294
|
-
<
|
|
295
|
-
<Table
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
391
|
+
<Table.Root>
|
|
392
|
+
<Table.Viewport classNames='fixed inset-0 overflow-auto'>
|
|
393
|
+
<Table.Table<Item>
|
|
394
|
+
role='grid'
|
|
395
|
+
rowsSelectable='multi'
|
|
396
|
+
keyAccessor={(row) => row.publicKey.toHex()}
|
|
397
|
+
columns={columns}
|
|
398
|
+
data={items}
|
|
399
|
+
fullWidth
|
|
400
|
+
stickyHeader
|
|
401
|
+
border
|
|
402
|
+
/>{' '}
|
|
403
|
+
</Table.Viewport>
|
|
404
|
+
</Table.Root>
|
|
405
|
+
);
|
|
406
|
+
},
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
registerSignalRuntime();
|
|
410
|
+
const state = create({ items: createItems(10) });
|
|
411
|
+
|
|
412
|
+
export const RealTimeUpdates = {
|
|
413
|
+
args: {
|
|
414
|
+
periodicMutations: true,
|
|
415
|
+
mutationInterval: 1000,
|
|
416
|
+
periodicDeletions: false,
|
|
417
|
+
deletionInterval: 5000,
|
|
418
|
+
periodicInsertions: false,
|
|
419
|
+
insertionInterval: 3000,
|
|
420
|
+
},
|
|
421
|
+
argTypes: {
|
|
422
|
+
mutationInterval: { control: 'number' },
|
|
423
|
+
periodicDeletions: { control: 'boolean' },
|
|
424
|
+
deletionInterval: { control: 'number' },
|
|
425
|
+
periodicInsertions: { control: 'boolean' },
|
|
426
|
+
insertionInterval: { control: 'number' },
|
|
427
|
+
},
|
|
428
|
+
render: ({
|
|
429
|
+
periodicMutations,
|
|
430
|
+
mutationInterval,
|
|
431
|
+
periodicDeletions,
|
|
432
|
+
deletionInterval,
|
|
433
|
+
periodicInsertions,
|
|
434
|
+
insertionInterval,
|
|
435
|
+
}: any) => {
|
|
436
|
+
useEffect(() => {
|
|
437
|
+
if (!periodicMutations) {
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
const interval = setInterval(() => {
|
|
442
|
+
if (state.items.length === 0) {
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const randomIndex = Math.floor(Math.random() * state.items.length);
|
|
447
|
+
console.log('Mutating row', randomIndex);
|
|
448
|
+
state.items[randomIndex].name = faker.commerce.productName();
|
|
449
|
+
state.items[randomIndex].count = Math.floor(Math.random() * 1000);
|
|
450
|
+
state.items[randomIndex].started = new Date();
|
|
451
|
+
}, mutationInterval);
|
|
452
|
+
|
|
453
|
+
return () => clearInterval(interval);
|
|
454
|
+
}, [periodicMutations, mutationInterval, state.items]);
|
|
455
|
+
|
|
456
|
+
useEffect(() => {
|
|
457
|
+
if (!periodicInsertions) {
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
const interval = setInterval(() => {
|
|
462
|
+
console.log('Inserting...');
|
|
463
|
+
state.items.push(createItems(1)[0]);
|
|
464
|
+
}, insertionInterval);
|
|
465
|
+
|
|
466
|
+
return () => clearInterval(interval);
|
|
467
|
+
}, [periodicInsertions, insertionInterval, state.items]);
|
|
468
|
+
|
|
469
|
+
useEffect(() => {
|
|
470
|
+
if (!periodicDeletions) {
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
const interval = setInterval(() => {
|
|
475
|
+
if (state.items.length === 0) {
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
console.log('Deleting');
|
|
480
|
+
|
|
481
|
+
// Randomly delete a row from state.items
|
|
482
|
+
const randomIndex = Math.floor(Math.random() * state.items.length);
|
|
483
|
+
state.items.splice(randomIndex, 1);
|
|
484
|
+
}, deletionInterval);
|
|
485
|
+
|
|
486
|
+
return () => clearInterval(interval);
|
|
487
|
+
}, [periodicDeletions, deletionInterval, state.items]);
|
|
488
|
+
|
|
489
|
+
const onUpdate = useCallback((...args: any[]) => {}, []);
|
|
490
|
+
const columns = useMemo(() => makeColumns(onUpdate), []);
|
|
491
|
+
|
|
492
|
+
return (
|
|
493
|
+
<Table.Root>
|
|
494
|
+
<Table.Viewport classNames='fixed inset-0 overflow-auto'>
|
|
495
|
+
<Table.Table<Item>
|
|
496
|
+
role='grid'
|
|
497
|
+
rowsSelectable='multi'
|
|
498
|
+
keyAccessor={(row) => row.publicKey.toHex()}
|
|
499
|
+
columns={columns}
|
|
500
|
+
data={state.items}
|
|
501
|
+
fullWidth
|
|
502
|
+
stickyHeader
|
|
503
|
+
border
|
|
504
|
+
pinLastRow
|
|
505
|
+
/>
|
|
506
|
+
</Table.Viewport>
|
|
507
|
+
</Table.Root>
|
|
307
508
|
);
|
|
308
509
|
},
|
|
309
510
|
};
|