@dxos/plugin-sheet 0.6.11 → 0.6.12-main.568932b

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 (277) hide show
  1. package/dist/lib/browser/SheetContainer-T2QWJOFD.mjs +262 -0
  2. package/dist/lib/browser/SheetContainer-T2QWJOFD.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-FUAGSXA4.mjs → chunk-5ZMVZYGB.mjs} +24 -19
  4. package/dist/lib/browser/chunk-5ZMVZYGB.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-GSV5QNLD.mjs +2966 -0
  6. package/dist/lib/browser/chunk-GSV5QNLD.mjs.map +7 -0
  7. package/dist/lib/browser/{chunk-JRL5LGCE.mjs → chunk-QILRZNE5.mjs} +2 -5
  8. package/dist/lib/browser/chunk-QILRZNE5.mjs.map +7 -0
  9. package/dist/lib/browser/{SheetContainer-U4H5D34A.mjs → chunk-ZL2V5UJR.mjs} +1182 -249
  10. package/dist/lib/browser/chunk-ZL2V5UJR.mjs.map +7 -0
  11. package/dist/lib/browser/graph-M4IQ76QX.mjs +33 -0
  12. package/dist/lib/browser/graph-M4IQ76QX.mjs.map +7 -0
  13. package/dist/lib/browser/index.mjs +96 -60
  14. package/dist/lib/browser/index.mjs.map +4 -4
  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-PV5ET4UJ.cjs +280 -0
  19. package/dist/lib/node/SheetContainer-PV5ET4UJ.cjs.map +7 -0
  20. package/dist/lib/node/{SheetContainer-AXQV3ZT5.cjs → chunk-2K53Z2TU.cjs} +1212 -287
  21. package/dist/lib/node/chunk-2K53Z2TU.cjs.map +7 -0
  22. package/dist/lib/node/{chunk-5KKJ4NPP.cjs → chunk-5XPK2V4A.cjs} +418 -678
  23. package/dist/lib/node/chunk-5XPK2V4A.cjs.map +7 -0
  24. package/dist/lib/node/{chunk-BJ6ZD7MN.cjs → chunk-BNARJ5GM.cjs} +5 -18
  25. package/dist/lib/node/chunk-BNARJ5GM.cjs.map +7 -0
  26. package/dist/lib/node/{chunk-DSYKOI4E.cjs → chunk-STAVQ2JE.cjs} +28 -24
  27. package/dist/lib/node/chunk-STAVQ2JE.cjs.map +7 -0
  28. package/dist/lib/node/graph-Q3N2X26H.cjs +55 -0
  29. package/dist/lib/node/graph-Q3N2X26H.cjs.map +7 -0
  30. package/dist/lib/node/index.cjs +106 -66
  31. package/dist/lib/node/index.cjs.map +4 -4
  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-FOZD2WLT.mjs +263 -0
  38. package/dist/lib/node-esm/SheetContainer-FOZD2WLT.mjs.map +7 -0
  39. package/dist/lib/node-esm/chunk-2HAM45RC.mjs +88 -0
  40. package/dist/lib/node-esm/chunk-2HAM45RC.mjs.map +7 -0
  41. package/dist/lib/{browser/chunk-D5AGLXJP.mjs → node-esm/chunk-5WPZCXNS.mjs} +411 -678
  42. package/dist/lib/node-esm/chunk-5WPZCXNS.mjs.map +7 -0
  43. package/dist/lib/node-esm/chunk-IU2L277A.mjs +17 -0
  44. package/dist/lib/node-esm/chunk-IU2L277A.mjs.map +7 -0
  45. package/dist/lib/node-esm/chunk-QEUCIHIN.mjs +2706 -0
  46. package/dist/lib/node-esm/chunk-QEUCIHIN.mjs.map +7 -0
  47. package/dist/lib/node-esm/graph-SMPUMOV2.mjs +34 -0
  48. package/dist/lib/node-esm/graph-SMPUMOV2.mjs.map +7 -0
  49. package/dist/lib/node-esm/index.mjs +285 -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 +16 -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 +8 -7
  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 +6 -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/graph/compute-graph-registry.d.ts +34 -0
  109. package/dist/types/src/graph/compute-graph-registry.d.ts.map +1 -0
  110. package/dist/types/src/graph/compute-graph.d.ts +64 -0
  111. package/dist/types/src/graph/compute-graph.d.ts.map +1 -0
  112. package/dist/types/src/graph/compute-graph.stories.d.ts +10 -0
  113. package/dist/types/src/graph/compute-graph.stories.d.ts.map +1 -0
  114. package/dist/types/src/graph/compute-graph.test.d.ts +2 -0
  115. package/dist/types/src/graph/compute-graph.test.d.ts.map +1 -0
  116. package/dist/types/src/graph/compute-node.d.ts +26 -0
  117. package/dist/types/src/graph/compute-node.d.ts.map +1 -0
  118. package/dist/types/src/{components/ComputeGraph → graph/functions}/async-function.d.ts +14 -5
  119. package/dist/types/src/graph/functions/async-function.d.ts.map +1 -0
  120. package/dist/types/src/graph/functions/edge-function.d.ts +21 -0
  121. package/dist/types/src/graph/functions/edge-function.d.ts.map +1 -0
  122. package/dist/types/src/{model/functions.d.ts → graph/functions/function-defs.d.ts} +1 -1
  123. package/dist/types/src/graph/functions/function-defs.d.ts.map +1 -0
  124. package/dist/types/src/graph/functions/index.d.ts +4 -0
  125. package/dist/types/src/graph/functions/index.d.ts.map +1 -0
  126. package/dist/types/src/graph/hyperformula.test.d.ts +2 -0
  127. package/dist/types/src/graph/hyperformula.test.d.ts.map +1 -0
  128. package/dist/types/src/graph/index.d.ts +5 -0
  129. package/dist/types/src/graph/index.d.ts.map +1 -0
  130. package/dist/types/src/graph/testing/index.d.ts +3 -0
  131. package/dist/types/src/graph/testing/index.d.ts.map +1 -0
  132. package/dist/types/src/graph/testing/test-builder.d.ts +15 -0
  133. package/dist/types/src/graph/testing/test-builder.d.ts.map +1 -0
  134. package/dist/types/src/graph/testing/test-plugin.d.ts +36 -0
  135. package/dist/types/src/graph/testing/test-plugin.d.ts.map +1 -0
  136. package/dist/types/src/graph/util.d.ts +2 -0
  137. package/dist/types/src/graph/util.d.ts.map +1 -0
  138. package/dist/types/src/hooks/hooks.stories.d.ts +11 -0
  139. package/dist/types/src/hooks/hooks.stories.d.ts.map +1 -0
  140. package/dist/types/src/hooks/index.d.ts +4 -0
  141. package/dist/types/src/hooks/index.d.ts.map +1 -0
  142. package/dist/types/src/hooks/useComputeGraph.d.ts +7 -0
  143. package/dist/types/src/hooks/useComputeGraph.d.ts.map +1 -0
  144. package/dist/types/src/hooks/useFormattingModel.d.ts +3 -0
  145. package/dist/types/src/hooks/useFormattingModel.d.ts.map +1 -0
  146. package/dist/types/src/hooks/useSheetModel.d.ts +8 -0
  147. package/dist/types/src/hooks/useSheetModel.d.ts.map +1 -0
  148. package/dist/types/src/meta.d.ts +1 -4
  149. package/dist/types/src/meta.d.ts.map +1 -1
  150. package/dist/types/src/model/formatting-model.d.ts +16 -0
  151. package/dist/types/src/model/formatting-model.d.ts.map +1 -0
  152. package/dist/types/src/model/index.d.ts +2 -3
  153. package/dist/types/src/model/index.d.ts.map +1 -1
  154. package/dist/types/src/model/{model.d.ts → sheet-model.d.ts} +10 -65
  155. package/dist/types/src/model/sheet-model.d.ts.map +1 -0
  156. package/dist/types/src/model/sheet-model.test.d.ts +2 -0
  157. package/dist/types/src/model/sheet-model.test.d.ts.map +1 -0
  158. package/dist/types/src/sanity.test.d.ts +2 -0
  159. package/dist/types/src/sanity.test.d.ts.map +1 -0
  160. package/dist/types/src/testing/index.d.ts +2 -0
  161. package/dist/types/src/testing/index.d.ts.map +1 -0
  162. package/dist/types/src/testing/testing.d.ts +8 -0
  163. package/dist/types/src/testing/testing.d.ts.map +1 -0
  164. package/dist/types/src/translations.d.ts +17 -12
  165. package/dist/types/src/translations.d.ts.map +1 -1
  166. package/dist/types/src/types.d.ts +86 -5
  167. package/dist/types/src/types.d.ts.map +1 -1
  168. package/dist/vendor/hyperformula.mjs +37145 -0
  169. package/package.json +55 -47
  170. package/src/SheetPlugin.tsx +50 -73
  171. package/src/components/CellEditor/CellEditor.stories.tsx +6 -6
  172. package/src/components/CellEditor/CellEditor.tsx +59 -9
  173. package/src/components/CellEditor/extension.test.ts +4 -6
  174. package/src/components/CellEditor/extension.ts +5 -6
  175. package/src/components/ComputeGraph/ComputeGraphContextProvider.tsx +20 -0
  176. package/src/components/ComputeGraph/index.ts +1 -3
  177. package/src/components/GridSheet/GridSheet.stories.tsx +36 -0
  178. package/src/components/GridSheet/GridSheet.tsx +171 -0
  179. package/src/components/GridSheet/util.ts +148 -0
  180. package/src/components/Sheet/Sheet.stories.tsx +52 -88
  181. package/src/components/Sheet/Sheet.tsx +87 -32
  182. package/src/components/Sheet/decorations.ts +62 -0
  183. package/src/components/Sheet/grid.ts +3 -3
  184. package/src/components/Sheet/nav.ts +19 -19
  185. package/src/components/Sheet/sheet-context.tsx +18 -80
  186. package/src/components/Sheet/threads.tsx +205 -0
  187. package/src/components/SheetContainer.tsx +68 -16
  188. package/src/components/Toolbar/Toolbar.tsx +53 -12
  189. package/src/components/index.ts +1 -0
  190. package/src/defs/index.ts +6 -0
  191. package/src/{model → defs}/types.test.ts +8 -9
  192. package/src/{model → defs}/types.ts +24 -14
  193. package/src/defs/util.ts +151 -0
  194. package/src/extensions/compute.stories.tsx +151 -0
  195. package/src/extensions/compute.ts +147 -0
  196. package/src/extensions/index.ts +5 -0
  197. package/src/graph/compute-graph-registry.ts +90 -0
  198. package/src/graph/compute-graph.stories.tsx +93 -0
  199. package/src/graph/compute-graph.test.ts +87 -0
  200. package/src/graph/compute-graph.ts +242 -0
  201. package/src/graph/compute-node.ts +63 -0
  202. package/src/{components/ComputeGraph → graph/functions}/async-function.ts +25 -15
  203. package/src/{components/ComputeGraph → graph/functions}/edge-function.ts +16 -14
  204. package/src/graph/functions/index.ts +7 -0
  205. package/src/graph/hyperformula.test.ts +14 -0
  206. package/src/graph/index.ts +8 -0
  207. package/src/graph/testing/index.ts +6 -0
  208. package/src/graph/testing/test-builder.ts +54 -0
  209. package/src/{components/ComputeGraph/custom.ts → graph/testing/test-plugin.ts} +44 -14
  210. package/src/graph/util.ts +8 -0
  211. package/src/hooks/hooks.stories.tsx +50 -0
  212. package/src/hooks/index.ts +7 -0
  213. package/src/hooks/useComputeGraph.ts +28 -0
  214. package/src/hooks/useFormattingModel.ts +11 -0
  215. package/src/hooks/useSheetModel.ts +40 -0
  216. package/src/meta.tsx +1 -5
  217. package/src/{components/Sheet/formatting.ts → model/formatting-model.ts} +20 -13
  218. package/src/model/index.ts +2 -3
  219. package/src/model/sheet-model.test.ts +57 -0
  220. package/src/model/sheet-model.ts +416 -0
  221. package/src/sanity.test.ts +40 -0
  222. package/src/testing/index.ts +5 -0
  223. package/src/testing/testing.tsx +68 -0
  224. package/src/translations.ts +6 -1
  225. package/src/types.ts +35 -10
  226. package/dist/lib/browser/SheetContainer-U4H5D34A.mjs.map +0 -7
  227. package/dist/lib/browser/chunk-APHOLYUB.mjs +0 -175
  228. package/dist/lib/browser/chunk-APHOLYUB.mjs.map +0 -7
  229. package/dist/lib/browser/chunk-D5AGLXJP.mjs.map +0 -7
  230. package/dist/lib/browser/chunk-FUAGSXA4.mjs.map +0 -7
  231. package/dist/lib/browser/chunk-JRL5LGCE.mjs.map +0 -7
  232. package/dist/lib/browser/chunk-NU4PBN33.mjs +0 -8
  233. package/dist/lib/browser/chunk-NU4PBN33.mjs.map +0 -7
  234. package/dist/lib/browser/testing.mjs +0 -92
  235. package/dist/lib/browser/testing.mjs.map +0 -7
  236. package/dist/lib/node/SheetContainer-AXQV3ZT5.cjs.map +0 -7
  237. package/dist/lib/node/chunk-5KKJ4NPP.cjs.map +0 -7
  238. package/dist/lib/node/chunk-BJ6ZD7MN.cjs.map +0 -7
  239. package/dist/lib/node/chunk-CN3RPESU.cjs +0 -202
  240. package/dist/lib/node/chunk-CN3RPESU.cjs.map +0 -7
  241. package/dist/lib/node/chunk-DSYKOI4E.cjs.map +0 -7
  242. package/dist/lib/node/chunk-PYXHNAAK.cjs +0 -40
  243. package/dist/lib/node/chunk-PYXHNAAK.cjs.map +0 -7
  244. package/dist/lib/node/testing.cjs +0 -111
  245. package/dist/lib/node/testing.cjs.map +0 -7
  246. package/dist/types/src/components/ComputeGraph/async-function.d.ts.map +0 -1
  247. package/dist/types/src/components/ComputeGraph/custom.d.ts +0 -21
  248. package/dist/types/src/components/ComputeGraph/custom.d.ts.map +0 -1
  249. package/dist/types/src/components/ComputeGraph/edge-function.d.ts +0 -20
  250. package/dist/types/src/components/ComputeGraph/edge-function.d.ts.map +0 -1
  251. package/dist/types/src/components/ComputeGraph/graph-context.d.ts +0 -12
  252. package/dist/types/src/components/ComputeGraph/graph-context.d.ts.map +0 -1
  253. package/dist/types/src/components/ComputeGraph/graph.browser.test.d.ts +0 -2
  254. package/dist/types/src/components/ComputeGraph/graph.browser.test.d.ts.map +0 -1
  255. package/dist/types/src/components/ComputeGraph/graph.d.ts +0 -26
  256. package/dist/types/src/components/ComputeGraph/graph.d.ts.map +0 -1
  257. package/dist/types/src/components/Sheet/formatting.d.ts +0 -14
  258. package/dist/types/src/components/Sheet/formatting.d.ts.map +0 -1
  259. package/dist/types/src/model/functions.d.ts.map +0 -1
  260. package/dist/types/src/model/model.browser.test.d.ts +0 -2
  261. package/dist/types/src/model/model.browser.test.d.ts.map +0 -1
  262. package/dist/types/src/model/model.d.ts.map +0 -1
  263. package/dist/types/src/model/types.d.ts.map +0 -1
  264. package/dist/types/src/model/types.test.d.ts.map +0 -1
  265. package/dist/types/src/model/util.d.ts +0 -15
  266. package/dist/types/src/model/util.d.ts.map +0 -1
  267. package/dist/types/src/testing.d.ts +0 -9
  268. package/dist/types/src/testing.d.ts.map +0 -1
  269. package/src/components/ComputeGraph/graph-context.tsx +0 -50
  270. package/src/components/ComputeGraph/graph.browser.test.ts +0 -50
  271. package/src/components/ComputeGraph/graph.ts +0 -62
  272. package/src/model/model.browser.test.ts +0 -100
  273. package/src/model/model.ts +0 -550
  274. package/src/model/util.ts +0 -36
  275. package/src/testing.ts +0 -50
  276. /package/dist/types/src/{model → defs}/types.test.d.ts +0 -0
  277. /package/src/{model/functions.ts → graph/functions/function-defs.ts} +0 -0
@@ -0,0 +1,171 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { useCallback, useMemo, useRef } from 'react';
6
+
7
+ import {
8
+ type DxGridElement,
9
+ Grid,
10
+ type GridContentProps,
11
+ type GridScopedProps,
12
+ useGridContext,
13
+ } from '@dxos/react-ui-grid';
14
+
15
+ import { colLabelCell, dxGridCellIndexToSheetCellAddress, rowLabelCell, useSheetModelDxGridProps } from './util';
16
+ import { rangeToA1Notation, type CellRange } from '../../defs';
17
+ import { type ComputeGraph } from '../../graph';
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 initialCells = {
53
+ grid: {},
54
+ frozenColsStart: [...Array(64)].reduce((acc, _, i) => {
55
+ acc[`0,${i}`] = rowLabelCell(i);
56
+ return acc;
57
+ }, {}),
58
+ frozenRowsStart: [...Array(12)].reduce((acc, _, i) => {
59
+ acc[`${i},0`] = colLabelCell(i);
60
+ return acc;
61
+ }, {}),
62
+ };
63
+
64
+ const frozen = {
65
+ frozenColsStart: 1,
66
+ frozenRowsStart: 1,
67
+ };
68
+
69
+ const sheetRowDefault = { grid: { size: 32, resizeable: true } };
70
+ const sheetColDefault = { frozenColsStart: { size: 48 }, grid: { size: 180, resizeable: true } };
71
+
72
+ const GridSheetImpl = ({
73
+ model,
74
+ formatting,
75
+ __gridScope,
76
+ }: GridScopedProps<{ model: SheetModel; formatting: FormattingModel }>) => {
77
+ const { editing, setEditing } = useGridContext('GridSheetCellEditor', __gridScope);
78
+ const dxGrid = useRef<DxGridElement | null>(null);
79
+ const rangeNotifier = useRef<CellRangeNotifier>();
80
+
81
+ // TODO(burdon): Validate formula before closing: hf.validateFormula();
82
+ const handleClose = useCallback<NonNullable<EditorKeysProps['onClose']> | NonNullable<EditorKeysProps['onNav']>>(
83
+ (value, { key, shift }) => {
84
+ if (value !== undefined) {
85
+ model.setValue(dxGridCellIndexToSheetCellAddress(editing)!, value);
86
+ }
87
+ setEditing(null);
88
+ const axis = ['Enter', 'ArrowUp', 'ArrowDown'].includes(key)
89
+ ? 'row'
90
+ : ['Tab', 'ArrowLeft', 'ArrowRight'].includes(key)
91
+ ? 'col'
92
+ : undefined;
93
+ const delta = key.startsWith('Arrow') ? (['ArrowUp', 'ArrowLeft'].includes(key) ? -1 : 1) : shift ? -1 : 1;
94
+ dxGrid.current?.refocus(axis, delta);
95
+ },
96
+ [model, editing, setEditing],
97
+ );
98
+
99
+ const handleAxisResize = useCallback<NonNullable<GridContentProps['onAxisResize']>>(
100
+ ({ axis, size, index: numericIndex }) => {
101
+ if (axis === 'row') {
102
+ const rowId = model.sheet.rows[parseInt(numericIndex)];
103
+ model.sheet.rowMeta[rowId] ??= {};
104
+ model.sheet.rowMeta[rowId].size = size;
105
+ } else {
106
+ const columnId = model.sheet.columns[parseInt(numericIndex)];
107
+ model.sheet.columnMeta[columnId] ??= {};
108
+ model.sheet.columnMeta[columnId].size = size;
109
+ }
110
+ },
111
+ [model],
112
+ );
113
+
114
+ const handleSelect = useCallback<NonNullable<GridContentProps['onSelect']>>(
115
+ ({ minCol, maxCol, minRow, maxRow }) => {
116
+ if (editing) {
117
+ const range: CellRange = { from: { col: minCol, row: minRow } };
118
+ if (minCol !== maxCol || minRow !== maxRow) {
119
+ range.to = { col: maxCol, row: maxRow };
120
+ }
121
+ // Update range selection in formula.
122
+ rangeNotifier.current?.(rangeToA1Notation(range));
123
+ }
124
+ },
125
+ [editing],
126
+ );
127
+
128
+ const { columns, rows } = useSheetModelDxGridProps(dxGrid, model, formatting);
129
+
130
+ const extension = useMemo(
131
+ () => [
132
+ editorKeys({ onClose: handleClose, ...(editing?.initialContent && { onNav: handleClose }) }),
133
+ sheetExtension({ functions: model.graph.getFunctions() }),
134
+ rangeExtension((fn) => (rangeNotifier.current = fn)),
135
+ ],
136
+ [model, handleClose, editing],
137
+ );
138
+
139
+ return (
140
+ <>
141
+ <GridSheetCellEditor model={model} extension={extension} />
142
+ <Grid.Content
143
+ initialCells={initialCells}
144
+ columns={columns}
145
+ rows={rows}
146
+ onAxisResize={handleAxisResize}
147
+ onSelect={handleSelect}
148
+ rowDefault={sheetRowDefault}
149
+ columnDefault={sheetColDefault}
150
+ frozen={frozen}
151
+ ref={dxGrid}
152
+ />
153
+ </>
154
+ );
155
+ };
156
+
157
+ export type GridSheetProps = { graph?: ComputeGraph; sheet?: SheetType } & UseSheetModelOptions;
158
+
159
+ export const GridSheet = ({ graph, sheet, ...options }: GridSheetProps) => {
160
+ const model = useSheetModel(graph, sheet, options);
161
+ const formatting = useFormattingModel(model);
162
+ if (!model || !formatting) {
163
+ return null;
164
+ }
165
+
166
+ return (
167
+ <Grid.Root id={model.id}>
168
+ <GridSheetImpl model={model} formatting={formatting} />
169
+ </Grid.Root>
170
+ );
171
+ };
@@ -0,0 +1,148 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { type MutableRefObject, useEffect, useLayoutEffect, useState } from 'react';
6
+
7
+ import { createDocAccessor } from '@dxos/react-client/echo';
8
+ import {
9
+ type GridEditing,
10
+ type GridContentProps,
11
+ type DxGridElement,
12
+ type DxGridAxisMeta,
13
+ type DxGridPlane,
14
+ type DxGridPlaneRange,
15
+ type DxGridPlaneCells,
16
+ colToA1Notation,
17
+ rowToA1Notation,
18
+ } from '@dxos/react-ui-grid';
19
+ import { mx } from '@dxos/react-ui-theme';
20
+
21
+ import { type CellAddress } from '../../defs';
22
+ import { type SheetModel, type FormattingModel } from '../../model';
23
+
24
+ export const dxGridCellIndexToSheetCellAddress = (gridEditing: GridEditing): CellAddress | null => {
25
+ if (!gridEditing) {
26
+ return null;
27
+ }
28
+ const [colStr, rowStr] = gridEditing.index.split(',');
29
+ return {
30
+ col: parseInt(colStr),
31
+ row: parseInt(rowStr),
32
+ };
33
+ };
34
+
35
+ const createDxGridColumns = (model: SheetModel): DxGridAxisMeta => {
36
+ return model.sheet.columns.reduce(
37
+ (acc: DxGridAxisMeta, columnId, numericIndex) => {
38
+ if (model.sheet.columnMeta[columnId] && model.sheet.columnMeta[columnId].size) {
39
+ acc.grid[numericIndex] = { size: model.sheet.columnMeta[columnId].size, resizeable: true };
40
+ }
41
+ return acc;
42
+ },
43
+ { grid: {} },
44
+ );
45
+ };
46
+
47
+ const createDxGridRows = (model: SheetModel): DxGridAxisMeta => {
48
+ return model.sheet.rows.reduce(
49
+ (acc: DxGridAxisMeta, rowId, numericIndex) => {
50
+ if (model.sheet.rowMeta[rowId] && model.sheet.rowMeta[rowId].size) {
51
+ acc.grid[numericIndex] = { size: model.sheet.rowMeta[rowId].size, resizeable: true };
52
+ }
53
+ return acc;
54
+ },
55
+ { grid: {} },
56
+ );
57
+ };
58
+
59
+ const gridCellGetter = (model: SheetModel, formatting: FormattingModel) => {
60
+ // TODO(thure): Actually use the cache.
61
+ const cachedGridCells: DxGridPlaneCells = {};
62
+ return (nextBounds: DxGridPlaneRange): DxGridPlaneCells => {
63
+ [...Array(nextBounds.end.col - nextBounds.start.col)].forEach((_, c0) => {
64
+ return [...Array(nextBounds.end.row - nextBounds.start.row)].forEach((_, r0) => {
65
+ const col = nextBounds.start.col + c0;
66
+ const row = nextBounds.start.row + r0;
67
+ const cell = formatting.getFormatting({ col, row });
68
+ if (cell.value) {
69
+ cachedGridCells;
70
+ cachedGridCells[`${col},${row}`] = { value: cell.value, className: mx(cell.classNames) };
71
+ }
72
+ });
73
+ });
74
+ return cachedGridCells;
75
+ };
76
+ };
77
+
78
+ export const rowLabelCell = (row: number) => ({
79
+ value: rowToA1Notation(row),
80
+ className: 'text-end !pie-1',
81
+ resizeHandle: 'row',
82
+ });
83
+
84
+ export const colLabelCell = (col: number) => ({ value: colToA1Notation(col), resizeHandle: 'col' });
85
+
86
+ const cellGetter = (model: SheetModel, formatting: FormattingModel) => {
87
+ const getGridCells = gridCellGetter(model, formatting);
88
+ return (nextBounds: DxGridPlaneRange, plane: DxGridPlane): DxGridPlaneCells => {
89
+ switch (plane) {
90
+ case 'grid':
91
+ return getGridCells(nextBounds);
92
+ case 'frozenColsStart':
93
+ return [...Array(nextBounds.end.row - nextBounds.start.row)].reduce((acc, _, r0) => {
94
+ const r = nextBounds.start.row + r0;
95
+ acc[`0,${r}`] = rowLabelCell(r);
96
+ return acc;
97
+ }, {});
98
+ case 'frozenRowsStart':
99
+ return [...Array(nextBounds.end.col - nextBounds.start.col)].reduce((acc, _, c0) => {
100
+ const c = nextBounds.start.col + c0;
101
+ acc[`${c},0`] = colLabelCell(c);
102
+ return acc;
103
+ }, {});
104
+ default:
105
+ return {};
106
+ }
107
+ };
108
+ };
109
+
110
+ export const useSheetModelDxGridProps = (
111
+ dxGridRef: MutableRefObject<DxGridElement | null>,
112
+ model: SheetModel,
113
+ formatting: FormattingModel,
114
+ ): Pick<GridContentProps, 'columns' | 'rows'> => {
115
+ const [columns, setColumns] = useState<DxGridAxisMeta>(createDxGridColumns(model));
116
+ const [rows, setRows] = useState<DxGridAxisMeta>(createDxGridColumns(model));
117
+
118
+ useLayoutEffect(() => {
119
+ const cellsAccessor = createDocAccessor(model.sheet, ['cells']);
120
+ if (dxGridRef.current) {
121
+ dxGridRef.current.getCells = cellGetter(model, formatting);
122
+ }
123
+ const handleCellsUpdate = () => {
124
+ dxGridRef.current?.requestUpdate('initialCells');
125
+ };
126
+ cellsAccessor.handle.addListener('change', handleCellsUpdate);
127
+ return () => cellsAccessor.handle.removeListener('change', handleCellsUpdate);
128
+ }, [model, formatting]);
129
+
130
+ useEffect(() => {
131
+ const columnMetaAccessor = createDocAccessor(model.sheet, ['columnMeta']);
132
+ const rowMetaAccessor = createDocAccessor(model.sheet, ['rowMeta']);
133
+ const handleColumnMetaUpdate = () => {
134
+ setColumns(createDxGridColumns(model));
135
+ };
136
+ const handleRowMetaUpdate = () => {
137
+ setRows(createDxGridRows(model));
138
+ };
139
+ columnMetaAccessor.handle.addListener('change', handleColumnMetaUpdate);
140
+ rowMetaAccessor.handle.addListener('change', handleRowMetaUpdate);
141
+ return () => {
142
+ columnMetaAccessor.handle.removeListener('change', handleColumnMetaUpdate);
143
+ rowMetaAccessor.handle.removeListener('change', handleRowMetaUpdate);
144
+ };
145
+ }, [model]);
146
+
147
+ return { columns, rows };
148
+ };
@@ -4,31 +4,34 @@
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';
10
+ import { useSpace } from '@dxos/react-client/echo';
11
+ import { withClientProvider } from '@dxos/react-client/testing';
14
12
  import { Button } from '@dxos/react-ui';
15
13
  import { mx } from '@dxos/react-ui-theme';
16
- import { withTheme, withLayout } 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 { type ComputeGraph } from '../../graph';
21
+ import { testFunctionPlugins } from '../../graph/testing';
22
+ import { useComputeGraph } from '../../hooks';
23
+ import { createTestCells, useTestSheet, withComputeGraphDecorator } from '../../testing';
24
+ import { SheetType, ValueTypeEnum } from '../../types';
26
25
  import { Toolbar, type ToolbarActionHandler } from '../Toolbar';
27
26
 
28
27
  // TODO(burdon): Allow toolbar to access sheet context; provide state for current cursor/range.
29
- const SheetWithToolbar = ({ debug, space }: { debug?: boolean; space: Space }) => {
28
+ const SheetWithToolbar = ({ graph, debug }: { graph: ComputeGraph; debug?: boolean }) => {
30
29
  const { model, cursor, range } = useSheetContext();
31
30
 
31
+ const handleRefresh = () => {
32
+ // graph?.refresh(); // TODO(burdon): ???
33
+ };
34
+
32
35
  // TODO(burdon): Factor out.
33
36
  const handleAction: ToolbarActionHandler = ({ type }) => {
34
37
  log.info('action', { type, cursor, range });
@@ -36,7 +39,7 @@ const SheetWithToolbar = ({ debug, space }: { debug?: boolean; space: Space }) =
36
39
  return;
37
40
  }
38
41
 
39
- const idx = range ? model.rangeToIndex(range) : model.addressToIndex(cursor);
42
+ const idx = range ? rangeToIndex(model.sheet, range) : addressToIndex(model.sheet, cursor);
40
43
  model.sheet.formatting[idx] ??= {};
41
44
  const format = model.sheet.formatting[idx];
42
45
 
@@ -75,14 +78,12 @@ const SheetWithToolbar = ({ debug, space }: { debug?: boolean; space: Space }) =
75
78
  format.precision = 2;
76
79
  break;
77
80
  }
81
+ case 'comment': {
82
+ break;
83
+ }
78
84
  }
79
85
  };
80
86
 
81
- const graph = useComputeGraph(space);
82
- const handleRefresh = () => {
83
- graph.refresh();
84
- };
85
-
86
87
  return (
87
88
  <div className='flex flex-col overflow-hidden'>
88
89
  <Toolbar.Root onAction={handleAction}>
@@ -99,56 +100,43 @@ const SheetWithToolbar = ({ debug, space }: { debug?: boolean; space: Space }) =
99
100
  );
100
101
  };
101
102
 
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
103
  export default {
123
104
  title: 'plugin-sheet/Sheet',
124
105
  component: Sheet,
125
- decorators: [withTheme, withLayout({ fullscreen: true, tooltips: true, classNames: 'inset-4' }), withGraphDecorator],
106
+ decorators: [
107
+ withClientProvider({ types: [SheetType], createIdentity: true }),
108
+ withComputeGraphDecorator({ plugins: testFunctionPlugins }),
109
+ withTheme,
110
+ withLayout({ fullscreen: true, tooltips: true, classNames: 'inset-4' }),
111
+ ],
126
112
  };
127
113
 
128
114
  export const Default = () => {
129
115
  const [debug, setDebug] = useState(false);
130
- const sheet = useTestSheet();
131
- const space = getSpace(sheet);
132
- if (!sheet || !space) {
116
+ const space = useSpace();
117
+ const graph = useComputeGraph(space);
118
+ const sheet = useTestSheet(space, graph, { cells: createTestCells() });
119
+ if (!graph || !sheet) {
133
120
  return null;
134
121
  }
135
122
 
136
123
  return (
137
- <Sheet.Root sheet={sheet} space={space} onInfo={() => setDebug((debug) => !debug)}>
138
- <SheetWithToolbar debug={debug} space={space} />
124
+ <Sheet.Root graph={graph} sheet={sheet} onInfo={() => setDebug((debug) => !debug)}>
125
+ <SheetWithToolbar graph={graph} debug={debug} />
139
126
  </Sheet.Root>
140
127
  );
141
128
  };
142
129
 
143
130
  export const Debug = () => {
144
- const sheet = useTestSheet();
145
- const space = getSpace(sheet);
146
- if (!sheet || !space) {
131
+ const space = useSpace();
132
+ const graph = useComputeGraph(space);
133
+ const sheet = useTestSheet(space, graph, { cells: createTestCells() });
134
+ if (!graph || !sheet) {
147
135
  return null;
148
136
  }
149
137
 
150
138
  return (
151
- <Sheet.Root sheet={sheet} space={space}>
139
+ <Sheet.Root graph={graph} sheet={sheet}>
152
140
  <Sheet.Main />
153
141
  <Sheet.Debug />
154
142
  </Sheet.Root>
@@ -157,14 +145,15 @@ export const Debug = () => {
157
145
 
158
146
  export const Rows = () => {
159
147
  const [rowSizes, setRowSizes] = useState<SizeMap>({});
160
- const sheet = useTestSheet();
161
- const space = getSpace(sheet);
162
- if (!sheet || !space) {
148
+ const space = useSpace();
149
+ const graph = useComputeGraph(space);
150
+ const sheet = useTestSheet(space, graph);
151
+ if (!graph || !sheet) {
163
152
  return null;
164
153
  }
165
154
 
166
155
  return (
167
- <Sheet.Root sheet={sheet} space={space}>
156
+ <Sheet.Root graph={graph} sheet={sheet}>
168
157
  <Sheet.Rows
169
158
  rows={sheet.rows}
170
159
  sizes={rowSizes}
@@ -176,14 +165,15 @@ export const Rows = () => {
176
165
 
177
166
  export const Columns = () => {
178
167
  const [columnSizes, setColumnSizes] = useState<SizeMap>({});
179
- const sheet = useTestSheet();
180
- const space = getSpace(sheet);
181
- if (!sheet || !space) {
168
+ const space = useSpace();
169
+ const graph = useComputeGraph(space);
170
+ const sheet = useTestSheet(space, graph);
171
+ if (!graph || !sheet) {
182
172
  return null;
183
173
  }
184
174
 
185
175
  return (
186
- <Sheet.Root sheet={sheet} space={space}>
176
+ <Sheet.Root graph={graph} sheet={sheet}>
187
177
  <Sheet.Columns
188
178
  columns={sheet.columns}
189
179
  sizes={columnSizes}
@@ -194,18 +184,19 @@ export const Columns = () => {
194
184
  };
195
185
 
196
186
  export const Main = () => {
197
- const sheet = useTestSheet();
198
- const space = getSpace(sheet);
199
- if (!sheet || !space) {
187
+ const space = useSpace();
188
+ const graph = useComputeGraph(space);
189
+ const sheet = useTestSheet(space, graph, { cells: createTestCells() });
190
+ if (!graph || !sheet) {
200
191
  return null;
201
192
  }
202
193
 
203
194
  return (
204
- <Sheet.Root sheet={sheet} space={space}>
195
+ <Sheet.Root graph={graph} sheet={sheet}>
205
196
  <Sheet.Grid
206
197
  size={{
207
198
  numRows: 50,
208
- numColumns: 26,
199
+ numCols: 26,
209
200
  }}
210
201
  rows={sheet.rows}
211
202
  columns={sheet.columns}
@@ -258,30 +249,3 @@ export const GridLayout = () => {
258
249
  const Cell = ({ className, label }: { className?: string; label: string }) => (
259
250
  <div className={mx('flex items-center justify-center border', className)}>{label}</div>
260
251
  );
261
-
262
- const useTestSheet = () => {
263
- const { graphs, setGraph } = useContext(ComputeGraphContext);
264
- const [sheet, setSheet] = useState<EchoReactiveObject<SheetType>>();
265
- useEffect(() => {
266
- const t = setTimeout(async () => {
267
- const client = new Client();
268
- await client.initialize();
269
- await client.halo.createIdentity();
270
- const space = await client.spaces.create();
271
- client.addTypes([SheetType]);
272
-
273
- const graph = graphs[space.id] ?? createComputeGraph();
274
- if (!graphs[space.id]) {
275
- setGraph(space.id, graph);
276
- }
277
-
278
- const sheet = await createTestSheet({ graph });
279
- space.db.add(sheet);
280
- setSheet(sheet);
281
- });
282
-
283
- return () => clearTimeout(t);
284
- }, []);
285
-
286
- return sheet;
287
- };