@dxos/plugin-sheet 0.6.12-main.5cc132e → 0.6.12-main.78ddbdf

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 (256) 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-GNNVBNCX.mjs → chunk-6ZMQVB4Z.mjs} +358 -678
  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/{node-esm/chunk-WUPTZUTX.mjs → browser/chunk-T3NJFTD4.mjs} +4 -14
  8. package/dist/lib/browser/chunk-T3NJFTD4.mjs.map +7 -0
  9. package/dist/lib/browser/{SheetContainer-Y7ZMFBAP.mjs → chunk-U2JHW3L6.mjs} +819 -498
  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 +58 -55
  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-ZRQZFV5T.cjs → chunk-DD6FIXWC.cjs} +359 -679
  23. package/dist/lib/node/chunk-DD6FIXWC.cjs.map +7 -0
  24. package/dist/lib/node/{SheetContainer-KEOKUKAQ.cjs → chunk-OTTD7FBK.cjs} +875 -551
  25. package/dist/lib/node/chunk-OTTD7FBK.cjs.map +7 -0
  26. package/dist/lib/node/{chunk-VJU3NPUJ.cjs → chunk-Q3HBHPRL.cjs} +8 -19
  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 +75 -64
  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/{SheetContainer-Y7ZMFBAP.mjs → chunk-7HVSOTGA.mjs} +820 -498
  40. package/dist/lib/node-esm/chunk-7HVSOTGA.mjs.map +7 -0
  41. package/dist/lib/{browser/chunk-WUPTZUTX.mjs → node-esm/chunk-BMNA27EX.mjs} +5 -14
  42. package/dist/lib/node-esm/chunk-BMNA27EX.mjs.map +7 -0
  43. package/dist/lib/node-esm/{chunk-GNNVBNCX.mjs → chunk-D6KU5MI7.mjs} +359 -677
  44. package/dist/lib/node-esm/chunk-D6KU5MI7.mjs.map +7 -0
  45. package/dist/lib/node-esm/{chunk-JRL5LGCE.mjs → chunk-IU2L277A.mjs} +4 -5
  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 +59 -55
  50. package/dist/lib/node-esm/index.mjs.map +3 -3
  51. package/dist/lib/node-esm/meta.json +1 -1
  52. package/dist/lib/node-esm/meta.mjs +2 -1
  53. package/dist/lib/node-esm/types.mjs +5 -6
  54. package/dist/types/src/SheetPlugin.d.ts.map +1 -1
  55. package/dist/types/src/components/CellEditor/CellEditor.d.ts +23 -3
  56. package/dist/types/src/components/CellEditor/CellEditor.d.ts.map +1 -1
  57. package/dist/types/src/components/CellEditor/CellEditor.stories.d.ts +2 -2
  58. package/dist/types/src/components/CellEditor/CellEditor.stories.d.ts.map +1 -1
  59. package/dist/types/src/components/CellEditor/extension.d.ts +1 -1
  60. package/dist/types/src/components/CellEditor/extension.d.ts.map +1 -1
  61. package/dist/types/src/components/ComputeGraph/ComputeGraphContextProvider.d.ts +11 -0
  62. package/dist/types/src/components/ComputeGraph/ComputeGraphContextProvider.d.ts.map +1 -0
  63. package/dist/types/src/components/ComputeGraph/index.d.ts +1 -3
  64. package/dist/types/src/components/ComputeGraph/index.d.ts.map +1 -1
  65. package/dist/types/src/components/GridSheet/GridSheet.d.ts +10 -0
  66. package/dist/types/src/components/GridSheet/GridSheet.d.ts.map +1 -0
  67. package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts +9 -0
  68. package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts.map +1 -0
  69. package/dist/types/src/components/GridSheet/util.d.ts +7 -0
  70. package/dist/types/src/components/GridSheet/util.d.ts.map +1 -0
  71. package/dist/types/src/components/Sheet/Sheet.d.ts +1 -1
  72. package/dist/types/src/components/Sheet/Sheet.d.ts.map +1 -1
  73. package/dist/types/src/components/Sheet/Sheet.stories.d.ts +5 -6
  74. package/dist/types/src/components/Sheet/Sheet.stories.d.ts.map +1 -1
  75. package/dist/types/src/components/Sheet/grid.d.ts +2 -2
  76. package/dist/types/src/components/Sheet/grid.d.ts.map +1 -1
  77. package/dist/types/src/components/Sheet/nav.d.ts +3 -3
  78. package/dist/types/src/components/Sheet/nav.d.ts.map +1 -1
  79. package/dist/types/src/components/Sheet/sheet-context.d.ts +4 -5
  80. package/dist/types/src/components/Sheet/sheet-context.d.ts.map +1 -1
  81. package/dist/types/src/components/Sheet/threads.d.ts.map +1 -1
  82. package/dist/types/src/components/SheetContainer.d.ts +1 -1
  83. package/dist/types/src/components/SheetContainer.d.ts.map +1 -1
  84. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
  85. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +1 -1
  86. package/dist/types/src/components/index.d.ts +2 -1
  87. package/dist/types/src/components/index.d.ts.map +1 -1
  88. package/dist/types/src/defs/index.d.ts +3 -0
  89. package/dist/types/src/defs/index.d.ts.map +1 -0
  90. package/dist/types/src/{model → defs}/types.d.ts +8 -3
  91. package/dist/types/src/defs/types.d.ts.map +1 -0
  92. package/dist/types/src/defs/types.test.d.ts.map +1 -0
  93. package/dist/types/src/{model → defs}/util.d.ts +8 -4
  94. package/dist/types/src/defs/util.d.ts.map +1 -0
  95. package/dist/types/src/extensions/compute.d.ts +5 -0
  96. package/dist/types/src/extensions/compute.d.ts.map +1 -0
  97. package/dist/types/src/extensions/compute.stories.d.ts +26 -0
  98. package/dist/types/src/extensions/compute.stories.d.ts.map +1 -0
  99. package/dist/types/src/extensions/index.d.ts +2 -0
  100. package/dist/types/src/extensions/index.d.ts.map +1 -0
  101. package/dist/types/src/{components/ComputeGraph → graph}/async-function.d.ts +1 -1
  102. package/dist/types/src/graph/async-function.d.ts.map +1 -0
  103. package/dist/types/src/graph/compute-graph.browser.test.d.ts +2 -0
  104. package/dist/types/src/graph/compute-graph.browser.test.d.ts.map +1 -0
  105. package/dist/types/src/graph/compute-graph.d.ts +81 -0
  106. package/dist/types/src/graph/compute-graph.d.ts.map +1 -0
  107. package/dist/types/src/graph/compute-graph.stories.d.ts +10 -0
  108. package/dist/types/src/graph/compute-graph.stories.d.ts.map +1 -0
  109. package/dist/types/src/graph/compute-node.d.ts +19 -0
  110. package/dist/types/src/graph/compute-node.d.ts.map +1 -0
  111. package/dist/types/src/{components/ComputeGraph/custom.d.ts → graph/custom-function.d.ts} +1 -1
  112. package/dist/types/src/graph/custom-function.d.ts.map +1 -0
  113. package/dist/types/src/graph/edge-function.d.ts.map +1 -0
  114. package/dist/types/src/{model/functions.d.ts → graph/function-defs.d.ts} +1 -1
  115. package/dist/types/src/graph/function-defs.d.ts.map +1 -0
  116. package/dist/types/src/graph/hyperformula.test.d.ts +2 -0
  117. package/dist/types/src/graph/hyperformula.test.d.ts.map +1 -0
  118. package/dist/types/src/graph/index.d.ts +4 -0
  119. package/dist/types/src/graph/index.d.ts.map +1 -0
  120. package/dist/types/src/graph/util.d.ts +2 -0
  121. package/dist/types/src/graph/util.d.ts.map +1 -0
  122. package/dist/types/src/hooks/hooks.stories.d.ts +11 -0
  123. package/dist/types/src/hooks/hooks.stories.d.ts.map +1 -0
  124. package/dist/types/src/hooks/index.d.ts +4 -0
  125. package/dist/types/src/hooks/index.d.ts.map +1 -0
  126. package/dist/types/src/hooks/useComputeGraph.d.ts +7 -0
  127. package/dist/types/src/hooks/useComputeGraph.d.ts.map +1 -0
  128. package/dist/types/src/hooks/useFormattingModel.d.ts +3 -0
  129. package/dist/types/src/hooks/useFormattingModel.d.ts.map +1 -0
  130. package/dist/types/src/hooks/useSheetModel.d.ts +8 -0
  131. package/dist/types/src/hooks/useSheetModel.d.ts.map +1 -0
  132. package/dist/types/src/meta.d.ts +1 -4
  133. package/dist/types/src/meta.d.ts.map +1 -1
  134. package/dist/types/src/model/formatting-model.d.ts +16 -0
  135. package/dist/types/src/model/formatting-model.d.ts.map +1 -0
  136. package/dist/types/src/model/index.d.ts +2 -4
  137. package/dist/types/src/model/index.d.ts.map +1 -1
  138. package/dist/types/src/model/{model.d.ts → sheet-model.d.ts} +9 -48
  139. package/dist/types/src/model/sheet-model.d.ts.map +1 -0
  140. package/dist/types/src/sanity.test.d.ts +2 -0
  141. package/dist/types/src/sanity.test.d.ts.map +1 -0
  142. package/dist/types/src/testing/index.d.ts +2 -0
  143. package/dist/types/src/testing/index.d.ts.map +1 -0
  144. package/dist/types/src/testing/testing.d.ts +9 -0
  145. package/dist/types/src/testing/testing.d.ts.map +1 -0
  146. package/dist/types/src/types.d.ts +12 -2
  147. package/dist/types/src/types.d.ts.map +1 -1
  148. package/dist/vendor/hyperformula.mjs +37145 -0
  149. package/package.json +41 -38
  150. package/src/SheetPlugin.tsx +39 -59
  151. package/src/components/CellEditor/CellEditor.stories.tsx +4 -3
  152. package/src/components/CellEditor/CellEditor.tsx +59 -9
  153. package/src/components/CellEditor/extension.test.ts +3 -3
  154. package/src/components/CellEditor/extension.ts +1 -3
  155. package/src/components/ComputeGraph/ComputeGraphContextProvider.tsx +20 -0
  156. package/src/components/ComputeGraph/index.ts +1 -3
  157. package/src/components/GridSheet/GridSheet.stories.tsx +36 -0
  158. package/src/components/GridSheet/GridSheet.tsx +153 -0
  159. package/src/components/GridSheet/util.ts +108 -0
  160. package/src/components/Sheet/Sheet.stories.tsx +41 -82
  161. package/src/components/Sheet/Sheet.tsx +12 -10
  162. package/src/components/Sheet/grid.ts +3 -3
  163. package/src/components/Sheet/nav.ts +19 -19
  164. package/src/components/Sheet/sheet-context.tsx +10 -80
  165. package/src/components/Sheet/threads.tsx +10 -6
  166. package/src/components/SheetContainer.tsx +2 -2
  167. package/src/components/Toolbar/Toolbar.tsx +1 -2
  168. package/src/components/index.ts +1 -0
  169. package/src/defs/index.ts +6 -0
  170. package/src/{model → defs}/types.test.ts +7 -7
  171. package/src/{model → defs}/types.ts +23 -14
  172. package/src/{model → defs}/util.ts +49 -17
  173. package/src/extensions/compute.stories.tsx +151 -0
  174. package/src/extensions/compute.ts +98 -0
  175. package/src/extensions/index.ts +5 -0
  176. package/src/{components/ComputeGraph → graph}/async-function.ts +3 -1
  177. package/src/graph/compute-graph.browser.test.ts +104 -0
  178. package/src/graph/compute-graph.stories.tsx +92 -0
  179. package/src/graph/compute-graph.ts +290 -0
  180. package/src/graph/compute-node.ts +51 -0
  181. package/src/{components/ComputeGraph/custom.ts → graph/custom-function.ts} +2 -6
  182. package/src/{components/ComputeGraph → graph}/edge-function.ts +2 -1
  183. package/src/graph/hyperformula.test.ts +15 -0
  184. package/src/graph/index.ts +7 -0
  185. package/src/graph/util.ts +8 -0
  186. package/src/hooks/hooks.stories.tsx +50 -0
  187. package/src/hooks/index.ts +7 -0
  188. package/src/hooks/useComputeGraph.ts +20 -0
  189. package/src/hooks/useFormattingModel.ts +11 -0
  190. package/src/hooks/useSheetModel.ts +43 -0
  191. package/src/meta.tsx +1 -5
  192. package/src/{components/Sheet/formatting.ts → model/formatting-model.ts} +20 -13
  193. package/src/model/index.ts +2 -4
  194. package/src/model/{model.ts → sheet-model.ts} +67 -184
  195. package/src/sanity.test.ts +40 -0
  196. package/src/testing/index.ts +5 -0
  197. package/src/testing/testing.tsx +66 -0
  198. package/src/types.ts +14 -12
  199. package/dist/lib/browser/SheetContainer-Y7ZMFBAP.mjs.map +0 -7
  200. package/dist/lib/browser/chunk-GNNVBNCX.mjs.map +0 -7
  201. package/dist/lib/browser/chunk-JRL5LGCE.mjs.map +0 -7
  202. package/dist/lib/browser/chunk-PGKZPKUD.mjs +0 -175
  203. package/dist/lib/browser/chunk-PGKZPKUD.mjs.map +0 -7
  204. package/dist/lib/browser/chunk-VBF7YENS.mjs +0 -8
  205. package/dist/lib/browser/chunk-VBF7YENS.mjs.map +0 -7
  206. package/dist/lib/browser/chunk-WUPTZUTX.mjs.map +0 -7
  207. package/dist/lib/browser/testing.mjs +0 -92
  208. package/dist/lib/browser/testing.mjs.map +0 -7
  209. package/dist/lib/node/SheetContainer-KEOKUKAQ.cjs.map +0 -7
  210. package/dist/lib/node/chunk-57PB2HPY.cjs +0 -40
  211. package/dist/lib/node/chunk-57PB2HPY.cjs.map +0 -7
  212. package/dist/lib/node/chunk-6LWBQAQZ.cjs +0 -202
  213. package/dist/lib/node/chunk-6LWBQAQZ.cjs.map +0 -7
  214. package/dist/lib/node/chunk-BJ6ZD7MN.cjs.map +0 -7
  215. package/dist/lib/node/chunk-VJU3NPUJ.cjs.map +0 -7
  216. package/dist/lib/node/chunk-ZRQZFV5T.cjs.map +0 -7
  217. package/dist/lib/node/testing.cjs +0 -111
  218. package/dist/lib/node/testing.cjs.map +0 -7
  219. package/dist/lib/node-esm/SheetContainer-Y7ZMFBAP.mjs.map +0 -7
  220. package/dist/lib/node-esm/chunk-GNNVBNCX.mjs.map +0 -7
  221. package/dist/lib/node-esm/chunk-JRL5LGCE.mjs.map +0 -7
  222. package/dist/lib/node-esm/chunk-PGKZPKUD.mjs +0 -175
  223. package/dist/lib/node-esm/chunk-PGKZPKUD.mjs.map +0 -7
  224. package/dist/lib/node-esm/chunk-VBF7YENS.mjs +0 -8
  225. package/dist/lib/node-esm/chunk-VBF7YENS.mjs.map +0 -7
  226. package/dist/lib/node-esm/chunk-WUPTZUTX.mjs.map +0 -7
  227. package/dist/lib/node-esm/testing.mjs +0 -92
  228. package/dist/lib/node-esm/testing.mjs.map +0 -7
  229. package/dist/types/src/components/ComputeGraph/async-function.d.ts.map +0 -1
  230. package/dist/types/src/components/ComputeGraph/custom.d.ts.map +0 -1
  231. package/dist/types/src/components/ComputeGraph/edge-function.d.ts.map +0 -1
  232. package/dist/types/src/components/ComputeGraph/graph-context.d.ts +0 -12
  233. package/dist/types/src/components/ComputeGraph/graph-context.d.ts.map +0 -1
  234. package/dist/types/src/components/ComputeGraph/graph.browser.test.d.ts +0 -2
  235. package/dist/types/src/components/ComputeGraph/graph.browser.test.d.ts.map +0 -1
  236. package/dist/types/src/components/ComputeGraph/graph.d.ts +0 -26
  237. package/dist/types/src/components/ComputeGraph/graph.d.ts.map +0 -1
  238. package/dist/types/src/components/Sheet/formatting.d.ts +0 -14
  239. package/dist/types/src/components/Sheet/formatting.d.ts.map +0 -1
  240. package/dist/types/src/model/functions.d.ts.map +0 -1
  241. package/dist/types/src/model/model.browser.test.d.ts +0 -2
  242. package/dist/types/src/model/model.browser.test.d.ts.map +0 -1
  243. package/dist/types/src/model/model.d.ts.map +0 -1
  244. package/dist/types/src/model/types.d.ts.map +0 -1
  245. package/dist/types/src/model/types.test.d.ts.map +0 -1
  246. package/dist/types/src/model/util.d.ts.map +0 -1
  247. package/dist/types/src/testing.d.ts +0 -9
  248. package/dist/types/src/testing.d.ts.map +0 -1
  249. package/src/components/ComputeGraph/graph-context.tsx +0 -50
  250. package/src/components/ComputeGraph/graph.browser.test.ts +0 -49
  251. package/src/components/ComputeGraph/graph.ts +0 -62
  252. package/src/model/model.browser.test.ts +0 -99
  253. package/src/testing.ts +0 -50
  254. /package/dist/types/src/{model → defs}/types.test.d.ts +0 -0
  255. /package/dist/types/src/{components/ComputeGraph → graph}/edge-function.d.ts +0 -0
  256. /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 { columns, rows } = useSheetModelDxGridProps(dxGrid, 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
+ initialCells={{}}
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,108 @@
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 DxGridCells,
13
+ type DxGridAxisMeta,
14
+ type DxGridRange,
15
+ } from '@dxos/react-ui-grid';
16
+ import { mx } from '@dxos/react-ui-theme';
17
+
18
+ import { type CellAddress } from '../../defs';
19
+ import { type SheetModel, type FormattingModel } from '../../model';
20
+
21
+ export const dxGridCellIndexToSheetCellAddress = (gridEditing: GridEditing): CellAddress | null => {
22
+ if (!gridEditing) {
23
+ return null;
24
+ }
25
+ const [colStr, rowStr] = gridEditing.index.split(',');
26
+ return {
27
+ col: parseInt(colStr),
28
+ row: parseInt(rowStr),
29
+ };
30
+ };
31
+
32
+ const createDxGridColumns = (model: SheetModel): DxGridAxisMeta => {
33
+ return model.sheet.columns.reduce((acc: DxGridAxisMeta, columnId, numericIndex) => {
34
+ if (model.sheet.columnMeta[columnId] && model.sheet.columnMeta[columnId].size) {
35
+ acc[numericIndex] = { size: model.sheet.columnMeta[columnId].size, resizeable: true };
36
+ }
37
+ return acc;
38
+ }, {});
39
+ };
40
+
41
+ const createDxGridRows = (model: SheetModel): DxGridAxisMeta => {
42
+ return model.sheet.rows.reduce((acc: DxGridAxisMeta, rowId, numericIndex) => {
43
+ if (model.sheet.rowMeta[rowId] && model.sheet.rowMeta[rowId].size) {
44
+ acc[numericIndex] = { size: model.sheet.rowMeta[rowId].size, resizeable: true };
45
+ }
46
+ return acc;
47
+ }, {});
48
+ };
49
+
50
+ const cellGetter = (model: SheetModel, formatting: FormattingModel) => {
51
+ // TODO(thure): Actually use the cache.
52
+ let _cachedBounds: DxGridRange | null = null;
53
+ const cachedCells: DxGridCells = {};
54
+ return (nextBounds: DxGridRange): DxGridCells => {
55
+ [...Array(nextBounds.end.col - nextBounds.start.col)].forEach((_, c0) => {
56
+ return [...Array(nextBounds.end.row - nextBounds.start.row)].forEach((_, r0) => {
57
+ const col = nextBounds.start.col + c0;
58
+ const row = nextBounds.start.row + r0;
59
+ const cell = formatting.getFormatting({ col, row });
60
+ if (cell.value) {
61
+ cachedCells[`${col},${row}`] = { value: cell.value, className: mx(cell.classNames) };
62
+ }
63
+ });
64
+ });
65
+ _cachedBounds = nextBounds;
66
+ return cachedCells;
67
+ };
68
+ };
69
+
70
+ export const useSheetModelDxGridProps = (
71
+ dxGridRef: MutableRefObject<DxGridElement | null>,
72
+ model: SheetModel,
73
+ formatting: FormattingModel,
74
+ ): Pick<GridContentProps, 'columns' | 'rows'> => {
75
+ const [columns, setColumns] = useState<DxGridAxisMeta>(createDxGridColumns(model));
76
+ const [rows, setRows] = useState<DxGridAxisMeta>(createDxGridColumns(model));
77
+
78
+ useLayoutEffect(() => {
79
+ const cellsAccessor = createDocAccessor(model.sheet, ['cells']);
80
+ if (dxGridRef.current) {
81
+ dxGridRef.current.getCells = cellGetter(model, formatting);
82
+ }
83
+ const handleCellsUpdate = () => {
84
+ dxGridRef.current?.requestUpdate('initialCells');
85
+ };
86
+ cellsAccessor.handle.addListener('change', handleCellsUpdate);
87
+ return () => cellsAccessor.handle.removeListener('change', handleCellsUpdate);
88
+ }, [model, formatting]);
89
+
90
+ useEffect(() => {
91
+ const columnMetaAccessor = createDocAccessor(model.sheet, ['columnMeta']);
92
+ const rowMetaAccessor = createDocAccessor(model.sheet, ['rowMeta']);
93
+ const handleColumnMetaUpdate = () => {
94
+ setColumns(createDxGridColumns(model));
95
+ };
96
+ const handleRowMetaUpdate = () => {
97
+ setRows(createDxGridRows(model));
98
+ };
99
+ columnMetaAccessor.handle.addListener('change', handleColumnMetaUpdate);
100
+ rowMetaAccessor.handle.addListener('change', handleRowMetaUpdate);
101
+ return () => {
102
+ columnMetaAccessor.handle.removeListener('change', handleColumnMetaUpdate);
103
+ rowMetaAccessor.handle.removeListener('change', handleRowMetaUpdate);
104
+ };
105
+ }, [model]);
106
+
107
+ return { columns, rows };
108
+ };
@@ -4,32 +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';
10
+ import { type Space, 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 { addressToIndex, rangeToIndex } from '../../model';
22
- import { createTestSheet, testSheetName } from '../../testing';
23
- import { ValueTypeEnum, SheetType } from '../../types';
24
- import { type ComputeGraph, createComputeGraph } from '../ComputeGraph';
25
- // TODO(wittjosiah): Refactor. This is not exported from ./components due to depending on ECHO.
26
- 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';
27
23
  import { Toolbar, type ToolbarActionHandler } from '../Toolbar';
28
24
 
29
25
  // TODO(burdon): Allow toolbar to access sheet context; provide state for current cursor/range.
30
26
  const SheetWithToolbar = ({ debug, space }: { debug?: boolean; space: Space }) => {
31
27
  const { model, cursor, range } = useSheetContext();
32
28
 
29
+ const graph = useComputeGraph(space);
30
+ const handleRefresh = () => {
31
+ graph?.refresh();
32
+ };
33
+
33
34
  // TODO(burdon): Factor out.
34
35
  const handleAction: ToolbarActionHandler = ({ type }) => {
35
36
  log.info('action', { type, cursor, range });
@@ -82,11 +83,6 @@ const SheetWithToolbar = ({ debug, space }: { debug?: boolean; space: Space }) =
82
83
  }
83
84
  };
84
85
 
85
- const graph = useComputeGraph(space);
86
- const handleRefresh = () => {
87
- graph.refresh();
88
- };
89
-
90
86
  return (
91
87
  <div className='flex flex-col overflow-hidden'>
92
88
  <Toolbar.Root onAction={handleAction}>
@@ -103,56 +99,43 @@ const SheetWithToolbar = ({ debug, space }: { debug?: boolean; space: Space }) =
103
99
  );
104
100
  };
105
101
 
106
- const withGraphDecorator: Decorator = (Story) => {
107
- const [graphs, setGraphs] = useState<Record<string, ComputeGraph>>({});
108
-
109
- const setGraph = (key: string, graph: ComputeGraph) => {
110
- if (!graph.hf.doesSheetExist(testSheetName)) {
111
- const sheetName = graph.hf.addSheet(testSheetName);
112
- const sheet = graph.hf.getSheetId(sheetName)!;
113
- graph.hf.setCellContents({ sheet, col: 0, row: 0 }, Math.random());
114
- }
115
-
116
- setGraphs((graphs) => ({ ...graphs, [key]: graph }));
117
- };
118
-
119
- return (
120
- <ComputeGraphContextProvider graphs={graphs} setGraph={setGraph}>
121
- <Story />
122
- </ComputeGraphContextProvider>
123
- );
124
- };
125
-
126
102
  export default {
127
103
  title: 'plugin-sheet/Sheet',
128
104
  component: Sheet,
129
- decorators: [withTheme, withLayout({ fullscreen: true, tooltips: true, classNames: 'inset-4' }), withGraphDecorator],
105
+ decorators: [
106
+ withClientProvider({ types: [SheetType], createIdentity: true }),
107
+ withGraphDecorator,
108
+ withTheme,
109
+ withLayout({ fullscreen: true, tooltips: true, classNames: 'inset-4' }),
110
+ ],
130
111
  };
131
112
 
132
113
  export const Default = () => {
133
114
  const [debug, setDebug] = useState(false);
134
- const sheet = useTestSheet();
135
- const space = getSpace(sheet);
136
- if (!sheet || !space) {
115
+ const space = useSpace();
116
+ const graph = useComputeGraph(space);
117
+ const sheet = useTestSheet(space, graph);
118
+ if (!space || !sheet) {
137
119
  return null;
138
120
  }
139
121
 
140
122
  return (
141
- <Sheet.Root sheet={sheet} space={space} onInfo={() => setDebug((debug) => !debug)}>
123
+ <Sheet.Root space={space} sheet={sheet} onInfo={() => setDebug((debug) => !debug)}>
142
124
  <SheetWithToolbar debug={debug} space={space} />
143
125
  </Sheet.Root>
144
126
  );
145
127
  };
146
128
 
147
129
  export const Debug = () => {
148
- const sheet = useTestSheet();
149
- const space = getSpace(sheet);
130
+ const space = useSpace();
131
+ const graph = useComputeGraph(space);
132
+ const sheet = useTestSheet(space, graph);
150
133
  if (!sheet || !space) {
151
134
  return null;
152
135
  }
153
136
 
154
137
  return (
155
- <Sheet.Root sheet={sheet} space={space}>
138
+ <Sheet.Root space={space} sheet={sheet}>
156
139
  <Sheet.Main />
157
140
  <Sheet.Debug />
158
141
  </Sheet.Root>
@@ -161,14 +144,15 @@ export const Debug = () => {
161
144
 
162
145
  export const Rows = () => {
163
146
  const [rowSizes, setRowSizes] = useState<SizeMap>({});
164
- const sheet = useTestSheet();
165
- const space = getSpace(sheet);
147
+ const space = useSpace();
148
+ const graph = useComputeGraph(space);
149
+ const sheet = useTestSheet(space, graph);
166
150
  if (!sheet || !space) {
167
151
  return null;
168
152
  }
169
153
 
170
154
  return (
171
- <Sheet.Root sheet={sheet} space={space}>
155
+ <Sheet.Root space={space} sheet={sheet}>
172
156
  <Sheet.Rows
173
157
  rows={sheet.rows}
174
158
  sizes={rowSizes}
@@ -180,14 +164,15 @@ export const Rows = () => {
180
164
 
181
165
  export const Columns = () => {
182
166
  const [columnSizes, setColumnSizes] = useState<SizeMap>({});
183
- const sheet = useTestSheet();
184
- const space = getSpace(sheet);
167
+ const space = useSpace();
168
+ const graph = useComputeGraph(space);
169
+ const sheet = useTestSheet(space, graph);
185
170
  if (!sheet || !space) {
186
171
  return null;
187
172
  }
188
173
 
189
174
  return (
190
- <Sheet.Root sheet={sheet} space={space}>
175
+ <Sheet.Root space={space} sheet={sheet}>
191
176
  <Sheet.Columns
192
177
  columns={sheet.columns}
193
178
  sizes={columnSizes}
@@ -198,18 +183,19 @@ export const Columns = () => {
198
183
  };
199
184
 
200
185
  export const Main = () => {
201
- const sheet = useTestSheet();
202
- const space = getSpace(sheet);
186
+ const space = useSpace();
187
+ const graph = useComputeGraph(space);
188
+ const sheet = useTestSheet(space, graph);
203
189
  if (!sheet || !space) {
204
190
  return null;
205
191
  }
206
192
 
207
193
  return (
208
- <Sheet.Root sheet={sheet} space={space}>
194
+ <Sheet.Root space={space} sheet={sheet}>
209
195
  <Sheet.Grid
210
196
  size={{
211
197
  numRows: 50,
212
- numColumns: 26,
198
+ numCols: 26,
213
199
  }}
214
200
  rows={sheet.rows}
215
201
  columns={sheet.columns}
@@ -262,30 +248,3 @@ export const GridLayout = () => {
262
248
  const Cell = ({ className, label }: { className?: string; label: string }) => (
263
249
  <div className={mx('flex items-center justify-center border', className)}>{label}</div>
264
250
  );
265
-
266
- const useTestSheet = () => {
267
- const { graphs, setGraph } = useContext(ComputeGraphContext);
268
- const [sheet, setSheet] = useState<EchoReactiveObject<SheetType>>();
269
- useEffect(() => {
270
- const t = setTimeout(async () => {
271
- const client = new Client();
272
- await client.initialize();
273
- await client.halo.createIdentity();
274
- const space = await client.spaces.create();
275
- client.addTypes([SheetType]);
276
-
277
- const graph = graphs[space.id] ?? createComputeGraph();
278
- if (!graphs[space.id]) {
279
- setGraph(space.id, graph);
280
- }
281
-
282
- const sheet = await createTestSheet({ graph });
283
- space.db.add(sheet);
284
- setSheet(sheet);
285
- });
286
-
287
- return () => clearTimeout(t);
288
- }, []);
289
-
290
- return sheet;
291
- };
@@ -71,7 +71,7 @@ import {
71
71
  rangeToA1Notation,
72
72
  addressToIndex,
73
73
  addressFromIndex,
74
- } from '../../model';
74
+ } from '../../defs';
75
75
  import {
76
76
  CellEditor,
77
77
  type CellRangeNotifier,
@@ -138,7 +138,7 @@ const SheetRoot = ({ children, ...props }: PropsWithChildren<SheetContextProps>)
138
138
 
139
139
  type SheetMainProps = ThemedClassName<Partial<GridSize>>;
140
140
 
141
- const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numRows, numColumns }, forwardRef) => {
141
+ const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numRows, numCols }, forwardRef) => {
142
142
  const { model, cursor, setCursor, setRange, setEditing } = useSheetContext();
143
143
 
144
144
  // Scrolling.
@@ -263,8 +263,8 @@ const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numR
263
263
  ref={columnsRef}
264
264
  columns={columns}
265
265
  sizes={columnSizes}
266
- selected={cursor?.column}
267
- onSelect={(column) => setCursor(cursor?.column === column ? undefined : { row: -1, column })}
266
+ selected={cursor?.col}
267
+ onSelect={(col) => setCursor(cursor?.col === col ? undefined : { row: -1, col })}
268
268
  onResize={handleResizeColumn}
269
269
  onMove={handleMoveColumns}
270
270
  />
@@ -274,13 +274,13 @@ const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numR
274
274
  rows={rows}
275
275
  sizes={rowSizes}
276
276
  selected={cursor?.row}
277
- onSelect={(row) => setCursor(cursor?.row === row ? undefined : { row, column: -1 })}
277
+ onSelect={(row) => setCursor(cursor?.row === row ? undefined : { row, col: -1 })}
278
278
  onResize={handleResizeRow}
279
279
  onMove={handleMoveRows}
280
280
  />
281
281
  <SheetGrid
282
282
  ref={contentRef}
283
- size={{ numRows: numRows ?? rows.length, numColumns: numColumns ?? columns.length }}
283
+ size={{ numRows: numRows ?? rows.length, numCols: numCols ?? columns.length }}
284
284
  rows={rows}
285
285
  columns={columns}
286
286
  rowSizes={rowSizes}
@@ -885,9 +885,9 @@ const SheetGrid = forwardRef<HTMLDivElement, SheetGridProps>(
885
885
 
886
886
  {/* Grid cells. */}
887
887
  {rowRange.map(({ row, top, height }) => {
888
- return columnRange.map(({ column, left, width }) => {
888
+ return columnRange.map(({ col, left, width }) => {
889
889
  const style: CSSProperties = { position: 'absolute', top, left, width, height };
890
- const cell = { row, column };
890
+ const cell: CellAddress = { row, col };
891
891
  const id = addressToA1Notation(cell);
892
892
  const idx = addressToIndex(model.sheet, cell);
893
893
  const active = posEquals(cursor, cell);
@@ -1082,10 +1082,11 @@ const GridCellEditor = ({ style, value, onNav, onClose }: GridCellEditorProps) =
1082
1082
  notifier.current?.(rangeToA1Notation(range));
1083
1083
  }
1084
1084
  }, [range]);
1085
+
1085
1086
  const extension = useMemo(
1086
1087
  () => [
1087
1088
  editorKeys({ onNav, onClose }),
1088
- sheetExtension({ functions: model.functions }),
1089
+ sheetExtension({ functions: model.graph.getFunctions() }),
1089
1090
  rangeExtension((fn) => (notifier.current = fn)),
1090
1091
  ],
1091
1092
  [model],
@@ -1109,12 +1110,13 @@ const GridCellEditor = ({ style, value, onNav, onClose }: GridCellEditorProps) =
1109
1110
 
1110
1111
  const SheetStatusBar = () => {
1111
1112
  const { model, cursor, range } = useSheetContext();
1113
+
1112
1114
  let value;
1113
1115
  let isFormula = false;
1114
1116
  if (cursor) {
1115
1117
  value = model.getCellValue(cursor);
1116
1118
  if (typeof value === 'string' && value.charAt(0) === '=') {
1117
- value = model.mapFormulaBindingFromId(model.mapFormulaIndicesToRefs(value));
1119
+ value = model.graph.mapFunctionBindingFromId(model.mapFormulaIndicesToRefs(value));
1118
1120
  isFormula = true;
1119
1121
  } else if (value != null) {
1120
1122
  value = String(value);
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { type MouseEvent, useEffect, useState } from 'react';
6
6
 
7
- import { type CellAddress, type CellIndex, addressFromA1Notation, addressToA1Notation } from '../../model';
7
+ import { type CellAddress, type CellIndex, addressFromA1Notation, addressToA1Notation } from '../../defs';
8
8
 
9
9
  // export type Bounds = Pick<DOMRect, 'left' | 'top' | 'width' | 'height'>;
10
10
  // export type Dimension = Pick<DOMRect, 'width' | 'height'>;
@@ -12,7 +12,7 @@ import { type CellAddress, type CellIndex, addressFromA1Notation, addressToA1Not
12
12
  export type SizeMap = Record<string, number>;
13
13
 
14
14
  export type RowPosition = { row: number } & Pick<DOMRect, 'top' | 'height'>;
15
- export type ColumnPosition = { column: number } & Pick<DOMRect, 'left' | 'width'>;
15
+ export type ColumnPosition = { col: number } & Pick<DOMRect, 'left' | 'width'>;
16
16
 
17
17
  export const axisWidth = 'calc(var(--rail-size)-2px)';
18
18
  export const axisHeight = 34;
@@ -88,7 +88,7 @@ export const useGridLayout = ({
88
88
  const width = columnSizes?.[idx] ?? defaultWidth;
89
89
  const left = x;
90
90
  x += width - 1;
91
- return { column: i, left, width };
91
+ return { col: i, left, width };
92
92
  }),
93
93
  );
94
94
  }, [columns, columnSizes]);
@@ -5,11 +5,11 @@
5
5
  import { type KeyboardEvent, type MouseEventHandler, useState } from 'react';
6
6
 
7
7
  import { getCellAtPointer } from './grid';
8
- import { type CellAddress, type CellRange, posEquals } from '../../model';
8
+ import { type CellAddress, type CellRange, posEquals } from '../../defs';
9
9
 
10
10
  export type GridSize = {
11
11
  numRows: number;
12
- numColumns: number;
12
+ numCols: number;
13
13
  };
14
14
 
15
15
  /**
@@ -38,14 +38,14 @@ export const handleNav = (
38
38
  break;
39
39
  }
40
40
  case 'ArrowLeft': {
41
- if (opposite.column > 0) {
42
- opposite.column -= 1;
41
+ if (opposite.col > 0) {
42
+ opposite.col -= 1;
43
43
  }
44
44
  break;
45
45
  }
46
46
  case 'ArrowRight': {
47
- if (opposite.column < size.numColumns - 1) {
48
- opposite.column += 1;
47
+ if (opposite.col < size.numCols - 1) {
48
+ opposite.col += 1;
49
49
  }
50
50
  break;
51
51
  }
@@ -64,41 +64,41 @@ export const handleNav = (
64
64
  export const handleArrowNav = (
65
65
  ev: Pick<KeyboardEvent<HTMLInputElement>, 'key' | 'metaKey'>,
66
66
  cursor: CellAddress | undefined,
67
- { numRows, numColumns }: GridSize,
67
+ { numRows, numCols }: GridSize,
68
68
  ): CellAddress | undefined => {
69
69
  switch (ev.key) {
70
70
  case 'ArrowUp':
71
71
  if (cursor === undefined) {
72
- return { row: 0, column: 0 };
72
+ return { row: 0, col: 0 };
73
73
  } else if (cursor.row > 0) {
74
- return { row: ev.metaKey ? 0 : cursor.row - 1, column: cursor.column };
74
+ return { row: ev.metaKey ? 0 : cursor.row - 1, col: cursor.col };
75
75
  }
76
76
  break;
77
77
  case 'ArrowDown':
78
78
  if (cursor === undefined) {
79
- return { row: 0, column: 0 };
79
+ return { row: 0, col: 0 };
80
80
  } else if (cursor.row < numRows - 1) {
81
- return { row: ev.metaKey ? numRows - 1 : cursor.row + 1, column: cursor.column };
81
+ return { row: ev.metaKey ? numRows - 1 : cursor.row + 1, col: cursor.col };
82
82
  }
83
83
  break;
84
84
  case 'ArrowLeft':
85
85
  if (cursor === undefined) {
86
- return { row: 0, column: 0 };
87
- } else if (cursor.column > 0) {
88
- return { row: cursor.row, column: ev.metaKey ? 0 : cursor.column - 1 };
86
+ return { row: 0, col: 0 };
87
+ } else if (cursor.col > 0) {
88
+ return { row: cursor.row, col: ev.metaKey ? 0 : cursor.col - 1 };
89
89
  }
90
90
  break;
91
91
  case 'ArrowRight':
92
92
  if (cursor === undefined) {
93
- return { row: 0, column: 0 };
94
- } else if (cursor.column < numColumns - 1) {
95
- return { row: cursor.row, column: ev.metaKey ? numColumns - 1 : cursor.column + 1 };
93
+ return { row: 0, col: 0 };
94
+ } else if (cursor.col < numCols - 1) {
95
+ return { row: cursor.row, col: ev.metaKey ? numCols - 1 : cursor.col + 1 };
96
96
  }
97
97
  break;
98
98
  case 'Home':
99
- return { row: 0, column: 0 };
99
+ return { row: 0, col: 0 };
100
100
  case 'End':
101
- return { row: numRows - 1, column: numColumns - 1 };
101
+ return { row: numRows - 1, col: numCols - 1 };
102
102
  }
103
103
  };
104
104