@dxos/plugin-sheet 0.6.12-main.ed7cda7 → 0.6.12-staging.0b4bb48

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 (260) hide show
  1. package/dist/lib/browser/{chunk-U2JHW3L6.mjs → SheetContainer-U4H5D34A.mjs} +240 -1020
  2. package/dist/lib/browser/SheetContainer-U4H5D34A.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-APHOLYUB.mjs +175 -0
  4. package/dist/lib/browser/chunk-APHOLYUB.mjs.map +7 -0
  5. package/dist/lib/{node-esm/chunk-D6KU5MI7.mjs → browser/chunk-D5AGLXJP.mjs} +670 -360
  6. package/dist/lib/browser/chunk-D5AGLXJP.mjs.map +7 -0
  7. package/dist/lib/browser/{chunk-T3NJFTD4.mjs → chunk-FUAGSXA4.mjs} +15 -8
  8. package/dist/lib/browser/chunk-FUAGSXA4.mjs.map +7 -0
  9. package/dist/lib/browser/{chunk-QILRZNE5.mjs → chunk-JRL5LGCE.mjs} +5 -2
  10. package/dist/lib/browser/chunk-JRL5LGCE.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-NU4PBN33.mjs +8 -0
  12. package/dist/lib/browser/chunk-NU4PBN33.mjs.map +7 -0
  13. package/dist/lib/browser/index.mjs +56 -68
  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/testing.mjs +92 -0
  18. package/dist/lib/browser/testing.mjs.map +7 -0
  19. package/dist/lib/browser/types.mjs +6 -4
  20. package/dist/lib/node/{chunk-OTTD7FBK.cjs → SheetContainer-AXQV3ZT5.cjs} +279 -1050
  21. package/dist/lib/node/SheetContainer-AXQV3ZT5.cjs.map +7 -0
  22. package/dist/lib/node/{chunk-DD6FIXWC.cjs → chunk-5KKJ4NPP.cjs} +667 -360
  23. package/dist/lib/node/chunk-5KKJ4NPP.cjs.map +7 -0
  24. package/dist/lib/node/{chunk-BNARJ5GM.cjs → chunk-BJ6ZD7MN.cjs} +18 -5
  25. package/dist/lib/node/chunk-BJ6ZD7MN.cjs.map +7 -0
  26. package/dist/lib/node/chunk-CN3RPESU.cjs +202 -0
  27. package/dist/lib/node/chunk-CN3RPESU.cjs.map +7 -0
  28. package/dist/lib/node/{chunk-Q3HBHPRL.cjs → chunk-DSYKOI4E.cjs} +20 -12
  29. package/dist/lib/node/chunk-DSYKOI4E.cjs.map +7 -0
  30. package/dist/lib/node/chunk-PYXHNAAK.cjs +40 -0
  31. package/dist/lib/node/chunk-PYXHNAAK.cjs.map +7 -0
  32. package/dist/lib/node/index.cjs +64 -83
  33. package/dist/lib/node/index.cjs.map +3 -3
  34. package/dist/lib/node/meta.cjs +3 -3
  35. package/dist/lib/node/meta.cjs.map +1 -1
  36. package/dist/lib/node/meta.json +1 -1
  37. package/dist/lib/node/testing.cjs +111 -0
  38. package/dist/lib/node/testing.cjs.map +7 -0
  39. package/dist/lib/node/types.cjs +12 -10
  40. package/dist/lib/node/types.cjs.map +2 -2
  41. package/dist/types/src/SheetPlugin.d.ts.map +1 -1
  42. package/dist/types/src/components/CellEditor/CellEditor.d.ts +3 -23
  43. package/dist/types/src/components/CellEditor/CellEditor.d.ts.map +1 -1
  44. package/dist/types/src/components/CellEditor/CellEditor.stories.d.ts +2 -2
  45. package/dist/types/src/components/CellEditor/CellEditor.stories.d.ts.map +1 -1
  46. package/dist/types/src/components/CellEditor/extension.d.ts +1 -1
  47. package/dist/types/src/components/CellEditor/extension.d.ts.map +1 -1
  48. package/dist/types/src/{graph → components/ComputeGraph}/async-function.d.ts +1 -1
  49. package/dist/types/src/components/ComputeGraph/async-function.d.ts.map +1 -0
  50. package/dist/types/src/{graph/custom-function.d.ts → components/ComputeGraph/custom.d.ts} +1 -1
  51. package/dist/types/src/components/ComputeGraph/custom.d.ts.map +1 -0
  52. package/dist/types/src/components/ComputeGraph/edge-function.d.ts.map +1 -0
  53. package/dist/types/src/components/ComputeGraph/graph-context.d.ts +12 -0
  54. package/dist/types/src/components/ComputeGraph/graph-context.d.ts.map +1 -0
  55. package/dist/types/src/components/ComputeGraph/graph.browser.test.d.ts +2 -0
  56. package/dist/types/src/components/ComputeGraph/graph.browser.test.d.ts.map +1 -0
  57. package/dist/types/src/components/ComputeGraph/graph.d.ts +26 -0
  58. package/dist/types/src/components/ComputeGraph/graph.d.ts.map +1 -0
  59. package/dist/types/src/components/ComputeGraph/index.d.ts +3 -1
  60. package/dist/types/src/components/ComputeGraph/index.d.ts.map +1 -1
  61. package/dist/types/src/components/Sheet/Sheet.d.ts +1 -1
  62. package/dist/types/src/components/Sheet/Sheet.d.ts.map +1 -1
  63. package/dist/types/src/components/Sheet/Sheet.stories.d.ts +6 -5
  64. package/dist/types/src/components/Sheet/Sheet.stories.d.ts.map +1 -1
  65. package/dist/types/src/components/Sheet/formatting.d.ts +14 -0
  66. package/dist/types/src/components/Sheet/formatting.d.ts.map +1 -0
  67. package/dist/types/src/components/Sheet/grid.d.ts +2 -2
  68. package/dist/types/src/components/Sheet/grid.d.ts.map +1 -1
  69. package/dist/types/src/components/Sheet/nav.d.ts +3 -3
  70. package/dist/types/src/components/Sheet/nav.d.ts.map +1 -1
  71. package/dist/types/src/components/Sheet/sheet-context.d.ts +5 -6
  72. package/dist/types/src/components/Sheet/sheet-context.d.ts.map +1 -1
  73. package/dist/types/src/components/SheetContainer.d.ts +3 -2
  74. package/dist/types/src/components/SheetContainer.d.ts.map +1 -1
  75. package/dist/types/src/components/Toolbar/Toolbar.d.ts +3 -19
  76. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
  77. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +13 -18
  78. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
  79. package/dist/types/src/components/index.d.ts +2 -2
  80. package/dist/types/src/components/index.d.ts.map +1 -1
  81. package/dist/types/src/meta.d.ts +4 -1
  82. package/dist/types/src/meta.d.ts.map +1 -1
  83. package/dist/types/src/{graph/function-defs.d.ts → model/functions.d.ts} +1 -1
  84. package/dist/types/src/model/functions.d.ts.map +1 -0
  85. package/dist/types/src/model/index.d.ts +3 -2
  86. package/dist/types/src/model/index.d.ts.map +1 -1
  87. package/dist/types/src/model/model.browser.test.d.ts +2 -0
  88. package/dist/types/src/model/model.browser.test.d.ts.map +1 -0
  89. package/dist/types/src/model/{sheet-model.d.ts → model.d.ts} +64 -9
  90. package/dist/types/src/model/model.d.ts.map +1 -0
  91. package/dist/types/src/{defs → model}/types.d.ts +3 -8
  92. package/dist/types/src/model/types.d.ts.map +1 -0
  93. package/dist/types/src/model/types.test.d.ts.map +1 -0
  94. package/dist/types/src/model/util.d.ts +15 -0
  95. package/dist/types/src/model/util.d.ts.map +1 -0
  96. package/dist/types/src/testing.d.ts +9 -0
  97. package/dist/types/src/testing.d.ts.map +1 -0
  98. package/dist/types/src/translations.d.ts +12 -17
  99. package/dist/types/src/translations.d.ts.map +1 -1
  100. package/dist/types/src/types.d.ts +3 -83
  101. package/dist/types/src/types.d.ts.map +1 -1
  102. package/package.json +41 -48
  103. package/src/SheetPlugin.tsx +70 -43
  104. package/src/components/CellEditor/CellEditor.stories.tsx +3 -4
  105. package/src/components/CellEditor/CellEditor.tsx +9 -59
  106. package/src/components/CellEditor/extension.test.ts +5 -4
  107. package/src/components/CellEditor/extension.ts +3 -1
  108. package/src/{graph → components/ComputeGraph}/async-function.ts +1 -3
  109. package/src/{graph/custom-function.ts → components/ComputeGraph/custom.ts} +6 -2
  110. package/src/{graph → components/ComputeGraph}/edge-function.ts +1 -2
  111. package/src/components/ComputeGraph/graph-context.tsx +50 -0
  112. package/src/components/ComputeGraph/graph.browser.test.ts +50 -0
  113. package/src/components/ComputeGraph/graph.ts +62 -0
  114. package/src/components/ComputeGraph/index.ts +3 -1
  115. package/src/components/Sheet/Sheet.stories.tsx +82 -45
  116. package/src/components/Sheet/Sheet.tsx +18 -57
  117. package/src/{model/formatting-model.ts → components/Sheet/formatting.ts} +13 -20
  118. package/src/components/Sheet/grid.ts +3 -3
  119. package/src/components/Sheet/nav.ts +19 -19
  120. package/src/components/Sheet/sheet-context.tsx +78 -16
  121. package/src/components/SheetContainer.tsx +19 -73
  122. package/src/components/Toolbar/Toolbar.tsx +12 -53
  123. package/src/components/index.ts +0 -1
  124. package/src/meta.tsx +5 -1
  125. package/src/model/index.ts +3 -2
  126. package/src/model/model.browser.test.ts +100 -0
  127. package/src/model/model.ts +550 -0
  128. package/src/{defs → model}/types.test.ts +9 -8
  129. package/src/{defs → model}/types.ts +14 -23
  130. package/src/model/util.ts +36 -0
  131. package/src/testing.ts +50 -0
  132. package/src/translations.ts +1 -6
  133. package/src/types.ts +5 -30
  134. package/dist/lib/browser/SheetContainer-V4GCCZTX.mjs +0 -261
  135. package/dist/lib/browser/SheetContainer-V4GCCZTX.mjs.map +0 -7
  136. package/dist/lib/browser/chunk-6ZMQVB4Z.mjs +0 -2923
  137. package/dist/lib/browser/chunk-6ZMQVB4Z.mjs.map +0 -7
  138. package/dist/lib/browser/chunk-QILRZNE5.mjs.map +0 -7
  139. package/dist/lib/browser/chunk-T3NJFTD4.mjs.map +0 -7
  140. package/dist/lib/browser/chunk-U2JHW3L6.mjs.map +0 -7
  141. package/dist/lib/browser/graph-T27BOBOV.mjs +0 -21
  142. package/dist/lib/browser/graph-T27BOBOV.mjs.map +0 -7
  143. package/dist/lib/node/SheetContainer-3ZY7MPWJ.cjs +0 -279
  144. package/dist/lib/node/SheetContainer-3ZY7MPWJ.cjs.map +0 -7
  145. package/dist/lib/node/chunk-BNARJ5GM.cjs.map +0 -7
  146. package/dist/lib/node/chunk-DD6FIXWC.cjs.map +0 -7
  147. package/dist/lib/node/chunk-OTTD7FBK.cjs.map +0 -7
  148. package/dist/lib/node/chunk-Q3HBHPRL.cjs.map +0 -7
  149. package/dist/lib/node/graph-SPKGX7W4.cjs +0 -43
  150. package/dist/lib/node/graph-SPKGX7W4.cjs.map +0 -7
  151. package/dist/lib/node-esm/SheetContainer-PXSJX6XK.mjs +0 -262
  152. package/dist/lib/node-esm/SheetContainer-PXSJX6XK.mjs.map +0 -7
  153. package/dist/lib/node-esm/chunk-7HVSOTGA.mjs +0 -2553
  154. package/dist/lib/node-esm/chunk-7HVSOTGA.mjs.map +0 -7
  155. package/dist/lib/node-esm/chunk-BMNA27EX.mjs +0 -76
  156. package/dist/lib/node-esm/chunk-BMNA27EX.mjs.map +0 -7
  157. package/dist/lib/node-esm/chunk-D6KU5MI7.mjs.map +0 -7
  158. package/dist/lib/node-esm/chunk-IU2L277A.mjs +0 -17
  159. package/dist/lib/node-esm/chunk-IU2L277A.mjs.map +0 -7
  160. package/dist/lib/node-esm/graph-U67IO4UC.mjs +0 -22
  161. package/dist/lib/node-esm/graph-U67IO4UC.mjs.map +0 -7
  162. package/dist/lib/node-esm/index.mjs +0 -261
  163. package/dist/lib/node-esm/index.mjs.map +0 -7
  164. package/dist/lib/node-esm/meta.json +0 -1
  165. package/dist/lib/node-esm/meta.mjs +0 -10
  166. package/dist/lib/node-esm/meta.mjs.map +0 -7
  167. package/dist/lib/node-esm/types.mjs +0 -21
  168. package/dist/lib/node-esm/types.mjs.map +0 -7
  169. package/dist/types/src/components/ComputeGraph/ComputeGraphContextProvider.d.ts +0 -11
  170. package/dist/types/src/components/ComputeGraph/ComputeGraphContextProvider.d.ts.map +0 -1
  171. package/dist/types/src/components/GridSheet/GridSheet.d.ts +0 -10
  172. package/dist/types/src/components/GridSheet/GridSheet.d.ts.map +0 -1
  173. package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts +0 -9
  174. package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts.map +0 -1
  175. package/dist/types/src/components/GridSheet/util.d.ts +0 -7
  176. package/dist/types/src/components/GridSheet/util.d.ts.map +0 -1
  177. package/dist/types/src/components/Sheet/decorations.d.ts +0 -24
  178. package/dist/types/src/components/Sheet/decorations.d.ts.map +0 -1
  179. package/dist/types/src/components/Sheet/threads.d.ts +0 -2
  180. package/dist/types/src/components/Sheet/threads.d.ts.map +0 -1
  181. package/dist/types/src/defs/index.d.ts +0 -3
  182. package/dist/types/src/defs/index.d.ts.map +0 -1
  183. package/dist/types/src/defs/types.d.ts.map +0 -1
  184. package/dist/types/src/defs/types.test.d.ts.map +0 -1
  185. package/dist/types/src/defs/util.d.ts +0 -43
  186. package/dist/types/src/defs/util.d.ts.map +0 -1
  187. package/dist/types/src/extensions/compute.d.ts +0 -5
  188. package/dist/types/src/extensions/compute.d.ts.map +0 -1
  189. package/dist/types/src/extensions/compute.stories.d.ts +0 -26
  190. package/dist/types/src/extensions/compute.stories.d.ts.map +0 -1
  191. package/dist/types/src/extensions/index.d.ts +0 -2
  192. package/dist/types/src/extensions/index.d.ts.map +0 -1
  193. package/dist/types/src/graph/async-function.d.ts.map +0 -1
  194. package/dist/types/src/graph/compute-graph.browser.test.d.ts +0 -2
  195. package/dist/types/src/graph/compute-graph.browser.test.d.ts.map +0 -1
  196. package/dist/types/src/graph/compute-graph.d.ts +0 -81
  197. package/dist/types/src/graph/compute-graph.d.ts.map +0 -1
  198. package/dist/types/src/graph/compute-graph.stories.d.ts +0 -10
  199. package/dist/types/src/graph/compute-graph.stories.d.ts.map +0 -1
  200. package/dist/types/src/graph/compute-node.d.ts +0 -19
  201. package/dist/types/src/graph/compute-node.d.ts.map +0 -1
  202. package/dist/types/src/graph/custom-function.d.ts.map +0 -1
  203. package/dist/types/src/graph/edge-function.d.ts.map +0 -1
  204. package/dist/types/src/graph/function-defs.d.ts.map +0 -1
  205. package/dist/types/src/graph/hyperformula.test.d.ts +0 -2
  206. package/dist/types/src/graph/hyperformula.test.d.ts.map +0 -1
  207. package/dist/types/src/graph/index.d.ts +0 -4
  208. package/dist/types/src/graph/index.d.ts.map +0 -1
  209. package/dist/types/src/graph/util.d.ts +0 -2
  210. package/dist/types/src/graph/util.d.ts.map +0 -1
  211. package/dist/types/src/hooks/hooks.stories.d.ts +0 -11
  212. package/dist/types/src/hooks/hooks.stories.d.ts.map +0 -1
  213. package/dist/types/src/hooks/index.d.ts +0 -4
  214. package/dist/types/src/hooks/index.d.ts.map +0 -1
  215. package/dist/types/src/hooks/useComputeGraph.d.ts +0 -7
  216. package/dist/types/src/hooks/useComputeGraph.d.ts.map +0 -1
  217. package/dist/types/src/hooks/useFormattingModel.d.ts +0 -3
  218. package/dist/types/src/hooks/useFormattingModel.d.ts.map +0 -1
  219. package/dist/types/src/hooks/useSheetModel.d.ts +0 -8
  220. package/dist/types/src/hooks/useSheetModel.d.ts.map +0 -1
  221. package/dist/types/src/model/formatting-model.d.ts +0 -16
  222. package/dist/types/src/model/formatting-model.d.ts.map +0 -1
  223. package/dist/types/src/model/sheet-model.d.ts.map +0 -1
  224. package/dist/types/src/sanity.test.d.ts +0 -2
  225. package/dist/types/src/sanity.test.d.ts.map +0 -1
  226. package/dist/types/src/testing/index.d.ts +0 -2
  227. package/dist/types/src/testing/index.d.ts.map +0 -1
  228. package/dist/types/src/testing/testing.d.ts +0 -9
  229. package/dist/types/src/testing/testing.d.ts.map +0 -1
  230. package/dist/vendor/hyperformula.mjs +0 -37145
  231. package/src/components/ComputeGraph/ComputeGraphContextProvider.tsx +0 -20
  232. package/src/components/GridSheet/GridSheet.stories.tsx +0 -35
  233. package/src/components/GridSheet/GridSheet.tsx +0 -153
  234. package/src/components/GridSheet/util.ts +0 -108
  235. package/src/components/Sheet/decorations.ts +0 -62
  236. package/src/components/Sheet/threads.tsx +0 -205
  237. package/src/defs/index.ts +0 -6
  238. package/src/defs/util.ts +0 -135
  239. package/src/extensions/compute.stories.tsx +0 -151
  240. package/src/extensions/compute.ts +0 -98
  241. package/src/extensions/index.ts +0 -5
  242. package/src/graph/compute-graph.browser.test.ts +0 -104
  243. package/src/graph/compute-graph.stories.tsx +0 -92
  244. package/src/graph/compute-graph.ts +0 -290
  245. package/src/graph/compute-node.ts +0 -51
  246. package/src/graph/hyperformula.test.ts +0 -15
  247. package/src/graph/index.ts +0 -7
  248. package/src/graph/util.ts +0 -8
  249. package/src/hooks/hooks.stories.tsx +0 -50
  250. package/src/hooks/index.ts +0 -7
  251. package/src/hooks/useComputeGraph.ts +0 -20
  252. package/src/hooks/useFormattingModel.ts +0 -11
  253. package/src/hooks/useSheetModel.ts +0 -43
  254. package/src/model/sheet-model.ts +0 -399
  255. package/src/sanity.test.ts +0 -40
  256. package/src/testing/index.ts +0 -5
  257. package/src/testing/testing.tsx +0 -66
  258. /package/dist/types/src/{graph → components/ComputeGraph}/edge-function.d.ts +0 -0
  259. /package/dist/types/src/{defs → model}/types.test.d.ts +0 -0
  260. /package/src/{graph/function-defs.ts → model/functions.ts} +0 -0
@@ -60,7 +60,6 @@ import {
60
60
  } from './grid';
61
61
  import { type GridSize, handleArrowNav, handleNav, useRangeSelect } from './nav';
62
62
  import { type SheetContextProps, SheetContextProvider, useSheetContext } from './sheet-context';
63
- import { useThreads } from './threads';
64
63
  import { getRectUnion, getRelativeClientRect, scrollIntoView } from './util';
65
64
  import {
66
65
  type CellIndex,
@@ -69,9 +68,7 @@ import {
69
68
  columnLetter,
70
69
  posEquals,
71
70
  rangeToA1Notation,
72
- addressToIndex,
73
- addressFromIndex,
74
- } from '../../defs';
71
+ } from '../../model';
75
72
  import {
76
73
  CellEditor,
77
74
  type CellRangeNotifier,
@@ -138,16 +135,12 @@ const SheetRoot = ({ children, ...props }: PropsWithChildren<SheetContextProps>)
138
135
 
139
136
  type SheetMainProps = ThemedClassName<Partial<GridSize>>;
140
137
 
141
- const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numRows, numCols }, forwardRef) => {
138
+ const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numRows, numColumns }, forwardRef) => {
142
139
  const { model, cursor, setCursor, setRange, setEditing } = useSheetContext();
143
140
 
144
141
  // Scrolling.
145
142
  const { rowsRef, columnsRef, contentRef } = useScrollHandlers();
146
143
 
147
- // Threads.
148
- // TODO(Zan): Move this to an extension once we have an extension model.
149
- useThreads();
150
-
151
144
  //
152
145
  // Order of Row/columns.
153
146
  //
@@ -177,21 +170,21 @@ const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numR
177
170
  }, [rows, columns]);
178
171
 
179
172
  const handleMoveRows: SheetRowsProps['onMove'] = (from, to, num = 1) => {
180
- const cursorIdx = cursor ? addressToIndex(model.sheet, cursor) : undefined;
173
+ const cursorIdx = cursor ? model.addressToIndex(cursor) : undefined;
181
174
  const [rows] = model.sheet.rows.splice(from, num);
182
175
  model.sheet.rows.splice(to, 0, rows);
183
176
  if (cursorIdx) {
184
- setCursor(addressFromIndex(model.sheet, cursorIdx));
177
+ setCursor(model.addressFromIndex(cursorIdx));
185
178
  }
186
179
  setRows([...model.sheet.rows]);
187
180
  };
188
181
 
189
182
  const handleMoveColumns: SheetColumnsProps['onMove'] = (from, to, num = 1) => {
190
- const cursorIdx = cursor ? addressToIndex(model.sheet, cursor) : undefined;
183
+ const cursorIdx = cursor ? model.addressToIndex(cursor) : undefined;
191
184
  const columns = model.sheet.columns.splice(from, num);
192
185
  model.sheet.columns.splice(to, 0, ...columns);
193
186
  if (cursorIdx) {
194
- setCursor(addressFromIndex(model.sheet, cursorIdx));
187
+ setCursor(model.addressFromIndex(cursorIdx));
195
188
  }
196
189
  setColumns([...model.sheet.columns]);
197
190
  };
@@ -263,8 +256,8 @@ const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numR
263
256
  ref={columnsRef}
264
257
  columns={columns}
265
258
  sizes={columnSizes}
266
- selected={cursor?.col}
267
- onSelect={(col) => setCursor(cursor?.col === col ? undefined : { row: -1, col })}
259
+ selected={cursor?.column}
260
+ onSelect={(column) => setCursor(cursor?.column === column ? undefined : { row: -1, column })}
268
261
  onResize={handleResizeColumn}
269
262
  onMove={handleMoveColumns}
270
263
  />
@@ -274,13 +267,13 @@ const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numR
274
267
  rows={rows}
275
268
  sizes={rowSizes}
276
269
  selected={cursor?.row}
277
- onSelect={(row) => setCursor(cursor?.row === row ? undefined : { row, col: -1 })}
270
+ onSelect={(row) => setCursor(cursor?.row === row ? undefined : { row, column: -1 })}
278
271
  onResize={handleResizeRow}
279
272
  onMove={handleMoveRows}
280
273
  />
281
274
  <SheetGrid
282
275
  ref={contentRef}
283
- size={{ numRows: numRows ?? rows.length, numCols: numCols ?? columns.length }}
276
+ size={{ numRows: numRows ?? rows.length, numColumns: numColumns ?? columns.length }}
284
277
  rows={rows}
285
278
  columns={columns}
286
279
  rowSizes={rowSizes}
@@ -885,11 +878,11 @@ const SheetGrid = forwardRef<HTMLDivElement, SheetGridProps>(
885
878
 
886
879
  {/* Grid cells. */}
887
880
  {rowRange.map(({ row, top, height }) => {
888
- return columnRange.map(({ col, left, width }) => {
881
+ return columnRange.map(({ column, left, width }) => {
889
882
  const style: CSSProperties = { position: 'absolute', top, left, width, height };
890
- const cell: CellAddress = { row, col };
883
+ const cell = { row, column };
891
884
  const id = addressToA1Notation(cell);
892
- const idx = addressToIndex(model.sheet, cell);
885
+ const idx = model.addressToIndex(cell);
893
886
  const active = posEquals(cursor, cell);
894
887
  if (active && editing) {
895
888
  const value = initialText.current ?? model.getCellText(cell) ?? '';
@@ -1010,46 +1003,16 @@ type SheetCellProps = {
1010
1003
  };
1011
1004
 
1012
1005
  const SheetCell = ({ id, cell, style, active, onSelect }: SheetCellProps) => {
1013
- const {
1014
- formatting,
1015
- editing,
1016
- setRange,
1017
- decorations,
1018
- model: { sheet },
1019
- } = useSheetContext();
1006
+ const { formatting, editing, setRange } = useSheetContext();
1020
1007
  const { value, classNames } = formatting.getFormatting(cell);
1021
1008
 
1022
- const decorationsForCell = decorations.getDecorationsForCell(addressToIndex(sheet, cell)) ?? [];
1023
- const decorationAddedClasses = useMemo(
1024
- () => decorationsForCell.flatMap((d) => d.classNames ?? []),
1025
- [decorationsForCell],
1026
- );
1027
- const decoratedContent = decorationsForCell.reduce(
1028
- (children, { decorate }) => {
1029
- if (!decorate) {
1030
- return children;
1031
- }
1032
- const DecoratorComponent = decorate;
1033
- return <DecoratorComponent>{children}</DecoratorComponent>;
1034
- },
1035
- <div
1036
- role='none'
1037
- className={mx(
1038
- 'flex flex-grow bs-full is-full px-2 items-center truncate cursor-pointer',
1039
- ...decorationAddedClasses,
1040
- )}
1041
- >
1042
- {value}
1043
- </div>,
1044
- );
1045
-
1046
1009
  return (
1047
1010
  <div
1048
1011
  {...{ [`data-${CELL_DATA_KEY}`]: id }}
1049
1012
  role='cell'
1050
1013
  style={style}
1051
1014
  className={mx(
1052
- 'border border-gridLine cursor-pointer',
1015
+ 'flex w-full h-full px-2 py-1 truncate items-center border border-gridLine cursor-pointer',
1053
1016
  fragments.cell,
1054
1017
  active && ['z-20', fragments.cellSelected],
1055
1018
  classNames,
@@ -1063,7 +1026,7 @@ const SheetCell = ({ id, cell, style, active, onSelect }: SheetCellProps) => {
1063
1026
  }}
1064
1027
  onDoubleClick={() => onSelect?.(cell, true)}
1065
1028
  >
1066
- {decoratedContent}
1029
+ {value}
1067
1030
  </div>
1068
1031
  );
1069
1032
  };
@@ -1082,11 +1045,10 @@ const GridCellEditor = ({ style, value, onNav, onClose }: GridCellEditorProps) =
1082
1045
  notifier.current?.(rangeToA1Notation(range));
1083
1046
  }
1084
1047
  }, [range]);
1085
-
1086
1048
  const extension = useMemo(
1087
1049
  () => [
1088
1050
  editorKeys({ onNav, onClose }),
1089
- sheetExtension({ functions: model.graph.getFunctions() }),
1051
+ sheetExtension({ functions: model.functions }),
1090
1052
  rangeExtension((fn) => (notifier.current = fn)),
1091
1053
  ],
1092
1054
  [model],
@@ -1110,13 +1072,12 @@ const GridCellEditor = ({ style, value, onNav, onClose }: GridCellEditorProps) =
1110
1072
 
1111
1073
  const SheetStatusBar = () => {
1112
1074
  const { model, cursor, range } = useSheetContext();
1113
-
1114
1075
  let value;
1115
1076
  let isFormula = false;
1116
1077
  if (cursor) {
1117
1078
  value = model.getCellValue(cursor);
1118
1079
  if (typeof value === 'string' && value.charAt(0) === '=') {
1119
- value = model.graph.mapFunctionBindingFromId(model.mapFormulaIndicesToRefs(value));
1080
+ value = model.mapFormulaBindingFromId(model.mapFormulaIndicesToRefs(value));
1120
1081
  isFormula = true;
1121
1082
  } else if (value != null) {
1122
1083
  value = String(value);
@@ -4,24 +4,17 @@
4
4
 
5
5
  import { type ClassNameValue } from '@dxos/react-ui-types';
6
6
 
7
- import { type SheetModel } from './sheet-model';
8
- import { type CellAddress, inRange } from '../defs';
9
- import { addressToIndex, rangeFromIndex } from '../defs';
10
- import { ValueTypeEnum } from '../types';
11
-
12
- export type CellFormat = {
13
- value?: string;
14
- classNames?: ClassNameValue;
15
- };
7
+ import { type SheetModel, type CellAddress, inRange } from '../../model';
8
+ import { ValueTypeEnum } from '../../types';
16
9
 
17
10
  export class FormattingModel {
18
- constructor(private readonly _model: SheetModel) {}
11
+ constructor(private readonly model: SheetModel) {}
19
12
 
20
13
  /**
21
14
  * Get formatted string value and className for cell.
22
15
  */
23
- getFormatting(cell: CellAddress): CellFormat {
24
- const value = this._model.getValue(cell);
16
+ getFormatting(cell: CellAddress): { value?: string; classNames?: ClassNameValue } {
17
+ const value = this.model.getValue(cell);
25
18
  if (value === undefined || value === null) {
26
19
  return {};
27
20
  }
@@ -30,15 +23,15 @@ export class FormattingModel {
30
23
  const locales = undefined;
31
24
 
32
25
  // Cell-specific formatting.
33
- const idx = addressToIndex(this._model.sheet, cell);
34
- let formatting = this._model.sheet.formatting?.[idx] ?? {};
26
+ const idx = this.model.addressToIndex(cell);
27
+ let formatting = this.model.sheet.formatting?.[idx] ?? {};
35
28
  const classNames = [...(formatting?.classNames ?? [])];
36
29
 
37
30
  // Range formatting.
38
31
  // TODO(burdon): NOTE: D0 means the D column.
39
32
  // TODO(burdon): Cache model formatting (e.g., for ranges). Create class out of this function.
40
- for (const [idx, _formatting] of Object.entries(this._model.sheet.formatting)) {
41
- const range = rangeFromIndex(this._model.sheet, idx);
33
+ for (const [idx, _formatting] of Object.entries(this.model.sheet.formatting)) {
34
+ const range = this.model.rangeFromIndex(idx);
42
35
  if (inRange(range, cell)) {
43
36
  if (_formatting.classNames) {
44
37
  classNames.push(..._formatting.classNames);
@@ -53,7 +46,7 @@ export class FormattingModel {
53
46
 
54
47
  const defaultNumber = 'justify-end font-mono';
55
48
 
56
- const type = formatting?.type ?? this._model.getValueType(cell);
49
+ const type = formatting?.type ?? this.model.getValueType(cell);
57
50
  switch (type) {
58
51
  case ValueTypeEnum.Boolean: {
59
52
  return {
@@ -91,17 +84,17 @@ export class FormattingModel {
91
84
  //
92
85
 
93
86
  case ValueTypeEnum.DateTime: {
94
- const date = this._model.toLocalDate(value as number);
87
+ const date = this.model.toLocalDate(value as number);
95
88
  return { value: date.toLocaleString(locales), classNames };
96
89
  }
97
90
 
98
91
  case ValueTypeEnum.Date: {
99
- const date = this._model.toLocalDate(value as number);
92
+ const date = this.model.toLocalDate(value as number);
100
93
  return { value: date.toLocaleDateString(locales), classNames };
101
94
  }
102
95
 
103
96
  case ValueTypeEnum.Time: {
104
- const date = this._model.toLocalDate(value as number);
97
+ const date = this.model.toLocalDate(value as number);
105
98
  return { value: date.toLocaleTimeString(locales), classNames };
106
99
  }
107
100
 
@@ -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 '../../defs';
7
+ import { type CellAddress, type CellIndex, addressFromA1Notation, addressToA1Notation } from '../../model';
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 = { col: number } & Pick<DOMRect, 'left' | 'width'>;
15
+ export type ColumnPosition = { column: 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 { col: i, left, width };
91
+ return { column: 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 '../../defs';
8
+ import { type CellAddress, type CellRange, posEquals } from '../../model';
9
9
 
10
10
  export type GridSize = {
11
11
  numRows: number;
12
- numCols: number;
12
+ numColumns: 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.col > 0) {
42
- opposite.col -= 1;
41
+ if (opposite.column > 0) {
42
+ opposite.column -= 1;
43
43
  }
44
44
  break;
45
45
  }
46
46
  case 'ArrowRight': {
47
- if (opposite.col < size.numCols - 1) {
48
- opposite.col += 1;
47
+ if (opposite.column < size.numColumns - 1) {
48
+ opposite.column += 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, numCols }: GridSize,
67
+ { numRows, numColumns }: GridSize,
68
68
  ): CellAddress | undefined => {
69
69
  switch (ev.key) {
70
70
  case 'ArrowUp':
71
71
  if (cursor === undefined) {
72
- return { row: 0, col: 0 };
72
+ return { row: 0, column: 0 };
73
73
  } else if (cursor.row > 0) {
74
- return { row: ev.metaKey ? 0 : cursor.row - 1, col: cursor.col };
74
+ return { row: ev.metaKey ? 0 : cursor.row - 1, column: cursor.column };
75
75
  }
76
76
  break;
77
77
  case 'ArrowDown':
78
78
  if (cursor === undefined) {
79
- return { row: 0, col: 0 };
79
+ return { row: 0, column: 0 };
80
80
  } else if (cursor.row < numRows - 1) {
81
- return { row: ev.metaKey ? numRows - 1 : cursor.row + 1, col: cursor.col };
81
+ return { row: ev.metaKey ? numRows - 1 : cursor.row + 1, column: cursor.column };
82
82
  }
83
83
  break;
84
84
  case 'ArrowLeft':
85
85
  if (cursor === undefined) {
86
- return { row: 0, col: 0 };
87
- } else if (cursor.col > 0) {
88
- return { row: cursor.row, col: ev.metaKey ? 0 : cursor.col - 1 };
86
+ return { row: 0, column: 0 };
87
+ } else if (cursor.column > 0) {
88
+ return { row: cursor.row, column: ev.metaKey ? 0 : cursor.column - 1 };
89
89
  }
90
90
  break;
91
91
  case 'ArrowRight':
92
92
  if (cursor === undefined) {
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 };
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 };
96
96
  }
97
97
  break;
98
98
  case 'Home':
99
- return { row: 0, col: 0 };
99
+ return { row: 0, column: 0 };
100
100
  case 'End':
101
- return { row: numRows - 1, col: numCols - 1 };
101
+ return { row: numRows - 1, column: numColumns - 1 };
102
102
  }
103
103
  };
104
104
 
@@ -2,16 +2,21 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import React, { type PropsWithChildren, createContext, useContext, useMemo, useState } from 'react';
5
+ import React, { type PropsWithChildren, createContext, useContext, useState, useEffect } from 'react';
6
6
 
7
7
  import { invariant } from '@dxos/invariant';
8
- import { type Space } from '@dxos/react-client/echo';
8
+ import { type FunctionType } from '@dxos/plugin-script';
9
+ import { fullyQualifiedId, type Space } from '@dxos/react-client/echo';
9
10
 
10
- import { createDecorations } from './decorations';
11
- import { type CellAddress, type CellRange } from '../../defs';
12
- import { useSheetModel, useFormattingModel } from '../../hooks';
13
- import { type FormattingModel, type SheetModel } from '../../model';
11
+ import { FormattingModel } from './formatting';
12
+ import { type CellAddress, type CellRange, defaultFunctions, SheetModel } from '../../model';
14
13
  import { type SheetType } from '../../types';
14
+ import { type FunctionContextOptions } from '../ComputeGraph';
15
+ // TODO(wittjosiah): Refactor. This is not exported from ./components due to depending on ECHO.
16
+ import { useComputeGraph } from '../ComputeGraph/graph-context';
17
+
18
+ // TODO(wittjosiah): Factor out.
19
+ const OBJECT_ID_LENGTH = 60; // 33 (space id) + 26 (object id) + 1 (separator).
15
20
 
16
21
  export type SheetContextType = {
17
22
  model: SheetModel;
@@ -31,9 +36,6 @@ export type SheetContextType = {
31
36
  // Events.
32
37
  // TODO(burdon): Generalize.
33
38
  onInfo?: () => void;
34
-
35
- // Decorations.
36
- decorations: ReturnType<typeof createDecorations>;
37
39
  };
38
40
 
39
41
  const SheetContext = createContext<SheetContextType | null>(null);
@@ -48,7 +50,49 @@ export type SheetContextProps = {
48
50
  sheet: SheetType;
49
51
  space: Space;
50
52
  readonly?: boolean;
51
- } & Pick<SheetContextType, 'onInfo'>;
53
+ } & Pick<SheetContextType, 'onInfo'> &
54
+ Partial<FunctionContextOptions>;
55
+
56
+ /**
57
+ * Map from binding to fully qualified ECHO ID.
58
+ */
59
+ const mapFormulaBindingToId =
60
+ (functions: FunctionType[]) =>
61
+ (formula: string): string => {
62
+ return formula.replace(/([a-zA-Z0-9]+)\((.*)\)/g, (match, binding, args) => {
63
+ if (defaultFunctions.find((fn) => fn.name === binding) || binding === 'EDGE') {
64
+ return match;
65
+ }
66
+
67
+ const fn = functions.find((fn) => fn.binding === binding);
68
+ if (fn) {
69
+ return `${fullyQualifiedId(fn)}(${args})`;
70
+ } else {
71
+ return match;
72
+ }
73
+ });
74
+ };
75
+
76
+ /**
77
+ * Map from fully qualified ECHO ID to binding.
78
+ */
79
+ const mapFormulaBindingFromId =
80
+ (functions: FunctionType[]) =>
81
+ (formula: string): string => {
82
+ return formula.replace(/([a-zA-Z0-9]+):([a-zA-Z0-9]+)\((.*)\)/g, (match, spaceId, objectId, args) => {
83
+ const id = `${spaceId}:${objectId}`;
84
+ if (id.length !== OBJECT_ID_LENGTH) {
85
+ return match;
86
+ }
87
+
88
+ const fn = functions.find((fn) => fullyQualifiedId(fn) === id);
89
+ if (fn?.binding) {
90
+ return `${fn.binding}(${args})`;
91
+ } else {
92
+ return match;
93
+ }
94
+ });
95
+ };
52
96
 
53
97
  export const SheetContextProvider = ({
54
98
  children,
@@ -56,17 +100,36 @@ export const SheetContextProvider = ({
56
100
  space,
57
101
  readonly,
58
102
  onInfo,
103
+ ...options
59
104
  }: PropsWithChildren<SheetContextProps>) => {
60
- const model = useSheetModel(space, sheet, { readonly });
61
- const formatting = useFormattingModel(model);
105
+ const graph = useComputeGraph(space, options);
62
106
 
63
- // TODO(Zan): Impl. set range and set cursor that scrolls to that cell or range if it is not visible.
64
107
  const [cursor, setCursor] = useState<CellAddress>();
65
108
  const [range, setRange] = useState<CellRange>();
66
109
  const [editing, setEditing] = useState<boolean>(false);
67
- const decorations = useMemo(() => createDecorations(), []);
68
110
 
69
- return !model || !formatting ? null : (
111
+ const [[model, formatting] = [], setModels] = useState<[SheetModel, FormattingModel] | undefined>(undefined);
112
+ useEffect(() => {
113
+ let model: SheetModel | undefined;
114
+ let formatting;
115
+ const t = setTimeout(async () => {
116
+ model = new SheetModel(graph, sheet, space, { readonly, mapFormulaBindingToId, mapFormulaBindingFromId });
117
+ await model.initialize();
118
+ formatting = new FormattingModel(model);
119
+ setModels([model, formatting]);
120
+ });
121
+
122
+ return () => {
123
+ clearTimeout(t);
124
+ void model?.destroy();
125
+ };
126
+ }, [graph, readonly]);
127
+
128
+ if (!model || !formatting) {
129
+ return null;
130
+ }
131
+
132
+ return (
70
133
  <SheetContext.Provider
71
134
  value={{
72
135
  model,
@@ -79,7 +142,6 @@ export const SheetContextProvider = ({
79
142
  setEditing,
80
143
  // TODO(burdon): Change to event.
81
144
  onInfo,
82
- decorations,
83
145
  }}
84
146
  >
85
147
  {children}
@@ -2,84 +2,30 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import React, { useCallback } from 'react';
5
+ import React from 'react';
6
6
 
7
- import { useIntentDispatcher } from '@dxos/app-framework';
8
- import { fullyQualifiedId } from '@dxos/react-client/echo';
9
- import { useIsDirectlyAttended } from '@dxos/react-ui-attention';
10
- import { focusRing, mx } from '@dxos/react-ui-theme';
7
+ import { type LayoutCoordinate } from '@dxos/app-framework';
8
+ import { mx } from '@dxos/react-ui-theme';
11
9
 
12
10
  import { Sheet, type SheetRootProps } from './Sheet';
13
- import { Toolbar, type ToolbarAction } from './Toolbar';
14
-
15
- // TODO(Zan): Factor out, copied this from MarkdownPlugin.
16
- const attentionFragment = mx(
17
- 'group-focus-within/editor:attention-surface group-[[aria-current]]/editor:attention-surface',
18
- 'group-focus-within/editor:border-separator',
19
- );
20
-
21
- // TODO(Zan): Factor out, copied this from MarkdownPlugin.
22
- export const sectionToolbarLayout =
23
- 'bs-[--rail-action] bg-[--sticky-bg] sticky block-start-0 __-block-start-px transition-opacity';
24
-
25
- const SheetContainer = ({ sheet, space, role }: SheetRootProps & { role?: string }) => {
26
- const dispatch = useIntentDispatcher();
27
-
28
- const id = fullyQualifiedId(sheet);
29
- const isDirectlyAttended = useIsDirectlyAttended(id);
30
-
31
- // TODO(Zan): Centralise the toolbar action handler. Current implementation in stories.
32
- const handleAction = useCallback(
33
- (action: ToolbarAction) => {
34
- switch (action.type) {
35
- case 'comment': {
36
- // TODO(Zan): We shouldn't hardcode the action ID.
37
- void dispatch({
38
- action: 'dxos.org/plugin/thread/action/create',
39
- data: {
40
- cursor: action.anchor,
41
- name: action.cellContent,
42
- subject: sheet,
43
- },
44
- });
45
- }
46
- }
47
- },
48
- [sheet, dispatch],
49
- );
50
11
 
12
+ const SheetContainer = ({
13
+ sheet,
14
+ space,
15
+ role,
16
+ remoteFunctionUrl,
17
+ }: SheetRootProps & { role?: string; coordinate?: LayoutCoordinate }) => {
51
18
  return (
52
- <div role='none' className={role === 'article' ? 'row-span-2 grid grid-rows-subgrid' : undefined}>
53
- <Sheet.Root space={space} sheet={sheet}>
54
- <div role='none' className={mx('flex flex-0 justify-center overflow-x-auto')}>
55
- <Toolbar.Root
56
- onAction={handleAction}
57
- classNames={mx(
58
- role === 'section'
59
- ? ['z-[2] group-focus-within/section:visible', !isDirectlyAttended && 'invisible', sectionToolbarLayout]
60
- : 'group-focus-within/editor:border-separator group-[[aria-current]]/editor:border-separator',
61
- )}
62
- >
63
- {/* TODO(Zan): Restore some of this functionality */}
64
- {/* <Toolbar.Styles /> */}
65
- {/* <Toolbar.Format /> */}
66
- {/* <Toolbar.Alignment /> */}
67
- <Toolbar.Separator />
68
- <Toolbar.Actions />
69
- </Toolbar.Root>
70
- </div>
71
- <div
72
- role='none'
73
- className={mx(
74
- role === 'section' && 'aspect-square border-is border-bs border-be border-separator',
75
- role === 'article' &&
76
- 'flex is-full overflow-hidden focus-visible:ring-inset row-span-1 data-[toolbar=disabled]:pbs-2 data-[toolbar=disabled]:row-span-2 border-bs border-separator',
77
- focusRing,
78
- attentionFragment,
79
- )}
80
- >
81
- <Sheet.Main />
82
- </div>
19
+ <div
20
+ role='none'
21
+ className={mx(
22
+ 'flex',
23
+ role === 'article' && 'row-span-2',
24
+ role === 'section' && 'aspect-square border-y border-is border-separator',
25
+ )}
26
+ >
27
+ <Sheet.Root sheet={sheet} space={space} remoteFunctionUrl={remoteFunctionUrl}>
28
+ <Sheet.Main />
83
29
  </Sheet.Root>
84
30
  </div>
85
31
  );