@dxos/plugin-sheet 0.6.11-staging.e6894a4 → 0.6.12-main.15a606f

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 (261) hide show
  1. package/dist/lib/browser/SheetContainer-V4GCCZTX.mjs +261 -0
  2. package/dist/lib/browser/SheetContainer-V4GCCZTX.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-P7SSL3EG.mjs → chunk-6ZMQVB4Z.mjs} +359 -671
  4. package/dist/lib/browser/chunk-6ZMQVB4Z.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-JRL5LGCE.mjs → chunk-QILRZNE5.mjs} +2 -5
  6. package/dist/lib/browser/chunk-QILRZNE5.mjs.map +7 -0
  7. package/dist/lib/browser/{chunk-FUAGSXA4.mjs → chunk-T3NJFTD4.mjs} +8 -15
  8. package/dist/lib/browser/chunk-T3NJFTD4.mjs.map +7 -0
  9. package/dist/lib/browser/{SheetContainer-4XOKHKKZ.mjs → chunk-U2JHW3L6.mjs} +1043 -261
  10. package/dist/lib/browser/chunk-U2JHW3L6.mjs.map +7 -0
  11. package/dist/lib/browser/graph-T27BOBOV.mjs +21 -0
  12. package/dist/lib/browser/graph-T27BOBOV.mjs.map +7 -0
  13. package/dist/lib/browser/index.mjs +80 -66
  14. package/dist/lib/browser/index.mjs.map +3 -3
  15. package/dist/lib/browser/meta.json +1 -1
  16. package/dist/lib/browser/meta.mjs +1 -1
  17. package/dist/lib/browser/types.mjs +4 -6
  18. package/dist/lib/node/SheetContainer-3ZY7MPWJ.cjs +279 -0
  19. package/dist/lib/node/SheetContainer-3ZY7MPWJ.cjs.map +7 -0
  20. package/dist/lib/node/{chunk-BJ6ZD7MN.cjs → chunk-BNARJ5GM.cjs} +5 -18
  21. package/dist/lib/node/chunk-BNARJ5GM.cjs.map +7 -0
  22. package/dist/lib/node/{chunk-SVAIIXWQ.cjs → chunk-DD6FIXWC.cjs} +360 -667
  23. package/dist/lib/node/chunk-DD6FIXWC.cjs.map +7 -0
  24. package/dist/lib/node/{SheetContainer-IQT6TR4Z.cjs → chunk-OTTD7FBK.cjs} +1062 -289
  25. package/dist/lib/node/chunk-OTTD7FBK.cjs.map +7 -0
  26. package/dist/lib/node/{chunk-DSYKOI4E.cjs → chunk-Q3HBHPRL.cjs} +12 -20
  27. package/dist/lib/node/chunk-Q3HBHPRL.cjs.map +7 -0
  28. package/dist/lib/node/graph-SPKGX7W4.cjs +43 -0
  29. package/dist/lib/node/graph-SPKGX7W4.cjs.map +7 -0
  30. package/dist/lib/node/index.cjs +93 -72
  31. package/dist/lib/node/index.cjs.map +3 -3
  32. package/dist/lib/node/meta.cjs +3 -3
  33. package/dist/lib/node/meta.cjs.map +1 -1
  34. package/dist/lib/node/meta.json +1 -1
  35. package/dist/lib/node/types.cjs +10 -12
  36. package/dist/lib/node/types.cjs.map +2 -2
  37. package/dist/lib/node-esm/SheetContainer-PXSJX6XK.mjs +262 -0
  38. package/dist/lib/node-esm/SheetContainer-PXSJX6XK.mjs.map +7 -0
  39. package/dist/lib/node-esm/chunk-7HVSOTGA.mjs +2553 -0
  40. package/dist/lib/node-esm/chunk-7HVSOTGA.mjs.map +7 -0
  41. package/dist/lib/node-esm/chunk-BMNA27EX.mjs +76 -0
  42. package/dist/lib/node-esm/chunk-BMNA27EX.mjs.map +7 -0
  43. package/dist/lib/node-esm/chunk-D6KU5MI7.mjs +2925 -0
  44. package/dist/lib/node-esm/chunk-D6KU5MI7.mjs.map +7 -0
  45. package/dist/lib/node-esm/chunk-IU2L277A.mjs +17 -0
  46. package/dist/lib/node-esm/chunk-IU2L277A.mjs.map +7 -0
  47. package/dist/lib/node-esm/graph-U67IO4UC.mjs +22 -0
  48. package/dist/lib/node-esm/graph-U67IO4UC.mjs.map +7 -0
  49. package/dist/lib/node-esm/index.mjs +261 -0
  50. package/dist/lib/node-esm/index.mjs.map +7 -0
  51. package/dist/lib/node-esm/meta.json +1 -0
  52. package/dist/lib/node-esm/meta.mjs +10 -0
  53. package/dist/lib/node-esm/meta.mjs.map +7 -0
  54. package/dist/lib/node-esm/types.mjs +21 -0
  55. package/dist/lib/node-esm/types.mjs.map +7 -0
  56. package/dist/types/src/SheetPlugin.d.ts.map +1 -1
  57. package/dist/types/src/components/CellEditor/CellEditor.d.ts +23 -3
  58. package/dist/types/src/components/CellEditor/CellEditor.d.ts.map +1 -1
  59. package/dist/types/src/components/CellEditor/CellEditor.stories.d.ts +2 -2
  60. package/dist/types/src/components/CellEditor/CellEditor.stories.d.ts.map +1 -1
  61. package/dist/types/src/components/CellEditor/extension.d.ts +1 -1
  62. package/dist/types/src/components/CellEditor/extension.d.ts.map +1 -1
  63. package/dist/types/src/components/ComputeGraph/ComputeGraphContextProvider.d.ts +11 -0
  64. package/dist/types/src/components/ComputeGraph/ComputeGraphContextProvider.d.ts.map +1 -0
  65. package/dist/types/src/components/ComputeGraph/index.d.ts +1 -3
  66. package/dist/types/src/components/ComputeGraph/index.d.ts.map +1 -1
  67. package/dist/types/src/components/GridSheet/GridSheet.d.ts +10 -0
  68. package/dist/types/src/components/GridSheet/GridSheet.d.ts.map +1 -0
  69. package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts +9 -0
  70. package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts.map +1 -0
  71. package/dist/types/src/components/GridSheet/util.d.ts +6 -0
  72. package/dist/types/src/components/GridSheet/util.d.ts.map +1 -0
  73. package/dist/types/src/components/Sheet/Sheet.d.ts +1 -1
  74. package/dist/types/src/components/Sheet/Sheet.d.ts.map +1 -1
  75. package/dist/types/src/components/Sheet/Sheet.stories.d.ts +5 -6
  76. package/dist/types/src/components/Sheet/Sheet.stories.d.ts.map +1 -1
  77. package/dist/types/src/components/Sheet/decorations.d.ts +24 -0
  78. package/dist/types/src/components/Sheet/decorations.d.ts.map +1 -0
  79. package/dist/types/src/components/Sheet/grid.d.ts +2 -2
  80. package/dist/types/src/components/Sheet/grid.d.ts.map +1 -1
  81. package/dist/types/src/components/Sheet/nav.d.ts +3 -3
  82. package/dist/types/src/components/Sheet/nav.d.ts.map +1 -1
  83. package/dist/types/src/components/Sheet/sheet-context.d.ts +6 -5
  84. package/dist/types/src/components/Sheet/sheet-context.d.ts.map +1 -1
  85. package/dist/types/src/components/Sheet/threads.d.ts +2 -0
  86. package/dist/types/src/components/Sheet/threads.d.ts.map +1 -0
  87. package/dist/types/src/components/SheetContainer.d.ts +2 -3
  88. package/dist/types/src/components/SheetContainer.d.ts.map +1 -1
  89. package/dist/types/src/components/Toolbar/Toolbar.d.ts +19 -3
  90. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
  91. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +18 -13
  92. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
  93. package/dist/types/src/components/index.d.ts +2 -2
  94. package/dist/types/src/components/index.d.ts.map +1 -1
  95. package/dist/types/src/defs/index.d.ts +3 -0
  96. package/dist/types/src/defs/index.d.ts.map +1 -0
  97. package/dist/types/src/{model → defs}/types.d.ts +8 -3
  98. package/dist/types/src/defs/types.d.ts.map +1 -0
  99. package/dist/types/src/defs/types.test.d.ts.map +1 -0
  100. package/dist/types/src/defs/util.d.ts +43 -0
  101. package/dist/types/src/defs/util.d.ts.map +1 -0
  102. package/dist/types/src/extensions/compute.d.ts +5 -0
  103. package/dist/types/src/extensions/compute.d.ts.map +1 -0
  104. package/dist/types/src/extensions/compute.stories.d.ts +26 -0
  105. package/dist/types/src/extensions/compute.stories.d.ts.map +1 -0
  106. package/dist/types/src/extensions/index.d.ts +2 -0
  107. package/dist/types/src/extensions/index.d.ts.map +1 -0
  108. package/dist/types/src/{components/ComputeGraph → graph}/async-function.d.ts +1 -1
  109. package/dist/types/src/graph/async-function.d.ts.map +1 -0
  110. package/dist/types/src/graph/compute-graph.browser.test.d.ts +2 -0
  111. package/dist/types/src/graph/compute-graph.browser.test.d.ts.map +1 -0
  112. package/dist/types/src/graph/compute-graph.d.ts +81 -0
  113. package/dist/types/src/graph/compute-graph.d.ts.map +1 -0
  114. package/dist/types/src/graph/compute-graph.stories.d.ts +10 -0
  115. package/dist/types/src/graph/compute-graph.stories.d.ts.map +1 -0
  116. package/dist/types/src/graph/compute-node.d.ts +19 -0
  117. package/dist/types/src/graph/compute-node.d.ts.map +1 -0
  118. package/dist/types/src/{components/ComputeGraph/custom.d.ts → graph/custom-function.d.ts} +1 -1
  119. package/dist/types/src/graph/custom-function.d.ts.map +1 -0
  120. package/dist/types/src/graph/edge-function.d.ts.map +1 -0
  121. package/dist/types/src/{model/functions.d.ts → graph/function-defs.d.ts} +1 -1
  122. package/dist/types/src/graph/function-defs.d.ts.map +1 -0
  123. package/dist/types/src/graph/hyperformula.test.d.ts +2 -0
  124. package/dist/types/src/graph/hyperformula.test.d.ts.map +1 -0
  125. package/dist/types/src/graph/index.d.ts +4 -0
  126. package/dist/types/src/graph/index.d.ts.map +1 -0
  127. package/dist/types/src/graph/util.d.ts +2 -0
  128. package/dist/types/src/graph/util.d.ts.map +1 -0
  129. package/dist/types/src/hooks/hooks.stories.d.ts +11 -0
  130. package/dist/types/src/hooks/hooks.stories.d.ts.map +1 -0
  131. package/dist/types/src/hooks/index.d.ts +4 -0
  132. package/dist/types/src/hooks/index.d.ts.map +1 -0
  133. package/dist/types/src/hooks/useComputeGraph.d.ts +7 -0
  134. package/dist/types/src/hooks/useComputeGraph.d.ts.map +1 -0
  135. package/dist/types/src/hooks/useFormattingModel.d.ts +3 -0
  136. package/dist/types/src/hooks/useFormattingModel.d.ts.map +1 -0
  137. package/dist/types/src/hooks/useSheetModel.d.ts +8 -0
  138. package/dist/types/src/hooks/useSheetModel.d.ts.map +1 -0
  139. package/dist/types/src/meta.d.ts +1 -4
  140. package/dist/types/src/meta.d.ts.map +1 -1
  141. package/dist/types/src/model/formatting-model.d.ts +16 -0
  142. package/dist/types/src/model/formatting-model.d.ts.map +1 -0
  143. package/dist/types/src/model/index.d.ts +2 -3
  144. package/dist/types/src/model/index.d.ts.map +1 -1
  145. package/dist/types/src/model/{model.d.ts → sheet-model.d.ts} +9 -64
  146. package/dist/types/src/model/sheet-model.d.ts.map +1 -0
  147. package/dist/types/src/sanity.test.d.ts +2 -0
  148. package/dist/types/src/sanity.test.d.ts.map +1 -0
  149. package/dist/types/src/testing/index.d.ts +2 -0
  150. package/dist/types/src/testing/index.d.ts.map +1 -0
  151. package/dist/types/src/testing/testing.d.ts +9 -0
  152. package/dist/types/src/testing/testing.d.ts.map +1 -0
  153. package/dist/types/src/translations.d.ts +17 -12
  154. package/dist/types/src/translations.d.ts.map +1 -1
  155. package/dist/types/src/types.d.ts +83 -3
  156. package/dist/types/src/types.d.ts.map +1 -1
  157. package/dist/vendor/hyperformula.mjs +37145 -0
  158. package/package.json +48 -41
  159. package/src/SheetPlugin.tsx +51 -72
  160. package/src/components/CellEditor/CellEditor.stories.tsx +4 -3
  161. package/src/components/CellEditor/CellEditor.tsx +59 -9
  162. package/src/components/CellEditor/extension.test.ts +4 -5
  163. package/src/components/CellEditor/extension.ts +1 -3
  164. package/src/components/ComputeGraph/ComputeGraphContextProvider.tsx +20 -0
  165. package/src/components/ComputeGraph/index.ts +1 -3
  166. package/src/components/GridSheet/GridSheet.stories.tsx +35 -0
  167. package/src/components/GridSheet/GridSheet.tsx +153 -0
  168. package/src/components/GridSheet/util.ts +89 -0
  169. package/src/components/Sheet/Sheet.stories.tsx +48 -87
  170. package/src/components/Sheet/Sheet.tsx +69 -39
  171. package/src/components/Sheet/decorations.ts +62 -0
  172. package/src/components/Sheet/grid.ts +3 -3
  173. package/src/components/Sheet/nav.ts +19 -19
  174. package/src/components/Sheet/sheet-context.tsx +16 -78
  175. package/src/components/Sheet/threads.tsx +205 -0
  176. package/src/components/SheetContainer.tsx +73 -21
  177. package/src/components/Toolbar/Toolbar.stories.tsx +5 -10
  178. package/src/components/Toolbar/Toolbar.tsx +53 -12
  179. package/src/components/index.ts +1 -0
  180. package/src/defs/index.ts +6 -0
  181. package/src/{model → defs}/types.test.ts +8 -9
  182. package/src/{model → defs}/types.ts +23 -14
  183. package/src/defs/util.ts +135 -0
  184. package/src/extensions/compute.stories.tsx +151 -0
  185. package/src/extensions/compute.ts +98 -0
  186. package/src/extensions/index.ts +5 -0
  187. package/src/{components/ComputeGraph → graph}/async-function.ts +3 -1
  188. package/src/graph/compute-graph.browser.test.ts +104 -0
  189. package/src/graph/compute-graph.stories.tsx +92 -0
  190. package/src/graph/compute-graph.ts +290 -0
  191. package/src/graph/compute-node.ts +51 -0
  192. package/src/{components/ComputeGraph/custom.ts → graph/custom-function.ts} +2 -6
  193. package/src/{components/ComputeGraph → graph}/edge-function.ts +2 -1
  194. package/src/graph/hyperformula.test.ts +15 -0
  195. package/src/graph/index.ts +7 -0
  196. package/src/graph/util.ts +8 -0
  197. package/src/hooks/hooks.stories.tsx +50 -0
  198. package/src/hooks/index.ts +7 -0
  199. package/src/hooks/useComputeGraph.ts +20 -0
  200. package/src/hooks/useFormattingModel.ts +11 -0
  201. package/src/hooks/useSheetModel.ts +43 -0
  202. package/src/meta.tsx +1 -5
  203. package/src/{components/Sheet/formatting.ts → model/formatting-model.ts} +20 -13
  204. package/src/model/index.ts +2 -3
  205. package/src/model/sheet-model.ts +399 -0
  206. package/src/sanity.test.ts +40 -0
  207. package/src/testing/index.ts +5 -0
  208. package/src/testing/testing.tsx +66 -0
  209. package/src/translations.ts +6 -1
  210. package/src/types.ts +30 -5
  211. package/dist/lib/browser/SheetContainer-4XOKHKKZ.mjs.map +0 -7
  212. package/dist/lib/browser/chunk-FUAGSXA4.mjs.map +0 -7
  213. package/dist/lib/browser/chunk-FWGRE3EG.mjs +0 -175
  214. package/dist/lib/browser/chunk-FWGRE3EG.mjs.map +0 -7
  215. package/dist/lib/browser/chunk-JRL5LGCE.mjs.map +0 -7
  216. package/dist/lib/browser/chunk-P7SSL3EG.mjs.map +0 -7
  217. package/dist/lib/browser/chunk-YPU3R7FA.mjs +0 -8
  218. package/dist/lib/browser/chunk-YPU3R7FA.mjs.map +0 -7
  219. package/dist/lib/browser/testing.mjs +0 -92
  220. package/dist/lib/browser/testing.mjs.map +0 -7
  221. package/dist/lib/node/SheetContainer-IQT6TR4Z.cjs.map +0 -7
  222. package/dist/lib/node/chunk-5EPCDAZC.cjs +0 -40
  223. package/dist/lib/node/chunk-5EPCDAZC.cjs.map +0 -7
  224. package/dist/lib/node/chunk-727C6YNP.cjs +0 -202
  225. package/dist/lib/node/chunk-727C6YNP.cjs.map +0 -7
  226. package/dist/lib/node/chunk-BJ6ZD7MN.cjs.map +0 -7
  227. package/dist/lib/node/chunk-DSYKOI4E.cjs.map +0 -7
  228. package/dist/lib/node/chunk-SVAIIXWQ.cjs.map +0 -7
  229. package/dist/lib/node/testing.cjs +0 -111
  230. package/dist/lib/node/testing.cjs.map +0 -7
  231. package/dist/types/src/components/ComputeGraph/async-function.d.ts.map +0 -1
  232. package/dist/types/src/components/ComputeGraph/custom.d.ts.map +0 -1
  233. package/dist/types/src/components/ComputeGraph/edge-function.d.ts.map +0 -1
  234. package/dist/types/src/components/ComputeGraph/graph-context.d.ts +0 -12
  235. package/dist/types/src/components/ComputeGraph/graph-context.d.ts.map +0 -1
  236. package/dist/types/src/components/ComputeGraph/graph.browser.test.d.ts +0 -2
  237. package/dist/types/src/components/ComputeGraph/graph.browser.test.d.ts.map +0 -1
  238. package/dist/types/src/components/ComputeGraph/graph.d.ts +0 -26
  239. package/dist/types/src/components/ComputeGraph/graph.d.ts.map +0 -1
  240. package/dist/types/src/components/Sheet/formatting.d.ts +0 -14
  241. package/dist/types/src/components/Sheet/formatting.d.ts.map +0 -1
  242. package/dist/types/src/model/functions.d.ts.map +0 -1
  243. package/dist/types/src/model/model.browser.test.d.ts +0 -2
  244. package/dist/types/src/model/model.browser.test.d.ts.map +0 -1
  245. package/dist/types/src/model/model.d.ts.map +0 -1
  246. package/dist/types/src/model/types.d.ts.map +0 -1
  247. package/dist/types/src/model/types.test.d.ts.map +0 -1
  248. package/dist/types/src/model/util.d.ts +0 -15
  249. package/dist/types/src/model/util.d.ts.map +0 -1
  250. package/dist/types/src/testing.d.ts +0 -9
  251. package/dist/types/src/testing.d.ts.map +0 -1
  252. package/src/components/ComputeGraph/graph-context.tsx +0 -50
  253. package/src/components/ComputeGraph/graph.browser.test.ts +0 -50
  254. package/src/components/ComputeGraph/graph.ts +0 -62
  255. package/src/model/model.browser.test.ts +0 -100
  256. package/src/model/model.ts +0 -551
  257. package/src/model/util.ts +0 -36
  258. package/src/testing.ts +0 -50
  259. /package/dist/types/src/{model → defs}/types.test.d.ts +0 -0
  260. /package/dist/types/src/{components/ComputeGraph → graph}/edge-function.d.ts +0 -0
  261. /package/src/{model/functions.ts → graph/function-defs.ts} +0 -0
@@ -0,0 +1,153 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { useCallback, useMemo, useRef } from 'react';
6
+
7
+ import { type Space } from '@dxos/client/echo';
8
+ import {
9
+ type DxGridElement,
10
+ Grid,
11
+ type GridContentProps,
12
+ type GridScopedProps,
13
+ useGridContext,
14
+ } from '@dxos/react-ui-grid';
15
+
16
+ import { dxGridCellIndexToSheetCellAddress, useSheetModelDxGridProps } from './util';
17
+ import { rangeToA1Notation, type CellRange } from '../../defs';
18
+ import { useFormattingModel, useSheetModel, type UseSheetModelOptions } from '../../hooks';
19
+ import { type SheetModel, type FormattingModel } from '../../model';
20
+ import { type SheetType } from '../../types';
21
+ import {
22
+ CellEditor,
23
+ type CellEditorProps,
24
+ type CellRangeNotifier,
25
+ editorKeys,
26
+ type EditorKeysProps,
27
+ rangeExtension,
28
+ sheetExtension,
29
+ } from '../CellEditor';
30
+
31
+ const GridSheetCellEditor = ({
32
+ model,
33
+ extension,
34
+ __gridScope,
35
+ }: GridScopedProps<Pick<CellEditorProps, 'extension'> & { model: SheetModel }>) => {
36
+ const { id, editing, setEditing, editBox } = useGridContext('GridSheetCellEditor', __gridScope);
37
+ const cell = dxGridCellIndexToSheetCellAddress(editing);
38
+
39
+ return editing ? (
40
+ <CellEditor
41
+ variant='grid'
42
+ value={editing.initialContent ?? (cell ? model.getCellText(cell) : undefined)}
43
+ autoFocus
44
+ box={editBox}
45
+ onBlur={() => setEditing(null)}
46
+ extension={extension}
47
+ gridId={id}
48
+ />
49
+ ) : null;
50
+ };
51
+
52
+ const sheetRowDefault = { size: 32, resizeable: true };
53
+ const sheetColDefault = { size: 180, resizeable: true };
54
+
55
+ const GridSheetImpl = ({
56
+ model,
57
+ formatting,
58
+ __gridScope,
59
+ }: GridScopedProps<{ model: SheetModel; formatting: FormattingModel }>) => {
60
+ const { editing, setEditing } = useGridContext('GridSheetCellEditor', __gridScope);
61
+ const dxGrid = useRef<DxGridElement | null>(null);
62
+ const rangeNotifier = useRef<CellRangeNotifier>();
63
+
64
+ // TODO(burdon): Validate formula before closing: hf.validateFormula();
65
+ const handleClose = useCallback<NonNullable<EditorKeysProps['onClose']> | NonNullable<EditorKeysProps['onNav']>>(
66
+ (value, { key, shift }) => {
67
+ if (value !== undefined) {
68
+ model.setValue(dxGridCellIndexToSheetCellAddress(editing)!, value);
69
+ }
70
+ setEditing(null);
71
+ const axis = ['Enter', 'ArrowUp', 'ArrowDown'].includes(key)
72
+ ? 'row'
73
+ : ['Tab', 'ArrowLeft', 'ArrowRight'].includes(key)
74
+ ? 'col'
75
+ : undefined;
76
+ const delta = key.startsWith('Arrow') ? (['ArrowUp', 'ArrowLeft'].includes(key) ? -1 : 1) : shift ? -1 : 1;
77
+ dxGrid.current?.refocus(axis, delta);
78
+ },
79
+ [model, editing, setEditing],
80
+ );
81
+
82
+ const handleAxisResize = useCallback<NonNullable<GridContentProps['onAxisResize']>>(
83
+ ({ axis, size, index: numericIndex }) => {
84
+ if (axis === 'row') {
85
+ const rowId = model.sheet.rows[parseInt(numericIndex)];
86
+ model.sheet.rowMeta[rowId] ??= {};
87
+ model.sheet.rowMeta[rowId].size = size;
88
+ } else {
89
+ const columnId = model.sheet.columns[parseInt(numericIndex)];
90
+ model.sheet.columnMeta[columnId] ??= {};
91
+ model.sheet.columnMeta[columnId].size = size;
92
+ }
93
+ },
94
+ [model],
95
+ );
96
+
97
+ const handleSelect = useCallback<NonNullable<GridContentProps['onSelect']>>(
98
+ ({ minCol, maxCol, minRow, maxRow }) => {
99
+ if (editing) {
100
+ const range: CellRange = { from: { col: minCol, row: minRow } };
101
+ if (minCol !== maxCol || minRow !== maxRow) {
102
+ range.to = { col: maxCol, row: maxRow };
103
+ }
104
+ // Update range selection in formula.
105
+ rangeNotifier.current?.(rangeToA1Notation(range));
106
+ }
107
+ },
108
+ [editing],
109
+ );
110
+
111
+ const { cells, columns, rows } = useSheetModelDxGridProps(model, formatting);
112
+
113
+ const extension = useMemo(
114
+ () => [
115
+ editorKeys({ onClose: handleClose, ...(editing?.initialContent && { onNav: handleClose }) }),
116
+ sheetExtension({ functions: model.graph.getFunctions() }),
117
+ rangeExtension((fn) => (rangeNotifier.current = fn)),
118
+ ],
119
+ [model, handleClose, editing],
120
+ );
121
+
122
+ return (
123
+ <>
124
+ <GridSheetCellEditor model={model} extension={extension} />
125
+ <Grid.Content
126
+ cells={cells}
127
+ columns={columns}
128
+ rows={rows}
129
+ onAxisResize={handleAxisResize}
130
+ onSelect={handleSelect}
131
+ rowDefault={sheetRowDefault}
132
+ columnDefault={sheetColDefault}
133
+ ref={dxGrid}
134
+ />
135
+ </>
136
+ );
137
+ };
138
+
139
+ export type GridSheetProps = { space?: Space; sheet?: SheetType } & UseSheetModelOptions;
140
+
141
+ export const GridSheet = ({ space, sheet, ...options }: GridSheetProps) => {
142
+ const model = useSheetModel(space, sheet, options);
143
+ const formatting = useFormattingModel(model);
144
+ if (!model || !formatting) {
145
+ return null;
146
+ }
147
+
148
+ return (
149
+ <Grid.Root id={model.id}>
150
+ <GridSheetImpl model={model} formatting={formatting} />
151
+ </Grid.Root>
152
+ );
153
+ };
@@ -0,0 +1,89 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { useEffect, useState } from 'react';
6
+
7
+ import { createDocAccessor } from '@dxos/react-client/echo';
8
+ import { type GridEditing, type GridContentProps } from '@dxos/react-ui-grid';
9
+ import { mx } from '@dxos/react-ui-theme';
10
+
11
+ import { addressFromIndex, type CellAddress } from '../../defs';
12
+ import { type SheetModel, type FormattingModel } from '../../model';
13
+
14
+ export const dxGridCellIndexToSheetCellAddress = (gridEditing: GridEditing): CellAddress | null => {
15
+ if (!gridEditing) {
16
+ return null;
17
+ }
18
+ const [colStr, rowStr] = gridEditing.index.split(',');
19
+ return {
20
+ col: parseInt(colStr),
21
+ row: parseInt(rowStr),
22
+ };
23
+ };
24
+
25
+ const createDxGridCells = (model: SheetModel, formatting: FormattingModel) => {
26
+ return Object.keys(model.sheet.cells).reduce((acc: NonNullable<GridContentProps['cells']>, sheetCellIndex) => {
27
+ const address = addressFromIndex(model.sheet, sheetCellIndex);
28
+ const cell = formatting.getFormatting(address);
29
+ if (cell.value) {
30
+ acc[`${address.col},${address.row}`] = { value: cell.value, className: mx(cell.classNames) };
31
+ }
32
+ return acc;
33
+ }, {});
34
+ };
35
+
36
+ const createDxGridColumns = (model: SheetModel): GridContentProps['columns'] => {
37
+ return model.sheet.columns.reduce((acc: NonNullable<GridContentProps['columns']>, columnId, numericIndex) => {
38
+ if (model.sheet.columnMeta[columnId] && model.sheet.columnMeta[columnId].size) {
39
+ acc[numericIndex] = { size: model.sheet.columnMeta[columnId].size, resizeable: true };
40
+ }
41
+ return acc;
42
+ }, {});
43
+ };
44
+
45
+ const createDxGridRows = (model: SheetModel): GridContentProps['rows'] => {
46
+ return model.sheet.rows.reduce((acc: NonNullable<GridContentProps['rows']>, rowId, numericIndex) => {
47
+ if (model.sheet.rowMeta[rowId] && model.sheet.rowMeta[rowId].size) {
48
+ acc[numericIndex] = { size: model.sheet.rowMeta[rowId].size, resizeable: true };
49
+ }
50
+ return acc;
51
+ }, {});
52
+ };
53
+
54
+ export const useSheetModelDxGridProps = (
55
+ model: SheetModel,
56
+ formatting: FormattingModel,
57
+ ): Pick<GridContentProps, 'cells' | 'columns' | 'rows'> => {
58
+ const [dxGridCells, setDxGridCells] = useState<GridContentProps['cells']>(createDxGridCells(model, formatting));
59
+ const [dxGridColumns, setDxGridColumns] = useState<GridContentProps['columns']>(createDxGridColumns(model));
60
+ const [dxGridRows, setDxGridRows] = useState<GridContentProps['rows']>(createDxGridColumns(model));
61
+
62
+ useEffect(() => {
63
+ const cellsAccessor = createDocAccessor(model.sheet, ['cells']);
64
+ const handleCellsUpdate = () => {
65
+ setDxGridCells(createDxGridCells(model, formatting));
66
+ };
67
+ cellsAccessor.handle.addListener('change', handleCellsUpdate);
68
+ return () => cellsAccessor.handle.removeListener('change', handleCellsUpdate);
69
+ }, [model, formatting]);
70
+
71
+ useEffect(() => {
72
+ const columnMetaAccessor = createDocAccessor(model.sheet, ['columnMeta']);
73
+ const rowMetaAccessor = createDocAccessor(model.sheet, ['rowMeta']);
74
+ const handleColumnMetaUpdate = () => {
75
+ setDxGridColumns(createDxGridColumns(model));
76
+ };
77
+ const handleRowMetaUpdate = () => {
78
+ setDxGridRows(createDxGridRows(model));
79
+ };
80
+ columnMetaAccessor.handle.addListener('change', handleColumnMetaUpdate);
81
+ rowMetaAccessor.handle.addListener('change', handleRowMetaUpdate);
82
+ return () => {
83
+ columnMetaAccessor.handle.removeListener('change', handleColumnMetaUpdate);
84
+ rowMetaAccessor.handle.removeListener('change', handleRowMetaUpdate);
85
+ };
86
+ }, [model]);
87
+
88
+ return { cells: dxGridCells, columns: dxGridColumns, rows: dxGridRows };
89
+ };
@@ -4,31 +4,33 @@
4
4
 
5
5
  import '@dxos-theme';
6
6
 
7
- import { type Decorator } from '@storybook/react';
8
- import React, { useContext, useEffect, useState } from 'react';
7
+ import React, { useState } from 'react';
9
8
 
10
- import { Client } from '@dxos/client';
11
- import { type EchoReactiveObject } from '@dxos/echo-schema';
12
9
  import { log } from '@dxos/log';
13
- import { getSpace, type Space } from '@dxos/react-client/echo';
14
- import { Button, Tooltip } from '@dxos/react-ui';
10
+ import { type Space, useSpace } from '@dxos/react-client/echo';
11
+ import { withClientProvider } from '@dxos/react-client/testing';
12
+ import { Button } from '@dxos/react-ui';
15
13
  import { mx } from '@dxos/react-ui-theme';
16
- import { withTheme, withFullscreen } from '@dxos/storybook-utils';
14
+ import { withLayout, withTheme } from '@dxos/storybook-utils';
17
15
 
18
16
  import { Sheet } from './Sheet';
19
17
  import { type SizeMap } from './grid';
20
18
  import { useSheetContext } from './sheet-context';
21
- import { createTestSheet, testSheetName } from '../../testing';
22
- import { ValueTypeEnum, SheetType } from '../../types';
23
- import { type ComputeGraph, createComputeGraph } from '../ComputeGraph';
24
- // TODO(wittjosiah): Refactor. This is not exported from ./components due to depending on ECHO.
25
- import { ComputeGraphContext, ComputeGraphContextProvider, useComputeGraph } from '../ComputeGraph/graph-context';
19
+ import { addressToIndex, rangeToIndex } from '../../defs';
20
+ import { useComputeGraph } from '../../hooks';
21
+ import { useTestSheet, withGraphDecorator } from '../../testing';
22
+ import { SheetType, ValueTypeEnum } from '../../types';
26
23
  import { Toolbar, type ToolbarActionHandler } from '../Toolbar';
27
24
 
28
25
  // TODO(burdon): Allow toolbar to access sheet context; provide state for current cursor/range.
29
26
  const SheetWithToolbar = ({ debug, space }: { debug?: boolean; space: Space }) => {
30
27
  const { model, cursor, range } = useSheetContext();
31
28
 
29
+ const graph = useComputeGraph(space);
30
+ const handleRefresh = () => {
31
+ graph?.refresh();
32
+ };
33
+
32
34
  // TODO(burdon): Factor out.
33
35
  const handleAction: ToolbarActionHandler = ({ type }) => {
34
36
  log.info('action', { type, cursor, range });
@@ -36,7 +38,7 @@ const SheetWithToolbar = ({ debug, space }: { debug?: boolean; space: Space }) =
36
38
  return;
37
39
  }
38
40
 
39
- const idx = range ? model.rangeToIndex(range) : model.addressToIndex(cursor);
41
+ const idx = range ? rangeToIndex(model.sheet, range) : addressToIndex(model.sheet, cursor);
40
42
  model.sheet.formatting[idx] ??= {};
41
43
  const format = model.sheet.formatting[idx];
42
44
 
@@ -75,14 +77,12 @@ const SheetWithToolbar = ({ debug, space }: { debug?: boolean; space: Space }) =
75
77
  format.precision = 2;
76
78
  break;
77
79
  }
80
+ case 'comment': {
81
+ break;
82
+ }
78
83
  }
79
84
  };
80
85
 
81
- const graph = useComputeGraph(space);
82
- const handleRefresh = () => {
83
- graph.refresh();
84
- };
85
-
86
86
  return (
87
87
  <div className='flex flex-col overflow-hidden'>
88
88
  <Toolbar.Root onAction={handleAction}>
@@ -99,58 +99,43 @@ const SheetWithToolbar = ({ debug, space }: { debug?: boolean; space: Space }) =
99
99
  );
100
100
  };
101
101
 
102
- const withGraphDecorator: Decorator = (Story) => {
103
- const [graphs, setGraphs] = useState<Record<string, ComputeGraph>>({});
104
-
105
- const setGraph = (key: string, graph: ComputeGraph) => {
106
- if (!graph.hf.doesSheetExist(testSheetName)) {
107
- const sheetName = graph.hf.addSheet(testSheetName);
108
- const sheet = graph.hf.getSheetId(sheetName)!;
109
- graph.hf.setCellContents({ sheet, col: 0, row: 0 }, Math.random());
110
- }
111
-
112
- setGraphs((graphs) => ({ ...graphs, [key]: graph }));
113
- };
114
-
115
- return (
116
- <ComputeGraphContextProvider graphs={graphs} setGraph={setGraph}>
117
- <Story />
118
- </ComputeGraphContextProvider>
119
- );
120
- };
121
-
122
102
  export default {
123
103
  title: 'plugin-sheet/Sheet',
124
104
  component: Sheet,
125
- decorators: [withGraphDecorator, withTheme, withFullscreen({ classNames: 'inset-4' })],
105
+ decorators: [
106
+ withClientProvider({ types: [SheetType], createIdentity: true }),
107
+ withGraphDecorator,
108
+ withTheme,
109
+ withLayout({ fullscreen: true, tooltips: true, classNames: 'inset-4' }),
110
+ ],
126
111
  };
127
112
 
128
113
  export const Default = () => {
129
114
  const [debug, setDebug] = useState(false);
130
- const sheet = useTestSheet();
131
- const space = getSpace(sheet);
132
- if (!sheet || !space) {
115
+ const space = useSpace();
116
+ const graph = useComputeGraph(space);
117
+ const sheet = useTestSheet(space, graph);
118
+ if (!space || !sheet) {
133
119
  return null;
134
120
  }
135
121
 
136
122
  return (
137
- <Tooltip.Provider>
138
- <Sheet.Root sheet={sheet} space={space} onInfo={() => setDebug((debug) => !debug)}>
139
- <SheetWithToolbar debug={debug} space={space} />
140
- </Sheet.Root>
141
- </Tooltip.Provider>
123
+ <Sheet.Root space={space} sheet={sheet} onInfo={() => setDebug((debug) => !debug)}>
124
+ <SheetWithToolbar debug={debug} space={space} />
125
+ </Sheet.Root>
142
126
  );
143
127
  };
144
128
 
145
129
  export const Debug = () => {
146
- const sheet = useTestSheet();
147
- const space = getSpace(sheet);
130
+ const space = useSpace();
131
+ const graph = useComputeGraph(space);
132
+ const sheet = useTestSheet(space, graph);
148
133
  if (!sheet || !space) {
149
134
  return null;
150
135
  }
151
136
 
152
137
  return (
153
- <Sheet.Root sheet={sheet} space={space}>
138
+ <Sheet.Root space={space} sheet={sheet}>
154
139
  <Sheet.Main />
155
140
  <Sheet.Debug />
156
141
  </Sheet.Root>
@@ -159,14 +144,15 @@ export const Debug = () => {
159
144
 
160
145
  export const Rows = () => {
161
146
  const [rowSizes, setRowSizes] = useState<SizeMap>({});
162
- const sheet = useTestSheet();
163
- const space = getSpace(sheet);
147
+ const space = useSpace();
148
+ const graph = useComputeGraph(space);
149
+ const sheet = useTestSheet(space, graph);
164
150
  if (!sheet || !space) {
165
151
  return null;
166
152
  }
167
153
 
168
154
  return (
169
- <Sheet.Root sheet={sheet} space={space}>
155
+ <Sheet.Root space={space} sheet={sheet}>
170
156
  <Sheet.Rows
171
157
  rows={sheet.rows}
172
158
  sizes={rowSizes}
@@ -178,14 +164,15 @@ export const Rows = () => {
178
164
 
179
165
  export const Columns = () => {
180
166
  const [columnSizes, setColumnSizes] = useState<SizeMap>({});
181
- const sheet = useTestSheet();
182
- const space = getSpace(sheet);
167
+ const space = useSpace();
168
+ const graph = useComputeGraph(space);
169
+ const sheet = useTestSheet(space, graph);
183
170
  if (!sheet || !space) {
184
171
  return null;
185
172
  }
186
173
 
187
174
  return (
188
- <Sheet.Root sheet={sheet} space={space}>
175
+ <Sheet.Root space={space} sheet={sheet}>
189
176
  <Sheet.Columns
190
177
  columns={sheet.columns}
191
178
  sizes={columnSizes}
@@ -196,18 +183,19 @@ export const Columns = () => {
196
183
  };
197
184
 
198
185
  export const Main = () => {
199
- const sheet = useTestSheet();
200
- const space = getSpace(sheet);
186
+ const space = useSpace();
187
+ const graph = useComputeGraph(space);
188
+ const sheet = useTestSheet(space, graph);
201
189
  if (!sheet || !space) {
202
190
  return null;
203
191
  }
204
192
 
205
193
  return (
206
- <Sheet.Root sheet={sheet} space={space}>
194
+ <Sheet.Root space={space} sheet={sheet}>
207
195
  <Sheet.Grid
208
196
  size={{
209
197
  numRows: 50,
210
- numColumns: 26,
198
+ numCols: 26,
211
199
  }}
212
200
  rows={sheet.rows}
213
201
  columns={sheet.columns}
@@ -260,30 +248,3 @@ export const GridLayout = () => {
260
248
  const Cell = ({ className, label }: { className?: string; label: string }) => (
261
249
  <div className={mx('flex items-center justify-center border', className)}>{label}</div>
262
250
  );
263
-
264
- const useTestSheet = () => {
265
- const { graphs, setGraph } = useContext(ComputeGraphContext);
266
- const [sheet, setSheet] = useState<EchoReactiveObject<SheetType>>();
267
- useEffect(() => {
268
- const t = setTimeout(async () => {
269
- const client = new Client();
270
- await client.initialize();
271
- await client.halo.createIdentity();
272
- const space = await client.spaces.create();
273
- client.addTypes([SheetType]);
274
-
275
- const graph = graphs[space.id] ?? createComputeGraph();
276
- if (!graphs[space.id]) {
277
- setGraph(space.id, graph);
278
- }
279
-
280
- const sheet = await createTestSheet({ graph });
281
- space.db.add(sheet);
282
- setSheet(sheet);
283
- });
284
-
285
- return () => clearTimeout(t);
286
- }, []);
287
-
288
- return sheet;
289
- };