@dxos/react-ui-table 0.6.13 → 0.6.14-main.7bd9c89
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 +45 -131
- 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} +2 -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 +10 -4
- package/dist/types/src/schema/types.d.ts.map +1 -1
- package/package.json +22 -20
- 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/{schemaToColumns.ts → column-utils.ts} +9 -9
- package/src/schema/index.ts +1 -1
- package/src/schema/types.ts +14 -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
|
@@ -7,39 +7,40 @@ import '@dxos-theme';
|
|
|
7
7
|
import { type SortDirection } from '@tanstack/react-table';
|
|
8
8
|
import React, { useState } from 'react';
|
|
9
9
|
|
|
10
|
+
import { FieldValueType } from '@dxos/schema';
|
|
10
11
|
import { withTheme } from '@dxos/storybook-utils';
|
|
11
12
|
|
|
12
13
|
import { ColumnMenu } from './ColumnMenu';
|
|
13
|
-
import { type
|
|
14
|
-
import { type
|
|
14
|
+
import { type ColumnSettingsProps } from './ColumnSettings';
|
|
15
|
+
import { type ColumnDef } from '../../schema';
|
|
15
16
|
|
|
16
17
|
export default {
|
|
17
|
-
title: 'react-ui-table/ColumnMenu',
|
|
18
|
+
title: 'ui/react-ui-table/ColumnMenu',
|
|
18
19
|
component: ColumnMenu,
|
|
19
20
|
decorators: [withTheme],
|
|
20
21
|
};
|
|
21
22
|
|
|
22
|
-
const defs: Pick<
|
|
23
|
+
const defs: Pick<ColumnSettingsProps, 'tableDef' | 'tablesToReference'> = {
|
|
23
24
|
tableDef: {
|
|
24
25
|
id: '1',
|
|
25
26
|
name: 'table 1',
|
|
26
|
-
columns: [{ id: 'col-1', prop: 'one
|
|
27
|
+
columns: [{ id: 'col-1', prop: 'one', type: FieldValueType.String }],
|
|
27
28
|
},
|
|
28
29
|
tablesToReference: [
|
|
29
30
|
{
|
|
30
31
|
id: '1',
|
|
31
32
|
name: 'table 1',
|
|
32
|
-
columns: [{ id: 'col-1', prop: 'one
|
|
33
|
+
columns: [{ id: 'col-1', prop: 'one', type: FieldValueType.String }],
|
|
33
34
|
},
|
|
34
35
|
{
|
|
35
36
|
id: '2',
|
|
36
37
|
name: 'table 2',
|
|
37
|
-
columns: [{ id: 'col-1', prop: 'two
|
|
38
|
+
columns: [{ id: 'col-1', prop: 'two', type: FieldValueType.String }],
|
|
38
39
|
},
|
|
39
40
|
],
|
|
40
41
|
};
|
|
41
42
|
|
|
42
|
-
const
|
|
43
|
+
const functions: Pick<ColumnSettingsProps, 'onUpdate' | 'onDelete'> = {
|
|
43
44
|
onUpdate: (...args: any) => console.log('onUpdate args', args),
|
|
44
45
|
onDelete: (...args: any) => console.log('onDelete args', args),
|
|
45
46
|
};
|
|
@@ -49,10 +50,10 @@ export const Default = {
|
|
|
49
50
|
column: {
|
|
50
51
|
id: 'test',
|
|
51
52
|
label: 'test',
|
|
52
|
-
} as
|
|
53
|
+
} as ColumnDef,
|
|
53
54
|
|
|
54
55
|
...defs,
|
|
55
|
-
...
|
|
56
|
+
...functions,
|
|
56
57
|
|
|
57
58
|
context: {
|
|
58
59
|
header: {
|
|
@@ -89,11 +90,13 @@ export const ReactiveSort = {
|
|
|
89
90
|
column: {
|
|
90
91
|
id: 'test',
|
|
91
92
|
label: 'test',
|
|
92
|
-
} as
|
|
93
|
+
} as ColumnDef,
|
|
93
94
|
context: {
|
|
94
95
|
header: {
|
|
95
96
|
column: {
|
|
96
97
|
getCanSort: () => true,
|
|
98
|
+
getIsSorted: () => sort,
|
|
99
|
+
clearSorting: () => setSort(false),
|
|
97
100
|
toggleSorting: (desc?: boolean) => {
|
|
98
101
|
if (desc === undefined) {
|
|
99
102
|
setSort(false);
|
|
@@ -103,8 +106,6 @@ export const ReactiveSort = {
|
|
|
103
106
|
setSort('asc');
|
|
104
107
|
}
|
|
105
108
|
},
|
|
106
|
-
getIsSorted: () => sort,
|
|
107
|
-
clearSorting: () => setSort(false),
|
|
108
109
|
getToggleSortingHandler: () => () => {
|
|
109
110
|
if (sort === 'asc') {
|
|
110
111
|
setSort('desc');
|
|
@@ -9,22 +9,25 @@ import React, { useRef, useState, useCallback } from 'react';
|
|
|
9
9
|
import { Button, Popover, DropdownMenu } from '@dxos/react-ui';
|
|
10
10
|
import { getSize, mx } from '@dxos/react-ui-theme';
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import { ColumnSettings } from './ColumnSettings';
|
|
13
13
|
import { useSortColumn } from '../../hooks';
|
|
14
|
-
import { type TableDef, type
|
|
14
|
+
import { type TableDef, type ColumnDef } from '../../schema';
|
|
15
15
|
|
|
16
16
|
export type ColumnMenuProps<TData extends RowData, TValue> = {
|
|
17
17
|
context: HeaderContext<TData, TValue>;
|
|
18
18
|
tablesToReference: TableDef[];
|
|
19
19
|
tableDef: TableDef;
|
|
20
|
-
column:
|
|
20
|
+
column: ColumnDef;
|
|
21
21
|
columnOrderable: boolean;
|
|
22
22
|
columnPosition: 'start' | 'end' | undefined;
|
|
23
23
|
onColumnReorder: (columnId: string, direction: 'left' | 'right') => void;
|
|
24
|
-
onUpdate?: (id: string, column:
|
|
24
|
+
onUpdate?: (id: string, column: ColumnDef) => void;
|
|
25
25
|
onDelete?: (id: string) => void;
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* @deprecated
|
|
30
|
+
*/
|
|
28
31
|
export const ColumnMenu = <TData extends RowData, TValue>({
|
|
29
32
|
column,
|
|
30
33
|
columnOrderable,
|
|
@@ -138,7 +141,7 @@ export const ColumnMenu = <TData extends RowData, TValue>({
|
|
|
138
141
|
<Popover.Portal>
|
|
139
142
|
<Popover.Content>
|
|
140
143
|
<Popover.Viewport>
|
|
141
|
-
<
|
|
144
|
+
<ColumnSettings {...props} column={column} onClose={() => setIsColumnSettingsOpen(false)} />
|
|
142
145
|
</Popover.Viewport>
|
|
143
146
|
<Popover.Arrow />
|
|
144
147
|
</Popover.Content>
|
package/src/components/ColumnMenu/{ColumnSettingsForm.stories.tsx → ColumnSettings.stories.tsx}
RENAMED
|
@@ -3,25 +3,38 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import '@dxos-theme';
|
|
6
|
+
|
|
6
7
|
import React from 'react';
|
|
7
8
|
|
|
8
|
-
import {
|
|
9
|
+
import { FieldValueType } from '@dxos/schema';
|
|
10
|
+
import { withTheme, withLayout } from '@dxos/storybook-utils';
|
|
9
11
|
|
|
10
|
-
import {
|
|
12
|
+
import { ColumnSettings, type ColumnSettingsProps } from './ColumnSettings';
|
|
11
13
|
import { type TableDef } from '../../schema';
|
|
14
|
+
import translations from '../../translations';
|
|
15
|
+
|
|
16
|
+
const DefaultStory = (props: ColumnSettingsProps) => (
|
|
17
|
+
<div className='flex w-[240px] m-2 p-2 border border-separator rounded'>
|
|
18
|
+
<ColumnSettings {...props} />
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
12
21
|
|
|
13
22
|
export default {
|
|
14
|
-
title: 'react-ui-table/
|
|
15
|
-
component:
|
|
16
|
-
|
|
23
|
+
title: 'ui/react-ui-table/ColumnSettings',
|
|
24
|
+
component: ColumnSettings,
|
|
25
|
+
render: DefaultStory,
|
|
26
|
+
decorators: [withTheme, withLayout()],
|
|
27
|
+
parameters: {
|
|
28
|
+
translations,
|
|
29
|
+
},
|
|
17
30
|
};
|
|
18
31
|
|
|
19
32
|
const sampleTableDef: TableDef = {
|
|
20
33
|
id: '1',
|
|
21
34
|
name: 'Sample Table',
|
|
22
35
|
columns: [
|
|
23
|
-
{ id: 'col-1', prop: 'name', type:
|
|
24
|
-
{ id: 'col-2', prop: 'age', type:
|
|
36
|
+
{ id: 'col-1', prop: 'name', type: FieldValueType.String, label: 'Name' },
|
|
37
|
+
{ id: 'col-2', prop: 'age', type: FieldValueType.Number, label: 'Age', digits: 0 },
|
|
25
38
|
],
|
|
26
39
|
};
|
|
27
40
|
|
|
@@ -31,17 +44,17 @@ const sampleTablesToReference: TableDef[] = [
|
|
|
31
44
|
id: '2',
|
|
32
45
|
name: 'Reference Table',
|
|
33
46
|
columns: [
|
|
34
|
-
{ id: 'ref-col-1', prop: 'id', type:
|
|
35
|
-
{ id: 'ref-col-2', prop: 'description', type:
|
|
47
|
+
{ id: 'ref-col-1', prop: 'id', type: FieldValueType.String, label: 'ID' },
|
|
48
|
+
{ id: 'ref-col-2', prop: 'description', type: FieldValueType.String, label: 'Description' },
|
|
36
49
|
],
|
|
37
50
|
},
|
|
38
51
|
];
|
|
39
52
|
|
|
40
|
-
const defaultArgs:
|
|
53
|
+
const defaultArgs: ColumnSettingsProps = {
|
|
41
54
|
column: {
|
|
42
55
|
id: 'col-1',
|
|
43
56
|
prop: 'name',
|
|
44
|
-
type:
|
|
57
|
+
type: FieldValueType.String,
|
|
45
58
|
label: 'Name',
|
|
46
59
|
},
|
|
47
60
|
tableDef: sampleTableDef,
|
|
@@ -61,7 +74,7 @@ export const NumberColumn = {
|
|
|
61
74
|
column: {
|
|
62
75
|
id: 'col-2',
|
|
63
76
|
prop: 'age',
|
|
64
|
-
type:
|
|
77
|
+
type: FieldValueType.Number,
|
|
65
78
|
label: 'Age',
|
|
66
79
|
digits: 0,
|
|
67
80
|
},
|
|
@@ -74,7 +87,7 @@ export const ReferenceColumn = {
|
|
|
74
87
|
column: {
|
|
75
88
|
id: 'col-3',
|
|
76
89
|
prop: 'reference',
|
|
77
|
-
type:
|
|
90
|
+
type: FieldValueType.Ref,
|
|
78
91
|
label: 'Reference',
|
|
79
92
|
refTable: '2',
|
|
80
93
|
refProp: 'ref-col-1',
|
|
@@ -88,17 +101,8 @@ export const NewColumn = {
|
|
|
88
101
|
column: {
|
|
89
102
|
id: 'new-col',
|
|
90
103
|
prop: '',
|
|
91
|
-
type:
|
|
104
|
+
type: FieldValueType.String,
|
|
92
105
|
label: '',
|
|
93
106
|
},
|
|
94
107
|
},
|
|
95
108
|
};
|
|
96
|
-
|
|
97
|
-
const Template = (args: ColumnSettingsFormProps) => (
|
|
98
|
-
<div className='p-4 max-is-64'>
|
|
99
|
-
<ColumnSettingsForm {...args} />
|
|
100
|
-
</div>
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
export const Interactive = Template.bind({});
|
|
104
|
-
(Interactive as any).args = defaultArgs;
|
|
@@ -1,31 +1,39 @@
|
|
|
1
1
|
//
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
|
+
|
|
4
5
|
import React, { useRef, useState } from 'react';
|
|
5
6
|
|
|
6
7
|
import { Button, Input, Select, useTranslation } from '@dxos/react-ui';
|
|
8
|
+
import { FieldValueTypes, type FieldValueType } from '@dxos/schema';
|
|
7
9
|
import { safeParseInt } from '@dxos/util';
|
|
8
10
|
|
|
9
|
-
import { type TableDef, type
|
|
11
|
+
import { type TableDef, type ColumnDef } from '../../schema';
|
|
10
12
|
import { translationKey } from '../../translations';
|
|
11
13
|
|
|
12
|
-
export type
|
|
13
|
-
column:
|
|
14
|
+
export type ColumnSettingsProps = {
|
|
15
|
+
column: ColumnDef;
|
|
14
16
|
tableDef: TableDef;
|
|
17
|
+
// TODO(burdon): Rename.
|
|
15
18
|
tablesToReference: TableDef[];
|
|
16
|
-
onUpdate?: (
|
|
17
|
-
onDelete?: (
|
|
19
|
+
onUpdate?: (id: string, column: ColumnDef) => void;
|
|
20
|
+
onDelete?: (id: string) => void;
|
|
18
21
|
onClose?: () => void;
|
|
19
22
|
};
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
/**
|
|
25
|
+
* @deprecated
|
|
26
|
+
*/
|
|
27
|
+
export const ColumnSettings = ({
|
|
22
28
|
column,
|
|
23
29
|
tableDef,
|
|
24
30
|
tablesToReference,
|
|
25
31
|
onUpdate,
|
|
26
32
|
onDelete,
|
|
27
33
|
onClose,
|
|
28
|
-
}:
|
|
34
|
+
}: ColumnSettingsProps) => {
|
|
35
|
+
const { t } = useTranslation(translationKey);
|
|
36
|
+
const propRef = useRef<HTMLInputElement>(null);
|
|
29
37
|
const [formState, setFormState] = useState({
|
|
30
38
|
prop: column.id,
|
|
31
39
|
refTable: column.refTable,
|
|
@@ -35,9 +43,6 @@ export const ColumnSettingsForm = ({
|
|
|
35
43
|
digits: String(column.digits ?? '0'),
|
|
36
44
|
});
|
|
37
45
|
|
|
38
|
-
const propRef = useRef<HTMLInputElement>(null);
|
|
39
|
-
const { t } = useTranslation(translationKey);
|
|
40
|
-
|
|
41
46
|
const handleSave = () => {
|
|
42
47
|
const { prop, refTable, refProp, type, label, digits } = formState;
|
|
43
48
|
|
|
@@ -62,7 +67,7 @@ export const ColumnSettingsForm = ({
|
|
|
62
67
|
id: prop, // TODO(burdon): Make unique.
|
|
63
68
|
prop,
|
|
64
69
|
label,
|
|
65
|
-
type: type as
|
|
70
|
+
type: type as FieldValueType,
|
|
66
71
|
refTable,
|
|
67
72
|
refProp,
|
|
68
73
|
digits: safeParseInt(digits),
|
|
@@ -75,9 +80,10 @@ export const ColumnSettingsForm = ({
|
|
|
75
80
|
onClose?.();
|
|
76
81
|
};
|
|
77
82
|
|
|
83
|
+
// TODO(burdon): Standardize dialog/popup.
|
|
78
84
|
return (
|
|
79
|
-
<div className='
|
|
80
|
-
<div className='
|
|
85
|
+
<div className='flex flex-col w-full gap-4'>
|
|
86
|
+
<div className='flex flex-col gap-2'>
|
|
81
87
|
<Input.Root>
|
|
82
88
|
<Input.Label>{t('column label label')}</Input.Label>
|
|
83
89
|
<Input.TextInput
|
|
@@ -88,8 +94,7 @@ export const ColumnSettingsForm = ({
|
|
|
88
94
|
data-testid='table.column-settings.label'
|
|
89
95
|
/>
|
|
90
96
|
</Input.Root>
|
|
91
|
-
|
|
92
|
-
<div className='space-y-1'>
|
|
97
|
+
|
|
93
98
|
<Input.Root>
|
|
94
99
|
<Input.Label>{t('property key label')}</Input.Label>
|
|
95
100
|
<Input.TextInput
|
|
@@ -101,8 +106,7 @@ export const ColumnSettingsForm = ({
|
|
|
101
106
|
}
|
|
102
107
|
/>
|
|
103
108
|
</Input.Root>
|
|
104
|
-
|
|
105
|
-
<div className='space-y-1'>
|
|
109
|
+
|
|
106
110
|
<Input.Root>
|
|
107
111
|
<Input.Label>{t('column type label')}</Input.Label>
|
|
108
112
|
<Select.Root
|
|
@@ -113,7 +117,7 @@ export const ColumnSettingsForm = ({
|
|
|
113
117
|
<Select.Portal>
|
|
114
118
|
<Select.Content>
|
|
115
119
|
<Select.Viewport>
|
|
116
|
-
{
|
|
120
|
+
{FieldValueTypes.map((type) => (
|
|
117
121
|
<Select.Option key={type} value={type}>
|
|
118
122
|
{t(`${type} column type label`)}
|
|
119
123
|
</Select.Option>
|
|
@@ -123,9 +127,8 @@ export const ColumnSettingsForm = ({
|
|
|
123
127
|
</Select.Portal>
|
|
124
128
|
</Select.Root>
|
|
125
129
|
</Input.Root>
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
<div className='space-y-1'>
|
|
130
|
+
|
|
131
|
+
{formState.type === 'number' && (
|
|
129
132
|
<Input.Root>
|
|
130
133
|
<Input.Label>{t('digits label')}</Input.Label>
|
|
131
134
|
<Input.TextInput
|
|
@@ -133,12 +136,10 @@ export const ColumnSettingsForm = ({
|
|
|
133
136
|
onChange={(event) => setFormState((prevState) => ({ ...prevState, digits: event.target.value }))}
|
|
134
137
|
/>
|
|
135
138
|
</Input.Root>
|
|
136
|
-
|
|
137
|
-
)}
|
|
139
|
+
)}
|
|
138
140
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
<div className='space-y-1'>
|
|
141
|
+
{formState.type === 'ref' && (
|
|
142
|
+
<>
|
|
142
143
|
<Input.Root>
|
|
143
144
|
<Input.Label>Table</Input.Label>
|
|
144
145
|
<Select.Root
|
|
@@ -161,9 +162,8 @@ export const ColumnSettingsForm = ({
|
|
|
161
162
|
</Select.Portal>
|
|
162
163
|
</Select.Root>
|
|
163
164
|
</Input.Root>
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
<div className='space-y-1'>
|
|
165
|
+
|
|
166
|
+
{formState.refTable && (
|
|
167
167
|
<Input.Root>
|
|
168
168
|
<Input.Label>Table property</Input.Label>
|
|
169
169
|
<Select.Root
|
|
@@ -186,20 +186,21 @@ export const ColumnSettingsForm = ({
|
|
|
186
186
|
</Select.Portal>
|
|
187
187
|
</Select.Root>
|
|
188
188
|
</Input.Root>
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
<div
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
189
|
+
)}
|
|
190
|
+
</>
|
|
191
|
+
)}
|
|
192
|
+
</div>
|
|
193
|
+
|
|
194
|
+
<div>
|
|
195
|
+
{/* TODO(burdon): Change delete to cancel. Delete should be menu item. */}
|
|
196
|
+
<div className='flex flex-row justify-end gap-1'>
|
|
197
|
+
<Button onClick={handleDelete} data-testid='table.column-settings.delete'>
|
|
198
|
+
{t('delete label')}
|
|
199
|
+
</Button>
|
|
200
|
+
<Button variant='primary' onClick={handleSave} data-testid='table.column-settings.save'>
|
|
201
|
+
{t('save label')}
|
|
202
|
+
</Button>
|
|
203
|
+
</div>
|
|
203
204
|
</div>
|
|
204
205
|
</div>
|
|
205
206
|
);
|
|
@@ -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
|
};
|