@dxos/react-ui-table 0.6.13 → 0.6.14-main.1366248
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 +74 -156
- 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 +6 -3
- package/dist/types/src/components/ColumnMenu/ColumnMenu.d.ts.map +1 -1
- package/dist/types/src/components/ColumnMenu/ColumnMenu.stories.d.ts +3 -3
- package/dist/types/src/components/ColumnMenu/ColumnMenu.stories.d.ts.map +1 -1
- package/dist/types/src/components/ColumnMenu/ColumnSettings.d.ts +15 -0
- package/dist/types/src/components/ColumnMenu/ColumnSettings.d.ts.map +1 -0
- package/dist/types/src/components/ColumnMenu/ColumnSettings.stories.d.ts +84 -0
- package/dist/types/src/components/ColumnMenu/ColumnSettings.stories.d.ts.map +1 -0
- package/dist/types/src/components/ColumnMenu/index.d.ts +1 -1
- package/dist/types/src/components/ColumnMenu/index.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts +9 -27
- package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/TableContext.d.ts +2 -4
- package/dist/types/src/components/Table/TableContext.d.ts.map +1 -1
- package/dist/types/src/components/Table/TableHead.d.ts.map +1 -1
- package/dist/types/src/components/Table/index.d.ts +2 -1
- package/dist/types/src/components/Table/index.d.ts.map +1 -1
- package/dist/types/src/helpers.d.ts +1 -1
- package/dist/types/src/helpers.d.ts.map +1 -1
- package/dist/types/src/hooks/useRowSelection.d.ts.map +1 -1
- package/dist/types/src/schema/{SchemaToTable.stories.d.ts → Schema.stories.d.ts} +2 -3
- package/dist/types/src/schema/Schema.stories.d.ts.map +1 -0
- package/dist/types/src/schema/{schemaToColumns.d.ts → column-utils.d.ts} +5 -2
- package/dist/types/src/schema/column-utils.d.ts.map +1 -0
- package/dist/types/src/schema/index.d.ts +1 -1
- package/dist/types/src/schema/index.d.ts.map +1 -1
- package/dist/types/src/schema/types.d.ts +11 -4
- package/dist/types/src/schema/types.d.ts.map +1 -1
- package/package.json +25 -22
- package/src/components/ColumnMenu/ColumnMenu.stories.tsx +14 -13
- package/src/components/ColumnMenu/ColumnMenu.tsx +8 -5
- package/src/components/ColumnMenu/{ColumnSettingsForm.stories.tsx → ColumnSettings.stories.tsx} +27 -23
- package/src/components/ColumnMenu/{ColumnSettingsForm.tsx → ColumnSettings.tsx} +44 -43
- package/src/components/ColumnMenu/index.ts +1 -1
- package/src/components/Table/Table.stories.tsx +93 -95
- package/src/components/Table/Table.tsx +10 -15
- package/src/components/Table/TableContext.tsx +13 -7
- package/src/components/Table/TableHead.tsx +0 -1
- package/src/components/Table/index.ts +2 -1
- package/src/components/Table/props.ts +4 -4
- package/src/helpers.tsx +4 -6
- package/src/hooks/useRowSelection.ts +1 -0
- package/src/schema/{SchemaToTable.stories.tsx → Schema.stories.tsx} +11 -23
- package/src/schema/column-utils.ts +54 -0
- package/src/schema/index.ts +1 -1
- package/src/schema/types.ts +15 -6
- package/src/translations.ts +1 -1
- package/dist/types/src/components/ColumnMenu/ColumnSettingsForm.d.ts +0 -12
- package/dist/types/src/components/ColumnMenu/ColumnSettingsForm.d.ts.map +0 -1
- package/dist/types/src/components/ColumnMenu/ColumnSettingsForm.stories.d.ts +0 -63
- package/dist/types/src/components/ColumnMenu/ColumnSettingsForm.stories.d.ts.map +0 -1
- package/dist/types/src/schema/SchemaToTable.stories.d.ts.map +0 -1
- package/dist/types/src/schema/schema.d.ts +0 -5
- package/dist/types/src/schema/schema.d.ts.map +0 -1
- package/dist/types/src/schema/schema.test.d.ts +0 -2
- package/dist/types/src/schema/schema.test.d.ts.map +0 -1
- package/dist/types/src/schema/schemaToColumns.d.ts.map +0 -1
- package/src/schema/schema.test.ts +0 -148
- package/src/schema/schema.ts +0 -93
- package/src/schema/schemaToColumns.ts +0 -48
|
@@ -5,14 +5,15 @@
|
|
|
5
5
|
import '@dxos-theme';
|
|
6
6
|
|
|
7
7
|
import { Plugs, PlugsConnected } from '@phosphor-icons/react';
|
|
8
|
+
import { type StoryObj } from '@storybook/react';
|
|
8
9
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
9
10
|
|
|
10
11
|
import { create } from '@dxos/echo-schema';
|
|
11
|
-
import { registerSignalRuntime } from '@dxos/echo-signals/react';
|
|
12
12
|
import { PublicKey } from '@dxos/keys';
|
|
13
|
+
import { log } from '@dxos/log';
|
|
13
14
|
import { faker } from '@dxos/random';
|
|
14
|
-
import { Button
|
|
15
|
-
import { withTheme } from '@dxos/storybook-utils';
|
|
15
|
+
import { Button } from '@dxos/react-ui';
|
|
16
|
+
import { withSignals, withTheme } from '@dxos/storybook-utils';
|
|
16
17
|
import { range } from '@dxos/util';
|
|
17
18
|
|
|
18
19
|
import { Table } from './Table';
|
|
@@ -127,7 +128,7 @@ const MinimalTable = (props: any) => {
|
|
|
127
128
|
};
|
|
128
129
|
|
|
129
130
|
export default {
|
|
130
|
-
title: 'react-ui-table/Table',
|
|
131
|
+
title: 'ui/react-ui-table/Table',
|
|
131
132
|
component: MinimalTable,
|
|
132
133
|
args: {
|
|
133
134
|
header: true,
|
|
@@ -157,14 +158,7 @@ export default {
|
|
|
157
158
|
},
|
|
158
159
|
rowsSelectable: { control: 'select', options: [false, true, 'multi'] },
|
|
159
160
|
},
|
|
160
|
-
decorators: [
|
|
161
|
-
withTheme,
|
|
162
|
-
(Story: any) => (
|
|
163
|
-
<DensityProvider density='fine'>
|
|
164
|
-
<Story />
|
|
165
|
-
</DensityProvider>
|
|
166
|
-
),
|
|
167
|
-
],
|
|
161
|
+
decorators: [withTheme],
|
|
168
162
|
};
|
|
169
163
|
|
|
170
164
|
export const Default = {
|
|
@@ -406,105 +400,109 @@ export const TenThousandRows = {
|
|
|
406
400
|
},
|
|
407
401
|
};
|
|
408
402
|
|
|
409
|
-
|
|
410
|
-
const state = create({ items: createItems(10) });
|
|
403
|
+
// TODO(burdon): Warning: Encountered two children with the same key.
|
|
411
404
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
if (
|
|
405
|
+
type StoryProps = {
|
|
406
|
+
periodicMutations: boolean;
|
|
407
|
+
mutationInterval: number;
|
|
408
|
+
periodicDeletions: boolean;
|
|
409
|
+
deletionInterval: number;
|
|
410
|
+
periodicInsertions: boolean;
|
|
411
|
+
insertionInterval: number;
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
const DefaultStory = ({
|
|
415
|
+
periodicMutations,
|
|
416
|
+
mutationInterval,
|
|
417
|
+
periodicDeletions,
|
|
418
|
+
deletionInterval,
|
|
419
|
+
periodicInsertions,
|
|
420
|
+
insertionInterval,
|
|
421
|
+
}: StoryProps) => {
|
|
422
|
+
const [state] = useState(() => create({ items: createItems(10) }));
|
|
423
|
+
|
|
424
|
+
useEffect(() => {
|
|
425
|
+
if (!periodicMutations) {
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
const i = setInterval(() => {
|
|
430
|
+
if (state.items.length === 0) {
|
|
438
431
|
return;
|
|
439
432
|
}
|
|
440
433
|
|
|
441
|
-
const
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
434
|
+
const idx = Math.floor(Math.random() * state.items.length);
|
|
435
|
+
log('mutating', { idx });
|
|
436
|
+
state.items[idx].name = faker.commerce.productName();
|
|
437
|
+
state.items[idx].count = Math.floor(Math.random() * 1000);
|
|
438
|
+
state.items[idx].started = new Date();
|
|
439
|
+
}, mutationInterval);
|
|
445
440
|
|
|
446
|
-
|
|
447
|
-
|
|
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);
|
|
441
|
+
return () => clearInterval(i);
|
|
442
|
+
}, [periodicMutations, mutationInterval, state.items]);
|
|
452
443
|
|
|
453
|
-
|
|
454
|
-
|
|
444
|
+
useEffect(() => {
|
|
445
|
+
if (!periodicInsertions) {
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
455
448
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
449
|
+
const i = setInterval(() => {
|
|
450
|
+
log('inserting...');
|
|
451
|
+
state.items.push(createItems(1)[0]);
|
|
452
|
+
}, insertionInterval);
|
|
460
453
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
state.items.push(createItems(1)[0]);
|
|
464
|
-
}, insertionInterval);
|
|
454
|
+
return () => clearInterval(i);
|
|
455
|
+
}, [periodicInsertions, insertionInterval, state.items]);
|
|
465
456
|
|
|
466
|
-
|
|
467
|
-
|
|
457
|
+
useEffect(() => {
|
|
458
|
+
if (!periodicDeletions) {
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
468
461
|
|
|
469
|
-
|
|
470
|
-
if (
|
|
462
|
+
const i = setInterval(() => {
|
|
463
|
+
if (state.items.length === 0) {
|
|
471
464
|
return;
|
|
472
465
|
}
|
|
473
466
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
console.log('Deleting');
|
|
467
|
+
log('deleting...');
|
|
468
|
+
const randomIndex = Math.floor(Math.random() * state.items.length);
|
|
469
|
+
state.items.splice(randomIndex, 1);
|
|
470
|
+
}, deletionInterval);
|
|
480
471
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
state.items.splice(randomIndex, 1);
|
|
484
|
-
}, deletionInterval);
|
|
472
|
+
return () => clearInterval(i);
|
|
473
|
+
}, [periodicDeletions, deletionInterval, state.items]);
|
|
485
474
|
|
|
486
|
-
|
|
487
|
-
|
|
475
|
+
const onUpdate = useCallback((...args: any[]) => {}, []);
|
|
476
|
+
const columns = useMemo(() => makeColumns(onUpdate), []);
|
|
488
477
|
|
|
489
|
-
|
|
490
|
-
|
|
478
|
+
return (
|
|
479
|
+
<Table.Root>
|
|
480
|
+
<Table.Viewport classNames='fixed inset-0'>
|
|
481
|
+
<Table.Main<Item>
|
|
482
|
+
role='grid'
|
|
483
|
+
rowsSelectable='multi'
|
|
484
|
+
keyAccessor={(row) => row.publicKey.toHex()}
|
|
485
|
+
columns={columns}
|
|
486
|
+
data={state.items}
|
|
487
|
+
fullWidth
|
|
488
|
+
stickyHeader
|
|
489
|
+
border
|
|
490
|
+
pinLastRow
|
|
491
|
+
/>
|
|
492
|
+
</Table.Viewport>
|
|
493
|
+
</Table.Root>
|
|
494
|
+
);
|
|
495
|
+
};
|
|
491
496
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
stickyHeader
|
|
503
|
-
border
|
|
504
|
-
pinLastRow
|
|
505
|
-
/>
|
|
506
|
-
</Table.Viewport>
|
|
507
|
-
</Table.Root>
|
|
508
|
-
);
|
|
497
|
+
export const RealTimeUpdates: StoryObj<StoryProps> = {
|
|
498
|
+
render: DefaultStory,
|
|
499
|
+
decorators: [withSignals],
|
|
500
|
+
args: {
|
|
501
|
+
periodicMutations: true,
|
|
502
|
+
mutationInterval: 1000,
|
|
503
|
+
periodicDeletions: false,
|
|
504
|
+
deletionInterval: 5000,
|
|
505
|
+
periodicInsertions: false,
|
|
506
|
+
insertionInterval: 3000,
|
|
509
507
|
},
|
|
510
508
|
};
|
|
@@ -16,16 +16,16 @@ import {
|
|
|
16
16
|
} from '@tanstack/react-table';
|
|
17
17
|
import React, {
|
|
18
18
|
type ComponentPropsWithoutRef,
|
|
19
|
+
type ReactNode,
|
|
19
20
|
Fragment,
|
|
21
|
+
memo,
|
|
20
22
|
useCallback,
|
|
21
23
|
useEffect,
|
|
22
24
|
useState,
|
|
23
25
|
useContext,
|
|
24
|
-
type ReactNode,
|
|
25
|
-
memo,
|
|
26
26
|
} from 'react';
|
|
27
27
|
|
|
28
|
-
import {
|
|
28
|
+
import { type ThemedClassName, useDefaultValue } from '@dxos/react-ui';
|
|
29
29
|
import { mx } from '@dxos/react-ui-theme';
|
|
30
30
|
|
|
31
31
|
import { TableBody } from './TableBody';
|
|
@@ -40,11 +40,7 @@ type TableRootProps = { children: ReactNode };
|
|
|
40
40
|
|
|
41
41
|
const TableRoot = ({ children }: TableRootProps) => {
|
|
42
42
|
const contextValue = useTableRootContext();
|
|
43
|
-
return
|
|
44
|
-
<TableRootContext.Provider value={contextValue}>
|
|
45
|
-
<DensityProvider density='fine'>{children}</DensityProvider>
|
|
46
|
-
</TableRootContext.Provider>
|
|
47
|
-
);
|
|
43
|
+
return <TableRootContext.Provider value={contextValue}>{children}</TableRootContext.Provider>;
|
|
48
44
|
};
|
|
49
45
|
|
|
50
46
|
type TableViewportProps = ThemedClassName<ComponentPropsWithoutRef<typeof Primitive.div>> & {
|
|
@@ -55,7 +51,6 @@ const TableViewport = ({ children, classNames, asChild, ...props }: TableViewpor
|
|
|
55
51
|
const { scrollContextRef } = useContext(TableRootContext);
|
|
56
52
|
|
|
57
53
|
const classes = mx(classNames, 'overflow-auto');
|
|
58
|
-
|
|
59
54
|
return asChild ? (
|
|
60
55
|
<Slot ref={scrollContextRef} className={classes} {...props}>
|
|
61
56
|
{children}
|
|
@@ -70,17 +65,17 @@ const TableViewport = ({ children, classNames, asChild, ...props }: TableViewpor
|
|
|
70
65
|
export const TablePrimitive = <TData extends RowData>(props: TableProps<TData>) => {
|
|
71
66
|
const {
|
|
72
67
|
role,
|
|
73
|
-
onColumnResize,
|
|
74
|
-
columnVisibility,
|
|
75
68
|
header = true,
|
|
76
69
|
rowsSelectable,
|
|
77
70
|
debug,
|
|
78
|
-
onDataSelectionChange,
|
|
79
71
|
pinLastRow,
|
|
72
|
+
columnVisibility,
|
|
73
|
+
onColumnResize,
|
|
74
|
+
onDataSelectionChange,
|
|
80
75
|
} = props;
|
|
81
76
|
|
|
82
|
-
const columns = useDefaultValue(props.columns, []);
|
|
83
|
-
const incomingData = useDefaultValue(props.data, []);
|
|
77
|
+
const columns = useDefaultValue(props.columns, () => []);
|
|
78
|
+
const incomingData = useDefaultValue(props.data, () => []);
|
|
84
79
|
|
|
85
80
|
const [data, setData] = useState([...incomingData]);
|
|
86
81
|
|
|
@@ -110,7 +105,7 @@ export const TablePrimitive = <TData extends RowData>(props: TableProps<TData>)
|
|
|
110
105
|
// Columns
|
|
111
106
|
columns,
|
|
112
107
|
defaultColumn: {
|
|
113
|
-
size:
|
|
108
|
+
size: 400, // Required in order remove default width.
|
|
114
109
|
maxSize: 1024,
|
|
115
110
|
},
|
|
116
111
|
|
|
@@ -3,26 +3,32 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { type RowData } from '@tanstack/react-table';
|
|
6
|
-
import React, {
|
|
6
|
+
import React, {
|
|
7
|
+
useContext,
|
|
8
|
+
createContext,
|
|
9
|
+
type Context,
|
|
10
|
+
type JSX,
|
|
11
|
+
type PropsWithChildren,
|
|
12
|
+
type ReactNode,
|
|
13
|
+
} from 'react';
|
|
14
|
+
|
|
15
|
+
import { raise } from '@dxos/debug';
|
|
7
16
|
|
|
8
17
|
import { type TableContextValue } from './props';
|
|
9
18
|
|
|
10
19
|
export const TABLE_NAME = 'Table';
|
|
11
20
|
|
|
12
|
-
|
|
13
|
-
// The expectation is that the provider will always supply a value, so no need to define a default here.
|
|
14
|
-
const TableContext = createContext<TableContextValue<RowData>>({} as TableContextValue<RowData>);
|
|
21
|
+
const TableContext = createContext<TableContextValue<RowData> | undefined>(undefined);
|
|
15
22
|
|
|
16
23
|
export type TypedTableProvider<TData extends RowData> = {
|
|
17
24
|
(props: TableContextValue<TData> & { children: ReactNode }): JSX.Element;
|
|
18
25
|
displayName: string;
|
|
19
26
|
};
|
|
20
27
|
|
|
21
|
-
export const TableProvider
|
|
28
|
+
export const TableProvider = ({ children, ...value }: PropsWithChildren<TableContextValue<RowData>>) => {
|
|
22
29
|
return <TableContext.Provider value={value}>{children}</TableContext.Provider>;
|
|
23
30
|
};
|
|
24
31
|
|
|
25
|
-
// Create a custom hook to consume the context.
|
|
26
32
|
export const useTableContext = <TData extends RowData>(): TableContextValue<TData> => {
|
|
27
|
-
return useContext(TableContext as Context<TableContextValue<TData>>);
|
|
33
|
+
return useContext(TableContext as Context<TableContextValue<TData>>) ?? raise(new Error('Missing TableContext'));
|
|
28
34
|
};
|
|
@@ -25,7 +25,7 @@ export type TableFlags = Partial<{
|
|
|
25
25
|
* This is ‘current’ in the `aria-current` sense.
|
|
26
26
|
*/
|
|
27
27
|
export type TableCurrent<TData extends RowData> = Partial<{
|
|
28
|
-
// App state
|
|
28
|
+
// App state.
|
|
29
29
|
currentDatum: TData;
|
|
30
30
|
onDatumClick: (datum: TData) => void;
|
|
31
31
|
}>;
|
|
@@ -39,13 +39,13 @@ export type TableProps<TData extends RowData> = TableFlags &
|
|
|
39
39
|
onColumnResize: (state: Record<string, number>) => void;
|
|
40
40
|
onColumnReorder: (columnId: string, direction: 'left' | 'right') => void;
|
|
41
41
|
columnVisibility: VisibilityState;
|
|
42
|
-
// Controllable row selection
|
|
42
|
+
// Controllable row selection.
|
|
43
43
|
rowSelection: RowSelectionState;
|
|
44
44
|
defaultRowSelection: RowSelectionState;
|
|
45
45
|
onRowSelectionChange: (rowSelection: RowSelectionState) => void;
|
|
46
|
-
// Derived from row selection
|
|
46
|
+
// Derived from row selection.
|
|
47
47
|
onDataSelectionChange: (dataSelection: TData[]) => void;
|
|
48
|
-
// `table` element props
|
|
48
|
+
// `table` element props.
|
|
49
49
|
classNames: ClassNameValue;
|
|
50
50
|
pinLastRow: boolean;
|
|
51
51
|
}>;
|
package/src/helpers.tsx
CHANGED
|
@@ -21,8 +21,7 @@ import { log } from '@dxos/log';
|
|
|
21
21
|
import { type ClassNameValue, Input, Tooltip } from '@dxos/react-ui';
|
|
22
22
|
import { getSize, mx } from '@dxos/react-ui-theme';
|
|
23
23
|
|
|
24
|
-
import { CellCombobox } from './components';
|
|
25
|
-
import { useTableContext } from './components/Table/TableContext';
|
|
24
|
+
import { CellCombobox, useTableContext } from './components';
|
|
26
25
|
import { textPadding } from './theme';
|
|
27
26
|
|
|
28
27
|
export type ValueUpdater<TData extends RowData, TValue> = (row: TData, id: string, value: TValue) => void;
|
|
@@ -470,7 +469,7 @@ export class ColumnBuilder<TData extends RowData> {
|
|
|
470
469
|
size: 50,
|
|
471
470
|
minSize: 50,
|
|
472
471
|
header: (column) => label ?? column.header.id,
|
|
473
|
-
// TODO(zan): Implement sort algorithm
|
|
472
|
+
// TODO(zan): Implement sort algorithm.
|
|
474
473
|
enableSorting: true,
|
|
475
474
|
cell: SwitchBuilderCell,
|
|
476
475
|
...props,
|
|
@@ -486,7 +485,7 @@ export class ColumnBuilder<TData extends RowData> {
|
|
|
486
485
|
const IconOff = off?.Icon ?? X;
|
|
487
486
|
return {
|
|
488
487
|
size: size ?? 32,
|
|
489
|
-
// TODO(zan): Implement sort algorithm
|
|
488
|
+
// TODO(zan): Implement sort algorithm.
|
|
490
489
|
enableSorting: false,
|
|
491
490
|
header: (column) => <div className={'justify-center'}>{label ?? column.header.id}</div>,
|
|
492
491
|
cell: (cell) => {
|
|
@@ -506,14 +505,13 @@ export class ColumnBuilder<TData extends RowData> {
|
|
|
506
505
|
/**
|
|
507
506
|
* This display column type is for nested/unhandled data to appear as JSON.
|
|
508
507
|
*/
|
|
509
|
-
|
|
508
|
+
json({ label, classNames, ...props }: KeyColumnOptions<TData> = {}): Partial<ColumnDef<TData, PublicKey>> {
|
|
510
509
|
return {
|
|
511
510
|
size: 120,
|
|
512
511
|
minSize: 120,
|
|
513
512
|
header: (cell) => label ?? cell.header.id,
|
|
514
513
|
cell: (cell) => {
|
|
515
514
|
const value = cell.getValue();
|
|
516
|
-
|
|
517
515
|
return (
|
|
518
516
|
<div className='overflow-scroll'>
|
|
519
517
|
<code className='text-xs'>{JSON.stringify(value)}</code>
|
|
@@ -4,31 +4,22 @@
|
|
|
4
4
|
|
|
5
5
|
import '@dxos-theme';
|
|
6
6
|
|
|
7
|
-
import
|
|
7
|
+
import { Arbitrary } from '@effect/schema';
|
|
8
8
|
import * as fc from 'fast-check';
|
|
9
9
|
import React from 'react';
|
|
10
10
|
|
|
11
11
|
import { S } from '@dxos/echo-schema';
|
|
12
|
-
import {
|
|
13
|
-
import { withTheme } from '@dxos/storybook-utils';
|
|
12
|
+
import { withTheme, withLayout } from '@dxos/storybook-utils';
|
|
14
13
|
|
|
15
|
-
import { schemaToColumnDefs } from './
|
|
14
|
+
import { schemaToColumnDefs } from './column-utils';
|
|
16
15
|
import { Table } from '../components';
|
|
17
16
|
|
|
18
17
|
export default {
|
|
19
|
-
title: 'react-ui-table/
|
|
20
|
-
|
|
21
|
-
decorators: [
|
|
22
|
-
withTheme,
|
|
23
|
-
(Story: any) => (
|
|
24
|
-
<DensityProvider density='fine'>
|
|
25
|
-
<Story />
|
|
26
|
-
</DensityProvider>
|
|
27
|
-
),
|
|
28
|
-
],
|
|
18
|
+
title: 'ui/react-ui-table/Schema',
|
|
19
|
+
decorators: [withTheme, withLayout()],
|
|
29
20
|
};
|
|
30
21
|
|
|
31
|
-
const
|
|
22
|
+
const TestSchema = S.Struct({
|
|
32
23
|
field1: S.String,
|
|
33
24
|
field2: S.Number,
|
|
34
25
|
field3: S.Date,
|
|
@@ -41,20 +32,17 @@ const exampleSchema = S.Struct({
|
|
|
41
32
|
),
|
|
42
33
|
});
|
|
43
34
|
|
|
44
|
-
type
|
|
35
|
+
type TestType = S.Schema.Type<typeof TestSchema>;
|
|
45
36
|
|
|
46
|
-
const columns = schemaToColumnDefs(
|
|
37
|
+
const columns = schemaToColumnDefs(TestSchema);
|
|
38
|
+
const items = fc.sample(Arbitrary.make(TestSchema), 10);
|
|
47
39
|
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
const items = fc.sample(exampleSchemaArbitrary, 10);
|
|
51
|
-
|
|
52
|
-
export const SchemaTable = {
|
|
40
|
+
export const Default = {
|
|
53
41
|
render: () => {
|
|
54
42
|
return (
|
|
55
43
|
<Table.Root>
|
|
56
44
|
<Table.Viewport classNames='fixed inset-0'>
|
|
57
|
-
<Table.Main<
|
|
45
|
+
<Table.Main<TestType>
|
|
58
46
|
role='grid'
|
|
59
47
|
rowsSelectable='multi'
|
|
60
48
|
keyAccessor={(row) => JSON.stringify(row)}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type ColumnDef } from '@tanstack/react-table';
|
|
6
|
+
|
|
7
|
+
import { TypeEnum, type S } from '@dxos/echo-schema';
|
|
8
|
+
import { FormatEnum } from '@dxos/echo-schema';
|
|
9
|
+
import { mapSchemaToFields } from '@dxos/schema';
|
|
10
|
+
|
|
11
|
+
import { createColumnBuilder } from '../helpers';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @deprecated
|
|
15
|
+
*/
|
|
16
|
+
export const schemaToColumnDefs = <T>(schema: S.Schema<T, any>): ColumnDef<T, any>[] => {
|
|
17
|
+
const { helper, builder } = createColumnBuilder<T>();
|
|
18
|
+
|
|
19
|
+
return mapSchemaToFields(schema).map(({ property, type, format }) => {
|
|
20
|
+
const propertyKey = property.toString();
|
|
21
|
+
|
|
22
|
+
if (!format) {
|
|
23
|
+
switch (type) {
|
|
24
|
+
case TypeEnum.String: {
|
|
25
|
+
return helper.accessor(
|
|
26
|
+
propertyKey as any,
|
|
27
|
+
builder.string({ label: propertyKey, classNames: [property === 'id' && 'font-mono'] }),
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
case TypeEnum.Number: {
|
|
31
|
+
return helper.accessor(propertyKey as any, builder.number({ label: propertyKey }));
|
|
32
|
+
}
|
|
33
|
+
case TypeEnum.Boolean: {
|
|
34
|
+
return helper.accessor(propertyKey as any, builder.switch({ label: propertyKey }));
|
|
35
|
+
}
|
|
36
|
+
default: {
|
|
37
|
+
throw new Error(`Unhandled scalar type: ${type}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
switch (format) {
|
|
43
|
+
case FormatEnum.Date: {
|
|
44
|
+
return helper.accessor(propertyKey as any, builder.date({ label: propertyKey }));
|
|
45
|
+
}
|
|
46
|
+
case FormatEnum.JSON: {
|
|
47
|
+
return helper.accessor(propertyKey as any, builder.json({ label: propertyKey, id: propertyKey }));
|
|
48
|
+
}
|
|
49
|
+
default: {
|
|
50
|
+
throw new Error(`Unhandled format: ${format}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
};
|
package/src/schema/index.ts
CHANGED
package/src/schema/types.ts
CHANGED
|
@@ -2,18 +2,27 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { type TypeEnum, type FormatEnum } from '@dxos/echo-schema';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @deprecated
|
|
9
|
+
*/
|
|
10
|
+
// TODO(burdon): Reconcile with @dxos/schema/View.
|
|
5
11
|
export type TableDef = {
|
|
6
12
|
id: string;
|
|
7
|
-
name?: string;
|
|
8
|
-
columns:
|
|
13
|
+
name?: string;
|
|
14
|
+
columns: ColumnDef[];
|
|
9
15
|
};
|
|
10
16
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated
|
|
19
|
+
*/
|
|
20
|
+
// TODO(burdon): Reconcile with @dxos/schema/Field.
|
|
21
|
+
export type ColumnDef = {
|
|
14
22
|
id: string;
|
|
15
23
|
prop: string;
|
|
16
|
-
type:
|
|
24
|
+
type: TypeEnum;
|
|
25
|
+
format?: FormatEnum;
|
|
17
26
|
size?: number;
|
|
18
27
|
label?: string;
|
|
19
28
|
|
package/src/translations.ts
CHANGED
|
@@ -10,7 +10,7 @@ export default [
|
|
|
10
10
|
[translationKey]: {
|
|
11
11
|
'no selection label': ' ',
|
|
12
12
|
'number column type label': 'Number',
|
|
13
|
-
'boolean column type label': '
|
|
13
|
+
'boolean column type label': 'Boolean',
|
|
14
14
|
'date column type label': 'Date',
|
|
15
15
|
'string column type label': 'Text',
|
|
16
16
|
'ref column type label': 'Reference',
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { type TableDef, type ColumnProps } from '../../schema';
|
|
3
|
-
export type ColumnSettingsFormProps = {
|
|
4
|
-
column: ColumnProps;
|
|
5
|
-
tableDef: TableDef;
|
|
6
|
-
tablesToReference: TableDef[];
|
|
7
|
-
onUpdate?: ((id: string, column: ColumnProps) => void) | undefined;
|
|
8
|
-
onDelete?: ((id: string) => void) | undefined;
|
|
9
|
-
onClose?: () => void;
|
|
10
|
-
};
|
|
11
|
-
export declare const ColumnSettingsForm: ({ column, tableDef, tablesToReference, onUpdate, onDelete, onClose, }: ColumnSettingsFormProps) => React.JSX.Element;
|
|
12
|
-
//# sourceMappingURL=ColumnSettingsForm.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ColumnSettingsForm.d.ts","sourceRoot":"","sources":["../../../../../src/components/ColumnMenu/ColumnSettingsForm.tsx"],"names":[],"mappings":"AAGA,OAAO,KAA2B,MAAM,OAAO,CAAC;AAKhD,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,WAAW,EAAmB,MAAM,cAAc,CAAC;AAGhF,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;IACnB,iBAAiB,EAAE,QAAQ,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACnE,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC9C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,CAAC;AAEF,eAAO,MAAM,kBAAkB,0EAO5B,uBAAuB,sBAkLzB,CAAC"}
|