@dxos/react-ui-table 0.6.14-staging.e15392e → 0.7.1-staging.599df14

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.
Files changed (242) hide show
  1. package/dist/lib/browser/_deprecated/index.mjs +1483 -0
  2. package/dist/lib/browser/_deprecated/index.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-A5W4XWPD.mjs +18 -0
  4. package/dist/lib/browser/chunk-A5W4XWPD.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +1274 -1356
  6. package/dist/lib/browser/index.mjs.map +4 -4
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/types/index.mjs +7 -0
  9. package/dist/lib/browser/types/index.mjs.map +7 -0
  10. package/dist/lib/node/_deprecated/index.cjs +1511 -0
  11. package/dist/lib/node/_deprecated/index.cjs.map +7 -0
  12. package/dist/lib/node/chunk-32IGMRME.cjs +40 -0
  13. package/dist/lib/node/chunk-32IGMRME.cjs.map +7 -0
  14. package/dist/lib/node/index.cjs +1380 -0
  15. package/dist/lib/node/index.cjs.map +7 -0
  16. package/dist/lib/node/meta.json +1 -0
  17. package/dist/lib/node/types/index.cjs +29 -0
  18. package/dist/lib/node/types/index.cjs.map +7 -0
  19. package/dist/lib/node-esm/_deprecated/index.mjs +1485 -0
  20. package/dist/lib/node-esm/_deprecated/index.mjs.map +7 -0
  21. package/dist/lib/node-esm/chunk-DWQ4KGLD.mjs +20 -0
  22. package/dist/lib/node-esm/chunk-DWQ4KGLD.mjs.map +7 -0
  23. package/dist/lib/node-esm/index.mjs +1399 -0
  24. package/dist/lib/node-esm/index.mjs.map +7 -0
  25. package/dist/lib/node-esm/meta.json +1 -0
  26. package/dist/lib/node-esm/types/index.mjs +8 -0
  27. package/dist/lib/node-esm/types/index.mjs.map +7 -0
  28. package/dist/types/src/_deprecated/components/Cell/Cell.d.ts.map +1 -0
  29. package/dist/types/src/_deprecated/components/Cell/CellCombobox.d.ts.map +1 -0
  30. package/dist/types/src/_deprecated/components/Cell/index.d.ts.map +1 -0
  31. package/dist/types/src/_deprecated/components/ColumnMenu/ColumnMenu.d.ts.map +1 -0
  32. package/dist/types/src/_deprecated/components/ColumnMenu/ColumnMenu.stories.d.ts.map +1 -0
  33. package/dist/types/src/_deprecated/components/ColumnMenu/ColumnSettings.d.ts.map +1 -0
  34. package/dist/types/src/{components → _deprecated/components}/ColumnMenu/ColumnSettings.stories.d.ts +4 -4
  35. package/dist/types/src/_deprecated/components/ColumnMenu/ColumnSettings.stories.d.ts.map +1 -0
  36. package/dist/types/src/_deprecated/components/ColumnMenu/index.d.ts.map +1 -0
  37. package/dist/types/src/_deprecated/components/Table/Table.d.ts +20 -0
  38. package/dist/types/src/_deprecated/components/Table/Table.d.ts.map +1 -0
  39. package/dist/types/src/_deprecated/components/Table/Table.stories.d.ts +116 -0
  40. package/dist/types/src/_deprecated/components/Table/Table.stories.d.ts.map +1 -0
  41. package/dist/types/src/_deprecated/components/Table/TableBody.d.ts.map +1 -0
  42. package/dist/types/src/_deprecated/components/Table/TableContext.d.ts.map +1 -0
  43. package/dist/types/src/_deprecated/components/Table/TableHead.d.ts.map +1 -0
  44. package/dist/types/src/_deprecated/components/Table/TableRootContext.d.ts.map +1 -0
  45. package/dist/types/src/_deprecated/components/Table/index.d.ts +5 -0
  46. package/dist/types/src/_deprecated/components/Table/index.d.ts.map +1 -0
  47. package/dist/types/src/_deprecated/components/Table/props.d.ts.map +1 -0
  48. package/dist/types/src/_deprecated/components/index.d.ts +4 -0
  49. package/dist/types/src/_deprecated/components/index.d.ts.map +1 -0
  50. package/dist/types/src/_deprecated/helpers.d.ts.map +1 -0
  51. package/dist/types/src/_deprecated/hooks/index.d.ts +5 -0
  52. package/dist/types/src/_deprecated/hooks/index.d.ts.map +1 -0
  53. package/dist/types/src/_deprecated/hooks/useColumnSizing.d.ts.map +1 -0
  54. package/dist/types/src/{hooks → _deprecated/hooks}/useColumnSorting.d.ts +1 -1
  55. package/dist/types/src/_deprecated/hooks/useColumnSorting.d.ts.map +1 -0
  56. package/dist/types/src/_deprecated/hooks/usePinLastRow.d.ts.map +1 -0
  57. package/dist/types/src/_deprecated/hooks/useRowSelection.d.ts.map +1 -0
  58. package/dist/types/src/_deprecated/index.d.ts +8 -0
  59. package/dist/types/src/_deprecated/index.d.ts.map +1 -0
  60. package/dist/types/src/_deprecated/schema/Schema.stories.d.ts.map +1 -0
  61. package/dist/types/src/{schema → _deprecated/schema}/column-utils.d.ts +3 -0
  62. package/dist/types/src/_deprecated/schema/column-utils.d.ts.map +1 -0
  63. package/dist/types/src/_deprecated/schema/index.d.ts.map +1 -0
  64. package/dist/types/src/{schema → _deprecated/schema}/types.d.ts +3 -2
  65. package/dist/types/src/_deprecated/schema/types.d.ts.map +1 -0
  66. package/dist/types/src/_deprecated/theme.d.ts.map +1 -0
  67. package/dist/types/src/_deprecated/translations.d.ts +21 -0
  68. package/dist/types/src/_deprecated/translations.d.ts.map +1 -0
  69. package/dist/types/src/_deprecated/types.d.ts.map +1 -0
  70. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts +8 -0
  71. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -0
  72. package/dist/types/src/components/Table/ColumnSettings.d.ts +8 -0
  73. package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -0
  74. package/dist/types/src/components/Table/RowActionsMenu.d.ts +8 -0
  75. package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -0
  76. package/dist/types/src/components/Table/Table.d.ts +13 -15
  77. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  78. package/dist/types/src/components/Table/Table.stories.d.ts +10 -113
  79. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  80. package/dist/types/src/components/Table/index.d.ts +0 -3
  81. package/dist/types/src/components/Table/index.d.ts.map +1 -1
  82. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +17 -0
  83. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -0
  84. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +11 -0
  85. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -0
  86. package/dist/types/src/components/TableCellEditor/extension.d.ts +12 -0
  87. package/dist/types/src/components/TableCellEditor/extension.d.ts.map +1 -0
  88. package/dist/types/src/components/TableCellEditor/index.d.ts +2 -0
  89. package/dist/types/src/components/TableCellEditor/index.d.ts.map +1 -0
  90. package/dist/types/src/components/Toolbar/Toolbar.d.ts +21 -0
  91. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -0
  92. package/dist/types/src/components/Toolbar/common.d.ts +14 -0
  93. package/dist/types/src/components/Toolbar/common.d.ts.map +1 -0
  94. package/dist/types/src/components/Toolbar/index.d.ts +2 -0
  95. package/dist/types/src/components/Toolbar/index.d.ts.map +1 -0
  96. package/dist/types/src/components/index.d.ts +1 -2
  97. package/dist/types/src/components/index.d.ts.map +1 -1
  98. package/dist/types/src/components/testing.d.ts +97 -0
  99. package/dist/types/src/components/testing.d.ts.map +1 -0
  100. package/dist/types/src/hooks/index.d.ts +1 -4
  101. package/dist/types/src/hooks/index.d.ts.map +1 -1
  102. package/dist/types/src/hooks/useTableModel.d.ts +15 -0
  103. package/dist/types/src/hooks/useTableModel.d.ts.map +1 -0
  104. package/dist/types/src/index.d.ts +3 -4
  105. package/dist/types/src/index.d.ts.map +1 -1
  106. package/dist/types/src/model/index.d.ts +3 -0
  107. package/dist/types/src/model/index.d.ts.map +1 -0
  108. package/dist/types/src/model/modal-controller.d.ts +29 -0
  109. package/dist/types/src/model/modal-controller.d.ts.map +1 -0
  110. package/dist/types/src/model/selection-model.d.ts +22 -0
  111. package/dist/types/src/model/selection-model.d.ts.map +1 -0
  112. package/dist/types/src/model/table-model.d.ts +93 -0
  113. package/dist/types/src/model/table-model.d.ts.map +1 -0
  114. package/dist/types/src/model/table-model.test.d.ts +2 -0
  115. package/dist/types/src/model/table-model.test.d.ts.map +1 -0
  116. package/dist/types/src/translations.d.ts +23 -16
  117. package/dist/types/src/translations.d.ts.map +1 -1
  118. package/dist/types/src/types/index.d.ts +2 -0
  119. package/dist/types/src/types/index.d.ts.map +1 -0
  120. package/dist/types/src/types/table.d.ts +106 -0
  121. package/dist/types/src/types/table.d.ts.map +1 -0
  122. package/dist/types/src/util/grid.d.ts +14 -0
  123. package/dist/types/src/util/grid.d.ts.map +1 -0
  124. package/dist/types/src/util/index.d.ts +5 -0
  125. package/dist/types/src/util/index.d.ts.map +1 -0
  126. package/dist/types/src/util/signals.d.ts +6 -0
  127. package/dist/types/src/util/signals.d.ts.map +1 -0
  128. package/dist/types/src/util/table-buttons.d.ts +24 -0
  129. package/dist/types/src/util/table-buttons.d.ts.map +1 -0
  130. package/dist/types/src/util/table-controls.d.ts +21 -0
  131. package/dist/types/src/util/table-controls.d.ts.map +1 -0
  132. package/dist/types/src/util/table.d.ts +8 -0
  133. package/dist/types/src/util/table.d.ts.map +1 -0
  134. package/package.json +56 -22
  135. package/src/{components → _deprecated/components}/ColumnMenu/ColumnMenu.stories.tsx +4 -4
  136. package/src/{components → _deprecated/components}/ColumnMenu/ColumnSettings.stories.tsx +9 -9
  137. package/src/{components → _deprecated/components}/ColumnMenu/ColumnSettings.tsx +3 -3
  138. package/src/_deprecated/components/Table/Table.stories.tsx +508 -0
  139. package/src/_deprecated/components/Table/Table.tsx +301 -0
  140. package/src/{components → _deprecated/components}/Table/TableHead.tsx +3 -1
  141. package/src/_deprecated/components/Table/index.ts +8 -0
  142. package/src/_deprecated/components/index.ts +7 -0
  143. package/src/{helpers.tsx → _deprecated/helpers.tsx} +4 -3
  144. package/src/_deprecated/hooks/index.ts +8 -0
  145. package/src/_deprecated/index.ts +12 -0
  146. package/src/_deprecated/schema/column-utils.ts +54 -0
  147. package/src/{schema → _deprecated/schema}/types.ts +3 -2
  148. package/src/_deprecated/translations.ts +26 -0
  149. package/src/components/Table/ColumnActionsMenu.tsx +60 -0
  150. package/src/components/Table/ColumnSettings.tsx +76 -0
  151. package/src/components/Table/RowActionsMenu.tsx +36 -0
  152. package/src/components/Table/Table.stories.tsx +197 -467
  153. package/src/components/Table/Table.tsx +177 -256
  154. package/src/components/Table/index.ts +1 -4
  155. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +114 -0
  156. package/src/components/TableCellEditor/TableCellEditor.tsx +155 -0
  157. package/src/components/TableCellEditor/extension.ts +62 -0
  158. package/src/components/TableCellEditor/index.ts +5 -0
  159. package/src/components/Toolbar/Toolbar.tsx +87 -0
  160. package/src/components/Toolbar/common.tsx +71 -0
  161. package/src/components/Toolbar/index.ts +5 -0
  162. package/src/components/index.ts +2 -3
  163. package/src/components/testing.ts +114 -0
  164. package/src/hooks/index.ts +1 -4
  165. package/src/hooks/useTableModel.ts +52 -0
  166. package/src/index.ts +5 -6
  167. package/src/model/index.ts +6 -0
  168. package/src/model/modal-controller.ts +83 -0
  169. package/src/model/selection-model.ts +99 -0
  170. package/src/model/table-model.test.ts +182 -0
  171. package/src/model/table-model.ts +565 -0
  172. package/src/translations.ts +20 -13
  173. package/src/types/index.ts +5 -0
  174. package/src/types/table.ts +13 -0
  175. package/src/util/grid.ts +23 -0
  176. package/src/util/index.ts +8 -0
  177. package/src/util/signals.ts +9 -0
  178. package/src/util/table-buttons.ts +48 -0
  179. package/src/util/table-controls.ts +27 -0
  180. package/src/util/table.ts +77 -0
  181. package/dist/types/src/components/Cell/Cell.d.ts.map +0 -1
  182. package/dist/types/src/components/Cell/CellCombobox.d.ts.map +0 -1
  183. package/dist/types/src/components/Cell/index.d.ts.map +0 -1
  184. package/dist/types/src/components/ColumnMenu/ColumnMenu.d.ts.map +0 -1
  185. package/dist/types/src/components/ColumnMenu/ColumnMenu.stories.d.ts.map +0 -1
  186. package/dist/types/src/components/ColumnMenu/ColumnSettings.d.ts.map +0 -1
  187. package/dist/types/src/components/ColumnMenu/ColumnSettings.stories.d.ts.map +0 -1
  188. package/dist/types/src/components/ColumnMenu/index.d.ts.map +0 -1
  189. package/dist/types/src/components/Table/TableBody.d.ts.map +0 -1
  190. package/dist/types/src/components/Table/TableContext.d.ts.map +0 -1
  191. package/dist/types/src/components/Table/TableHead.d.ts.map +0 -1
  192. package/dist/types/src/components/Table/TableRootContext.d.ts.map +0 -1
  193. package/dist/types/src/components/Table/props.d.ts.map +0 -1
  194. package/dist/types/src/helpers.d.ts.map +0 -1
  195. package/dist/types/src/hooks/useColumnSizing.d.ts.map +0 -1
  196. package/dist/types/src/hooks/useColumnSorting.d.ts.map +0 -1
  197. package/dist/types/src/hooks/usePinLastRow.d.ts.map +0 -1
  198. package/dist/types/src/hooks/useRowSelection.d.ts.map +0 -1
  199. package/dist/types/src/schema/Schema.stories.d.ts.map +0 -1
  200. package/dist/types/src/schema/column-utils.d.ts.map +0 -1
  201. package/dist/types/src/schema/index.d.ts.map +0 -1
  202. package/dist/types/src/schema/types.d.ts.map +0 -1
  203. package/dist/types/src/theme.d.ts.map +0 -1
  204. package/dist/types/src/types.d.ts.map +0 -1
  205. package/src/schema/column-utils.ts +0 -48
  206. /package/dist/types/src/{components → _deprecated/components}/Cell/Cell.d.ts +0 -0
  207. /package/dist/types/src/{components → _deprecated/components}/Cell/CellCombobox.d.ts +0 -0
  208. /package/dist/types/src/{components → _deprecated/components}/Cell/index.d.ts +0 -0
  209. /package/dist/types/src/{components → _deprecated/components}/ColumnMenu/ColumnMenu.d.ts +0 -0
  210. /package/dist/types/src/{components → _deprecated/components}/ColumnMenu/ColumnMenu.stories.d.ts +0 -0
  211. /package/dist/types/src/{components → _deprecated/components}/ColumnMenu/ColumnSettings.d.ts +0 -0
  212. /package/dist/types/src/{components → _deprecated/components}/ColumnMenu/index.d.ts +0 -0
  213. /package/dist/types/src/{components → _deprecated/components}/Table/TableBody.d.ts +0 -0
  214. /package/dist/types/src/{components → _deprecated/components}/Table/TableContext.d.ts +0 -0
  215. /package/dist/types/src/{components → _deprecated/components}/Table/TableHead.d.ts +0 -0
  216. /package/dist/types/src/{components → _deprecated/components}/Table/TableRootContext.d.ts +0 -0
  217. /package/dist/types/src/{components → _deprecated/components}/Table/props.d.ts +0 -0
  218. /package/dist/types/src/{helpers.d.ts → _deprecated/helpers.d.ts} +0 -0
  219. /package/dist/types/src/{hooks → _deprecated/hooks}/useColumnSizing.d.ts +0 -0
  220. /package/dist/types/src/{hooks → _deprecated/hooks}/usePinLastRow.d.ts +0 -0
  221. /package/dist/types/src/{hooks → _deprecated/hooks}/useRowSelection.d.ts +0 -0
  222. /package/dist/types/src/{schema → _deprecated/schema}/Schema.stories.d.ts +0 -0
  223. /package/dist/types/src/{schema → _deprecated/schema}/index.d.ts +0 -0
  224. /package/dist/types/src/{theme.d.ts → _deprecated/theme.d.ts} +0 -0
  225. /package/dist/types/src/{types.d.ts → _deprecated/types.d.ts} +0 -0
  226. /package/src/{components → _deprecated/components}/Cell/Cell.tsx +0 -0
  227. /package/src/{components → _deprecated/components}/Cell/CellCombobox.tsx +0 -0
  228. /package/src/{components → _deprecated/components}/Cell/index.ts +0 -0
  229. /package/src/{components → _deprecated/components}/ColumnMenu/ColumnMenu.tsx +0 -0
  230. /package/src/{components → _deprecated/components}/ColumnMenu/index.ts +0 -0
  231. /package/src/{components → _deprecated/components}/Table/TableBody.tsx +0 -0
  232. /package/src/{components → _deprecated/components}/Table/TableContext.tsx +0 -0
  233. /package/src/{components → _deprecated/components}/Table/TableRootContext.ts +0 -0
  234. /package/src/{components → _deprecated/components}/Table/props.ts +0 -0
  235. /package/src/{hooks → _deprecated/hooks}/useColumnSizing.ts +0 -0
  236. /package/src/{hooks → _deprecated/hooks}/useColumnSorting.ts +0 -0
  237. /package/src/{hooks → _deprecated/hooks}/usePinLastRow.ts +0 -0
  238. /package/src/{hooks → _deprecated/hooks}/useRowSelection.ts +0 -0
  239. /package/src/{schema → _deprecated/schema}/Schema.stories.tsx +0 -0
  240. /package/src/{schema → _deprecated/schema}/index.ts +0 -0
  241. /package/src/{theme.ts → _deprecated/theme.ts} +0 -0
  242. /package/src/{types.ts → _deprecated/types.ts} +0 -0
@@ -0,0 +1,508 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import '@dxos-theme';
6
+
7
+ import { Plugs, PlugsConnected } from '@phosphor-icons/react';
8
+ import { type StoryObj } from '@storybook/react';
9
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
10
+
11
+ import { create } from '@dxos/echo-schema';
12
+ import { PublicKey } from '@dxos/keys';
13
+ import { log } from '@dxos/log';
14
+ import { faker } from '@dxos/random';
15
+ import { Button } from '@dxos/react-ui';
16
+ import { withSignals, withTheme } from '@dxos/storybook-utils';
17
+ import { range } from '@dxos/util';
18
+
19
+ import { Table } from './Table';
20
+ import { createColumnBuilder, type SearchListQueryModel, type ValueUpdater } from '../../helpers';
21
+ import { type TableColumnDef } from '../../types';
22
+
23
+ // TODO(burdon): Header menu builder.
24
+ // TODO(burdon): Expand width if not all columns have explicit size.
25
+
26
+ type Item = {
27
+ publicKey: PublicKey;
28
+ name: string;
29
+ company?: string;
30
+ count?: number;
31
+ started?: Date;
32
+ complete?: boolean;
33
+ };
34
+
35
+ faker.seed(911);
36
+
37
+ const createItems = (count: number) =>
38
+ range(count).map(
39
+ () =>
40
+ create<Item>({
41
+ publicKey: PublicKey.random(),
42
+ name: faker.commerce.productName(),
43
+ count: faker.datatype.boolean({ probability: 0.9 }) ? faker.number.int({ min: 0, max: 10_000 }) : undefined,
44
+ started: faker.date.recent(),
45
+ complete: faker.datatype.boolean() ? true : faker.datatype.boolean() ? false : undefined,
46
+ }) as Item,
47
+ );
48
+
49
+ const updateItems = <TValue = any,>(items: Item[], key: PublicKey, id: string, value: TValue) => {
50
+ return items.map((item) => (item.publicKey.equals(key) ? { ...item, [id]: value } : item));
51
+ };
52
+
53
+ const tableStorySelectItems: Record<string, Item> = range(128).reduce((acc: Record<string, Item>, _i) => {
54
+ const id = PublicKey.random();
55
+ acc[id.toHex()] = {
56
+ publicKey: id,
57
+ name: faker.company.name(),
58
+ };
59
+ return acc;
60
+ }, {});
61
+
62
+ const timeout = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
63
+
64
+ const tableStorySelectModel: SearchListQueryModel<Item> = {
65
+ getId: (object) => object?.publicKey?.toHex() ?? 'never',
66
+ getText: (object) => object?.name ?? 'never',
67
+ query: async (search: string) => {
68
+ await timeout(400);
69
+ return Object.values(tableStorySelectItems).filter((item) => {
70
+ return item.name.toLowerCase().includes(search.toLowerCase());
71
+ });
72
+ },
73
+ };
74
+
75
+ const { helper, builder } = createColumnBuilder<Item>();
76
+
77
+ const makeColumns = (onUpdate?: ValueUpdater<Item, any>): TableColumnDef<Item, any>[] => [
78
+ helper.display(builder.selectRow()),
79
+ helper.accessor((item) => item.publicKey, { id: 'key', ...builder.key({ tooltip: true }) }),
80
+ helper.accessor(
81
+ 'name',
82
+ builder.string({
83
+ label: 'Name',
84
+ onUpdate,
85
+ meta: { expand: true },
86
+ footer: (props) => props.table.getRowModel().rows.length,
87
+ }),
88
+ ),
89
+ helper.accessor('started', builder.date({ label: 'Started', relative: true, meta: { resizable: true } })),
90
+ helper.accessor(
91
+ 'count',
92
+ builder.number({
93
+ label: 'Count',
94
+ meta: { resizable: true },
95
+ onUpdate,
96
+ getGroupingValue: (row) => (row.count ? (row.count < 2000 ? 'A' : row.count < 5000 ? 'B' : 'C') : 'D'),
97
+ }),
98
+ ),
99
+ helper.accessor('company', builder.combobox({ label: 'Company', model: tableStorySelectModel, onUpdate })),
100
+ helper.accessor(
101
+ 'complete',
102
+ builder.switch({ getGroupingValue: (row) => row.complete === true, label: '', onUpdate }),
103
+ ),
104
+ helper.accessor('complete', builder.icon({ id: 'done', label: '' })),
105
+ helper.accessor(
106
+ 'complete',
107
+ builder.icon({
108
+ id: 'connected',
109
+ label: '',
110
+ on: { Icon: PlugsConnected, className: 'text-blue-500' },
111
+ off: { Icon: Plugs, className: 'text-blue-200' },
112
+ }),
113
+ ),
114
+ ];
115
+
116
+ //
117
+ // Tests
118
+ //
119
+
120
+ const MinimalTable = (props: any) => {
121
+ return (
122
+ <Table.Root>
123
+ <Table.Viewport classNames='fixed inset-0'>
124
+ <Table.Main<any> {...props} />
125
+ </Table.Viewport>
126
+ </Table.Root>
127
+ );
128
+ };
129
+
130
+ export default {
131
+ title: 'ui/react-ui-table/Table',
132
+ component: MinimalTable,
133
+ args: {
134
+ header: true,
135
+ keyAccessor: (item: Item) => item.publicKey.toHex(),
136
+ },
137
+ argTypes: {
138
+ header: { control: 'boolean' },
139
+ footer: { control: 'boolean' },
140
+ border: { control: 'boolean' },
141
+ fullWidth: { control: 'boolean' },
142
+ grouping: {
143
+ control: 'select',
144
+ options: ['none', 'complete', 'count'],
145
+ mapping: {
146
+ none: undefined,
147
+ complete: ['complete'],
148
+ count: ['count'],
149
+ },
150
+ },
151
+ columnVisibility: {
152
+ control: 'select',
153
+ options: ['all', 'limited'],
154
+ mapping: {
155
+ all: undefined,
156
+ limited: { key: false, started: false },
157
+ },
158
+ },
159
+ rowsSelectable: { control: 'select', options: [false, true, 'multi'] },
160
+ },
161
+ decorators: [withTheme],
162
+ };
163
+
164
+ export const Default = {
165
+ args: {
166
+ columns: makeColumns(),
167
+ data: createItems(20),
168
+ },
169
+ };
170
+
171
+ export const Scrolling = {
172
+ args: {
173
+ columns: makeColumns(),
174
+ data: createItems(200),
175
+ },
176
+ };
177
+
178
+ export const Visibility = {
179
+ args: {
180
+ columns: makeColumns(),
181
+ data: createItems(10),
182
+ columnVisibility: { key: false, started: false },
183
+ },
184
+ };
185
+
186
+ export const Empty = {
187
+ args: {
188
+ columns: makeColumns(),
189
+ },
190
+ };
191
+
192
+ export const Dynamic = {
193
+ render: () => {
194
+ const [items, setItems] = useState<Item[]>(createItems(50));
195
+
196
+ useEffect(() => {
197
+ const interval = setInterval(() => {
198
+ setItems((items) => {
199
+ if (items.length >= 200) {
200
+ clearInterval(interval);
201
+ }
202
+ return [...items, ...createItems(1)];
203
+ });
204
+ }, 500);
205
+ return () => clearInterval(interval);
206
+ }, []);
207
+
208
+ const columns = useMemo(() => makeColumns(), []);
209
+
210
+ return (
211
+ <Table.Root>
212
+ <Table.Viewport classNames='fixed inset-0'>
213
+ <Table.Main<Item>
214
+ role='grid'
215
+ rowsSelectable='multi'
216
+ keyAccessor={(row) => row.publicKey.toHex()}
217
+ columns={columns}
218
+ data={items}
219
+ fullWidth
220
+ stickyHeader
221
+ border
222
+ pinLastRow
223
+ />
224
+ </Table.Viewport>
225
+ </Table.Root>
226
+ );
227
+ },
228
+ };
229
+
230
+ export const Editable = {
231
+ render: () => {
232
+ const [items, setItems] = useState<Item[]>(createItems(200));
233
+
234
+ const onUpdate: ValueUpdater<Item, any> = useCallback(
235
+ (item, prop, value) => setItems((items) => updateItems(items, item.publicKey, prop, value)),
236
+ [setItems],
237
+ );
238
+
239
+ const columns = useMemo(() => makeColumns(onUpdate), [onUpdate]);
240
+
241
+ return (
242
+ <Table.Root>
243
+ <Table.Viewport classNames='fixed inset-0'>
244
+ <Table.Main<Item>
245
+ role='grid'
246
+ rowsSelectable='multi'
247
+ keyAccessor={(row) => row.publicKey.toHex()}
248
+ columns={columns}
249
+ data={items}
250
+ fullWidth
251
+ stickyHeader
252
+ border
253
+ pinLastRow
254
+ />
255
+ </Table.Viewport>
256
+ </Table.Root>
257
+ );
258
+ },
259
+ };
260
+
261
+ export const PinnedLastRow = {
262
+ render: () => {
263
+ const [items, setItems] = useState<Item[]>(createItems(200));
264
+
265
+ const onUpdate: ValueUpdater<Item, any> = useCallback(
266
+ (item, prop, value) => setItems((items) => updateItems(items, item.publicKey, prop, value)),
267
+ [setItems],
268
+ );
269
+
270
+ const columns = useMemo(() => makeColumns(onUpdate), [onUpdate]);
271
+
272
+ return (
273
+ <Table.Root>
274
+ <Table.Viewport classNames='fixed inset-0'>
275
+ <Table.Main<Item>
276
+ role='grid'
277
+ rowsSelectable='multi'
278
+ keyAccessor={(row) => row.publicKey.toHex()}
279
+ columns={columns}
280
+ data={items}
281
+ fullWidth
282
+ stickyHeader
283
+ border
284
+ pinLastRow
285
+ />
286
+ </Table.Viewport>
287
+ </Table.Root>
288
+ );
289
+ },
290
+ };
291
+
292
+ export const InsertDelete = {
293
+ render: () => {
294
+ const [items, setItems] = useState<Item[]>(createItems(10));
295
+
296
+ const onUpdate: ValueUpdater<Item, any> = useCallback(
297
+ (item, prop, value) => setItems((items) => updateItems(items, item.publicKey, prop, value)),
298
+ [setItems],
299
+ );
300
+
301
+ const columns = useMemo(() => makeColumns(onUpdate), [onUpdate]);
302
+
303
+ const onInsertFirst = () => {
304
+ setItems((items) => [...createItems(1), ...items]);
305
+ };
306
+
307
+ const onInsertLast = () => {
308
+ setItems((items) => [...items, ...createItems(1)]);
309
+ };
310
+
311
+ const onDeleteFirst = () => {
312
+ setItems(([_first, ...rest]) => rest);
313
+ };
314
+
315
+ const onDeleteLast = () => {
316
+ setItems((items) => [...items.slice(0, items.length - 1)]);
317
+ };
318
+
319
+ return (
320
+ <div className='space-y-4'>
321
+ <div className='flex flex-row gap-2'>
322
+ <Button onClick={onInsertFirst}>Insert first</Button>
323
+ <Button onClick={onInsertLast}>Insert last</Button>
324
+ <Button onClick={onDeleteFirst}>Delete first</Button>
325
+ <Button onClick={onDeleteLast}>Delete last</Button>
326
+ </div>
327
+ <Table.Root>
328
+ <Table.Viewport>
329
+ <Table.Main<Item>
330
+ role='grid'
331
+ rowsSelectable='multi'
332
+ keyAccessor={(row) => row.publicKey.toHex()}
333
+ columns={columns}
334
+ data={items}
335
+ fullWidth
336
+ stickyHeader
337
+ border
338
+ pinLastRow
339
+ />
340
+ </Table.Viewport>
341
+ </Table.Root>
342
+ </div>
343
+ );
344
+ },
345
+ };
346
+
347
+ export const Resizable = {
348
+ render: () => {
349
+ const [items, setItems] = useState<Item[]>(createItems(10));
350
+
351
+ const onUpdate: ValueUpdater<Item, any> = useCallback(
352
+ (item, prop, value) => setItems((items) => updateItems(items, item.publicKey, prop, value)),
353
+ [setItems],
354
+ );
355
+
356
+ return (
357
+ <Table.Root>
358
+ <Table.Viewport classNames='fixed inset-0'>
359
+ <Table.Main<Item>
360
+ rowsSelectable='multi'
361
+ keyAccessor={(row) => row.publicKey.toHex()}
362
+ columns={makeColumns(onUpdate)}
363
+ data={items}
364
+ fullWidth
365
+ stickyHeader
366
+ />
367
+ </Table.Viewport>
368
+ </Table.Root>
369
+ );
370
+ },
371
+ };
372
+
373
+ export const TenThousandRows = {
374
+ render: () => {
375
+ const [items, setItems] = useState<Item[]>(createItems(10000));
376
+
377
+ const onUpdate: ValueUpdater<Item, any> = useCallback(
378
+ (item, prop, value) => setItems((items) => updateItems(items, item.publicKey, prop, value)),
379
+ [setItems],
380
+ );
381
+
382
+ const columns = useMemo(() => makeColumns(onUpdate), [onUpdate]);
383
+
384
+ return (
385
+ <Table.Root>
386
+ <Table.Viewport classNames='fixed inset-0'>
387
+ <Table.Main<Item>
388
+ role='grid'
389
+ rowsSelectable='multi'
390
+ keyAccessor={(row) => row.publicKey.toHex()}
391
+ columns={columns}
392
+ data={items}
393
+ fullWidth
394
+ stickyHeader
395
+ border
396
+ />{' '}
397
+ </Table.Viewport>
398
+ </Table.Root>
399
+ );
400
+ },
401
+ };
402
+
403
+ // TODO(burdon): Warning: Encountered two children with the same key.
404
+
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) {
431
+ return;
432
+ }
433
+
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);
440
+
441
+ return () => clearInterval(i);
442
+ }, [periodicMutations, mutationInterval, state.items]);
443
+
444
+ useEffect(() => {
445
+ if (!periodicInsertions) {
446
+ return;
447
+ }
448
+
449
+ const i = setInterval(() => {
450
+ log('inserting...');
451
+ state.items.push(createItems(1)[0]);
452
+ }, insertionInterval);
453
+
454
+ return () => clearInterval(i);
455
+ }, [periodicInsertions, insertionInterval, state.items]);
456
+
457
+ useEffect(() => {
458
+ if (!periodicDeletions) {
459
+ return;
460
+ }
461
+
462
+ const i = setInterval(() => {
463
+ if (state.items.length === 0) {
464
+ return;
465
+ }
466
+
467
+ log('deleting...');
468
+ const randomIndex = Math.floor(Math.random() * state.items.length);
469
+ state.items.splice(randomIndex, 1);
470
+ }, deletionInterval);
471
+
472
+ return () => clearInterval(i);
473
+ }, [periodicDeletions, deletionInterval, state.items]);
474
+
475
+ const onUpdate = useCallback((...args: any[]) => {}, []);
476
+ const columns = useMemo(() => makeColumns(onUpdate), []);
477
+
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
+ };
496
+
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,
507
+ },
508
+ };