@dxos/plugin-sheet 0.6.12-main.f9d0246 → 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 (263) hide show
  1. package/dist/lib/browser/{chunk-ZLJ2GRE2.mjs → SheetContainer-U4H5D34A.mjs} +240 -1151
  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/browser/{chunk-Z2XOOC2R.mjs → chunk-D5AGLXJP.mjs} +678 -385
  6. package/dist/lib/browser/chunk-D5AGLXJP.mjs.map +7 -0
  7. package/dist/lib/browser/{chunk-WZMOZKQZ.mjs → chunk-FUAGSXA4.mjs} +16 -9
  8. package/dist/lib/browser/chunk-FUAGSXA4.mjs.map +7 -0
  9. package/dist/lib/{node-esm/chunk-IU2L277A.mjs → browser/chunk-JRL5LGCE.mjs} +5 -4
  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 +60 -74
  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-6DQABRGJ.cjs → SheetContainer-AXQV3ZT5.cjs} +279 -1182
  21. package/dist/lib/node/SheetContainer-AXQV3ZT5.cjs.map +7 -0
  22. package/dist/lib/node/{chunk-P5QYYEHQ.cjs → chunk-5KKJ4NPP.cjs} +676 -388
  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-AOP42UAA.cjs → chunk-DSYKOI4E.cjs} +21 -13
  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 +66 -86
  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 +2 -8
  49. package/dist/types/src/components/ComputeGraph/async-function.d.ts.map +1 -0
  50. package/dist/types/src/{graph/testing/custom-function.d.ts → components/ComputeGraph/custom.d.ts} +2 -4
  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 +7 -8
  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} +65 -10
  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 +5 -86
  101. package/dist/types/src/types.d.ts.map +1 -1
  102. package/package.json +41 -48
  103. package/src/SheetPlugin.tsx +73 -48
  104. package/src/components/CellEditor/CellEditor.stories.tsx +4 -5
  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 +6 -15
  109. package/src/{graph/testing/custom-function.ts → components/ComputeGraph/custom.ts} +7 -11
  110. package/src/{graph → components/ComputeGraph}/edge-function.ts +3 -3
  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 +88 -52
  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 +80 -18
  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 -24
  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 +6 -31
  134. package/dist/lib/browser/SheetContainer-VISF3VUB.mjs +0 -261
  135. package/dist/lib/browser/SheetContainer-VISF3VUB.mjs.map +0 -7
  136. package/dist/lib/browser/chunk-QILRZNE5.mjs +0 -15
  137. package/dist/lib/browser/chunk-QILRZNE5.mjs.map +0 -7
  138. package/dist/lib/browser/chunk-WZMOZKQZ.mjs.map +0 -7
  139. package/dist/lib/browser/chunk-Z2XOOC2R.mjs.map +0 -7
  140. package/dist/lib/browser/chunk-ZLJ2GRE2.mjs.map +0 -7
  141. package/dist/lib/browser/graph-4XFKIHRL.mjs +0 -21
  142. package/dist/lib/browser/graph-4XFKIHRL.mjs.map +0 -7
  143. package/dist/lib/node/SheetContainer-2MEALQWW.cjs +0 -279
  144. package/dist/lib/node/SheetContainer-2MEALQWW.cjs.map +0 -7
  145. package/dist/lib/node/chunk-6DQABRGJ.cjs.map +0 -7
  146. package/dist/lib/node/chunk-AOP42UAA.cjs.map +0 -7
  147. package/dist/lib/node/chunk-BNARJ5GM.cjs.map +0 -7
  148. package/dist/lib/node/chunk-P5QYYEHQ.cjs.map +0 -7
  149. package/dist/lib/node/graph-2LRDUXBZ.cjs +0 -43
  150. package/dist/lib/node/graph-2LRDUXBZ.cjs.map +0 -7
  151. package/dist/lib/node-esm/SheetContainer-RPSUSXWS.mjs +0 -262
  152. package/dist/lib/node-esm/SheetContainer-RPSUSXWS.mjs.map +0 -7
  153. package/dist/lib/node-esm/chunk-4MM7THJW.mjs +0 -2944
  154. package/dist/lib/node-esm/chunk-4MM7THJW.mjs.map +0 -7
  155. package/dist/lib/node-esm/chunk-5RLTCIE2.mjs +0 -2684
  156. package/dist/lib/node-esm/chunk-5RLTCIE2.mjs.map +0 -7
  157. package/dist/lib/node-esm/chunk-IU2L277A.mjs.map +0 -7
  158. package/dist/lib/node-esm/chunk-RR2AO4SM.mjs +0 -76
  159. package/dist/lib/node-esm/chunk-RR2AO4SM.mjs.map +0 -7
  160. package/dist/lib/node-esm/graph-WG5EKOMO.mjs +0 -22
  161. package/dist/lib/node-esm/graph-WG5EKOMO.mjs.map +0 -7
  162. package/dist/lib/node-esm/index.mjs +0 -263
  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 -9
  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.d.ts +0 -84
  195. package/dist/types/src/graph/compute-graph.d.ts.map +0 -1
  196. package/dist/types/src/graph/compute-graph.stories.d.ts +0 -10
  197. package/dist/types/src/graph/compute-graph.stories.d.ts.map +0 -1
  198. package/dist/types/src/graph/compute-graph.test.d.ts +0 -2
  199. package/dist/types/src/graph/compute-graph.test.d.ts.map +0 -1
  200. package/dist/types/src/graph/compute-node.d.ts +0 -26
  201. package/dist/types/src/graph/compute-node.d.ts.map +0 -1
  202. package/dist/types/src/graph/edge-function.d.ts.map +0 -1
  203. package/dist/types/src/graph/function-defs.d.ts.map +0 -1
  204. package/dist/types/src/graph/hyperformula.test.d.ts +0 -2
  205. package/dist/types/src/graph/hyperformula.test.d.ts.map +0 -1
  206. package/dist/types/src/graph/index.d.ts +0 -4
  207. package/dist/types/src/graph/index.d.ts.map +0 -1
  208. package/dist/types/src/graph/testing/custom-function.d.ts.map +0 -1
  209. package/dist/types/src/graph/testing/index.d.ts +0 -2
  210. package/dist/types/src/graph/testing/index.d.ts.map +0 -1
  211. package/dist/types/src/graph/util.d.ts +0 -2
  212. package/dist/types/src/graph/util.d.ts.map +0 -1
  213. package/dist/types/src/hooks/hooks.stories.d.ts +0 -11
  214. package/dist/types/src/hooks/hooks.stories.d.ts.map +0 -1
  215. package/dist/types/src/hooks/index.d.ts +0 -4
  216. package/dist/types/src/hooks/index.d.ts.map +0 -1
  217. package/dist/types/src/hooks/useComputeGraph.d.ts +0 -7
  218. package/dist/types/src/hooks/useComputeGraph.d.ts.map +0 -1
  219. package/dist/types/src/hooks/useFormattingModel.d.ts +0 -3
  220. package/dist/types/src/hooks/useFormattingModel.d.ts.map +0 -1
  221. package/dist/types/src/hooks/useSheetModel.d.ts +0 -8
  222. package/dist/types/src/hooks/useSheetModel.d.ts.map +0 -1
  223. package/dist/types/src/model/formatting-model.d.ts +0 -16
  224. package/dist/types/src/model/formatting-model.d.ts.map +0 -1
  225. package/dist/types/src/model/sheet-model.d.ts.map +0 -1
  226. package/dist/types/src/sanity.test.d.ts +0 -2
  227. package/dist/types/src/sanity.test.d.ts.map +0 -1
  228. package/dist/types/src/testing/index.d.ts +0 -2
  229. package/dist/types/src/testing/index.d.ts.map +0 -1
  230. package/dist/types/src/testing/testing.d.ts +0 -8
  231. package/dist/types/src/testing/testing.d.ts.map +0 -1
  232. package/dist/vendor/hyperformula.mjs +0 -37145
  233. package/src/components/ComputeGraph/ComputeGraphContextProvider.tsx +0 -20
  234. package/src/components/GridSheet/GridSheet.stories.tsx +0 -36
  235. package/src/components/GridSheet/GridSheet.tsx +0 -153
  236. package/src/components/GridSheet/util.ts +0 -108
  237. package/src/components/Sheet/decorations.ts +0 -62
  238. package/src/components/Sheet/threads.tsx +0 -205
  239. package/src/defs/index.ts +0 -6
  240. package/src/defs/util.ts +0 -151
  241. package/src/extensions/compute.stories.tsx +0 -153
  242. package/src/extensions/compute.ts +0 -131
  243. package/src/extensions/index.ts +0 -5
  244. package/src/graph/compute-graph.stories.tsx +0 -93
  245. package/src/graph/compute-graph.test.ts +0 -127
  246. package/src/graph/compute-graph.ts +0 -313
  247. package/src/graph/compute-node.ts +0 -62
  248. package/src/graph/hyperformula.test.ts +0 -15
  249. package/src/graph/index.ts +0 -7
  250. package/src/graph/testing/index.ts +0 -5
  251. package/src/graph/util.ts +0 -8
  252. package/src/hooks/hooks.stories.tsx +0 -50
  253. package/src/hooks/index.ts +0 -7
  254. package/src/hooks/useComputeGraph.ts +0 -21
  255. package/src/hooks/useFormattingModel.ts +0 -11
  256. package/src/hooks/useSheetModel.ts +0 -40
  257. package/src/model/sheet-model.ts +0 -414
  258. package/src/sanity.test.ts +0 -40
  259. package/src/testing/index.ts +0 -5
  260. package/src/testing/testing.tsx +0 -68
  261. /package/dist/types/src/{graph → components/ComputeGraph}/edge-function.d.ts +0 -0
  262. /package/dist/types/src/{defs → model}/types.test.d.ts +0 -0
  263. /package/src/{graph/function-defs.ts → model/functions.ts} +0 -0
@@ -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 FunctionType } from '@dxos/plugin-script';
9
+ import { fullyQualifiedId, type Space } from '@dxos/react-client/echo';
8
10
 
9
- import { createDecorations } from './decorations';
10
- import { type CellAddress, type CellRange } from '../../defs';
11
- import { type ComputeGraph } from '../../graph';
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);
@@ -45,28 +47,89 @@ export const useSheetContext = (): SheetContextType => {
45
47
  };
46
48
 
47
49
  export type SheetContextProps = {
48
- graph: ComputeGraph;
49
50
  sheet: SheetType;
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,
55
- graph,
56
99
  sheet,
100
+ space,
57
101
  readonly,
58
102
  onInfo,
103
+ ...options
59
104
  }: PropsWithChildren<SheetContextProps>) => {
60
- const model = useSheetModel(graph, 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 = ({ graph, sheet, 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 graph={graph} 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
  );
@@ -23,31 +23,22 @@ import {
23
23
  type ThemedClassName,
24
24
  useTranslation,
25
25
  } from '@dxos/react-ui';
26
- import { nonNullable } from '@dxos/util';
27
26
 
28
27
  import { ToolbarButton, ToolbarSeparator, ToolbarToggleButton } from './common';
29
- import { addressToIndex } from '../../defs';
30
28
  import { SHEET_PLUGIN } from '../../meta';
31
29
  import { type Formatting } from '../../types';
32
- import { useSheetContext } from '../Sheet/sheet-context';
33
30
 
34
31
  //
35
32
  // Root
36
33
  //
37
34
 
38
- export type ToolbarAction =
39
- | { type: 'clear' }
40
- | { type: 'highlight' }
41
- | { type: 'left' }
42
- | { type: 'center' }
43
- | { type: 'right' }
44
- | { type: 'date' }
45
- | { type: 'currency' }
46
- | { type: 'comment'; anchor: string; cellContent?: string };
35
+ export type ToolbarActionType = 'clear' | 'highlight' | 'left' | 'center' | 'right' | 'date' | 'currency';
47
36
 
48
- export type ToolbarActionType = ToolbarAction['type'];
37
+ export type ToolbarAction = {
38
+ type: ToolbarActionType;
39
+ };
49
40
 
50
- export type ToolbarActionHandler = (action: ToolbarAction) => void;
41
+ export type ToolbarActionHandler = ({ type }: ToolbarAction) => void;
51
42
 
52
43
  export type ToolbarProps = ThemedClassName<
53
44
  PropsWithChildren<{
@@ -105,7 +96,7 @@ const Format = () => {
105
96
  Icon={Icon}
106
97
  // disabled={state?.blockType === 'codeblock'}
107
98
  // onClick={state ? () => onAction?.({ type, data: !getState(state) }) : undefined}
108
- onClick={() => onAction?.({ type: type as Exclude<typeof type, 'comment'> })}
99
+ onClick={() => onAction?.({ type })}
109
100
  >
110
101
  {t(`toolbar ${type} label`)}
111
102
  </ToolbarToggleButton>
@@ -136,7 +127,7 @@ const Alignment = () => {
136
127
  Icon={Icon}
137
128
  // disabled={state?.blockType === 'codeblock'}
138
129
  // onClick={state ? () => onAction?.({ type, data: !getState(state) }) : undefined}
139
- onClick={() => onAction?.({ type: type as Exclude<typeof type, 'comment'> })}
130
+ onClick={() => onAction?.({ type })}
140
131
  >
141
132
  {t(`toolbar ${type} label`)}
142
133
  </ToolbarToggleButton>
@@ -166,7 +157,7 @@ const Styles = () => {
166
157
  Icon={Icon}
167
158
  // disabled={state?.blockType === 'codeblock'}
168
159
  // onClick={state ? () => onAction?.({ type, data: !getState(state) }) : undefined}
169
- onClick={() => onAction?.({ type: type as Exclude<typeof type, 'comment'> })}
160
+ onClick={() => onAction?.({ type })}
170
161
  >
171
162
  {t(`toolbar ${type} label`)}
172
163
  </ToolbarToggleButton>
@@ -180,49 +171,17 @@ const Styles = () => {
180
171
  //
181
172
 
182
173
  const Actions = () => {
183
- const { onAction } = useToolbarContext('Actions');
184
- const { cursor, range, model } = useSheetContext();
174
+ // const { onAction } = useToolbarContext('Actions');
185
175
  const { t } = useTranslation(SHEET_PLUGIN);
186
-
187
- const overlapsCommentAnchor = (model.sheet.threads ?? [])
188
- .filter(nonNullable)
189
- .filter((thread) => thread.status !== 'resolved')
190
- .some((thread) => {
191
- if (!cursor) {
192
- return false;
193
- }
194
- return addressToIndex(model.sheet, cursor) === thread.anchor;
195
- });
196
-
197
- const hasCursor = !!cursor;
198
- const cursorOnly = hasCursor && !range && !overlapsCommentAnchor;
199
-
200
- const tooltipLabelKey = !hasCursor
201
- ? 'no cursor label'
202
- : overlapsCommentAnchor
203
- ? 'selection overlaps existing comment label'
204
- : range
205
- ? 'comment ranges not supported label'
206
- : 'comment label';
207
-
208
176
  return (
209
177
  <ToolbarButton
210
178
  value='comment'
211
179
  Icon={ChatText}
212
180
  data-testid='editor.toolbar.comment'
213
- onClick={() => {
214
- if (!cursor) {
215
- return;
216
- }
217
- return onAction?.({
218
- type: 'comment',
219
- anchor: addressToIndex(model.sheet, cursor),
220
- cellContent: model.getCellText(cursor),
221
- });
222
- }}
223
- disabled={!cursorOnly || overlapsCommentAnchor}
181
+ // onClick={() => onAction?.({ type: 'comment' })}
182
+ // disabled={!state || state.comment || !state.selection}
224
183
  >
225
- {t(tooltipLabelKey)}
184
+ {t('comment label')}
226
185
  </ToolbarButton>
227
186
  );
228
187
  };
@@ -5,7 +5,6 @@
5
5
  import React from 'react';
6
6
 
7
7
  export * from './ComputeGraph';
8
- export * from './Sheet';
9
8
 
10
9
  // Lazily load components for content surfaces.
11
10
  export const SheetContainer = React.lazy(() => import('./SheetContainer'));
package/src/meta.tsx CHANGED
@@ -2,6 +2,9 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ import { GridNine, type IconProps } from '@phosphor-icons/react';
6
+ import React from 'react';
7
+
5
8
  import { pluginMeta } from '@dxos/app-framework';
6
9
 
7
10
  export const SHEET_PLUGIN = 'dxos.org/plugin/sheet';
@@ -10,5 +13,6 @@ export default pluginMeta({
10
13
  id: SHEET_PLUGIN,
11
14
  name: 'Sheet',
12
15
  description: 'A simple spreadsheet plugin.',
13
- icon: 'ph--grid-nine--regular',
16
+ iconComponent: (props: IconProps) => <GridNine {...props} />,
17
+ iconSymbol: 'ph--grid-nine--regular',
14
18
  });
@@ -2,5 +2,6 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- export * from './formatting-model';
6
- export * from './sheet-model';
5
+ export * from './functions';
6
+ export * from './model';
7
+ export * from './types';
@@ -0,0 +1,100 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { expect } from 'chai';
6
+ import { describe, test } from 'vitest';
7
+
8
+ import { SheetModel } from './model';
9
+ import { addressFromA1Notation, rangeFromA1Notation } from './types';
10
+ import { createComputeGraph } from '../components';
11
+ import { createSheet, ValueTypeEnum } from '../types';
12
+
13
+ // TODO(burdon): Test undo (e.g., clear cells).
14
+
15
+ /**
16
+ * VITEST_ENV=chrome p vitest --watch
17
+ * NOTE: Browser test required for hyperformula due to raw translation files.
18
+ */
19
+ describe('model', () => {
20
+ const createModel = async () => {
21
+ const graph = createComputeGraph();
22
+ const sheet = createSheet();
23
+ const model = new SheetModel(graph, sheet, undefined, { rows: 5, columns: 5 });
24
+ await model.initialize();
25
+ return model;
26
+ };
27
+
28
+ test('create', async () => {
29
+ const model = await createModel();
30
+ expect(model.bounds).to.deep.eq({ rows: 5, columns: 5 });
31
+ model.setValue(addressFromA1Notation('A1'), 100);
32
+ const value = model.getValue(addressFromA1Notation('A1'));
33
+ expect(value).to.eq(100);
34
+ });
35
+
36
+ test('map formula', async () => {
37
+ const model = await createModel();
38
+ const x1 = model.mapFormulaRefsToIndices('=SUM(A1:A3)');
39
+ const x2 = model.mapFormulaIndicesToRefs(x1);
40
+ expect(x2).to.eq('=SUM(A1:A3)');
41
+ });
42
+
43
+ test('dates', async () => {
44
+ const model = await createModel();
45
+ const cell = addressFromA1Notation('A1');
46
+ model.setValue(cell, '=NOW()');
47
+ const type = model.getValueType(cell);
48
+ expect(type).to.eq(ValueTypeEnum.DateTime);
49
+ const value = model.getValue(cell);
50
+ const date = model.toLocalDate(value as number);
51
+ const now = new Date();
52
+ expect(date.getUTCFullYear()).to.eq(now.getUTCFullYear());
53
+ expect(date.getUTCMonth()).to.eq(now.getUTCMonth());
54
+ expect(date.getUTCDate()).to.eq(now.getUTCDate());
55
+ });
56
+
57
+ test('formula', async () => {
58
+ const model = await createModel();
59
+
60
+ // Nested formula.
61
+ {
62
+ model.setValue(addressFromA1Notation('A1'), 100);
63
+ model.setValue(addressFromA1Notation('A2'), 200);
64
+ model.setValue(addressFromA1Notation('A3'), '=SUM(A1:A2)');
65
+ model.setValue(addressFromA1Notation('A4'), '=SUM(A1:A3)');
66
+ const value = model.getValue(addressFromA1Notation('A4'));
67
+ expect(value).to.eq(600);
68
+ // console.log(JSON.stringify(model.sheet.cells, undefined, 2));
69
+
70
+ const cells = model.getCellValues(rangeFromA1Notation('A1:A4'));
71
+ expect(cells).to.deep.eq([
72
+ [100],
73
+ [200],
74
+ [model.mapFormulaRefsToIndices('=SUM(A1:A2)')],
75
+ [model.mapFormulaRefsToIndices('=SUM(A1:A3)')],
76
+ ]);
77
+ // console.log(JSON.stringify(model.sheet.cells, undefined, 2));
78
+ // console.log(cells);
79
+ }
80
+
81
+ // Insert row.
82
+ {
83
+ model.insertRows(2, 1);
84
+ model.setValue(addressFromA1Notation('A3'), 400);
85
+ const value = model.getValue(addressFromA1Notation('A5'));
86
+ expect(value).to.eq(1000);
87
+
88
+ const cells = model.getCellValues(rangeFromA1Notation('A1:A5'));
89
+ expect(cells).to.deep.eq([
90
+ [100],
91
+ [200],
92
+ [400],
93
+ [model.mapFormulaRefsToIndices('=SUM(A1:A2)')],
94
+ [model.mapFormulaRefsToIndices('=SUM(A1:A4)')],
95
+ ]);
96
+ // console.log(JSON.stringify(model.sheet.cells, undefined, 2));
97
+ // console.log(cells);
98
+ }
99
+ });
100
+ });