@dxos/plugin-sheet 0.8.4-main.7ace549 → 0.8.4-main.937b3ca

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 (199) hide show
  1. package/dist/lib/browser/SheetContainer-ESCXPI7Y.mjs +397 -0
  2. package/dist/lib/browser/SheetContainer-ESCXPI7Y.mjs.map +7 -0
  3. package/dist/lib/browser/{anchor-sort-OWOAGQM6.mjs → anchor-sort-JBRMW6OY.mjs} +7 -7
  4. package/dist/lib/browser/anchor-sort-JBRMW6OY.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-2SAGT3BB.mjs +397 -0
  6. package/dist/lib/browser/chunk-2SAGT3BB.mjs.map +7 -0
  7. package/dist/lib/browser/{chunk-7VEWYJJN.mjs → chunk-IFLWVS2V.mjs} +5 -5
  8. package/dist/lib/browser/chunk-IFLWVS2V.mjs.map +7 -0
  9. package/dist/lib/browser/chunk-W6N44ONZ.mjs +1470 -0
  10. package/dist/lib/browser/chunk-W6N44ONZ.mjs.map +7 -0
  11. package/dist/lib/browser/compute-graph-registry-DL2PX7TF.mjs +21 -0
  12. package/dist/lib/browser/compute-graph-registry-DL2PX7TF.mjs.map +7 -0
  13. package/dist/lib/browser/index.mjs +66 -76
  14. package/dist/lib/browser/index.mjs.map +4 -4
  15. package/dist/lib/browser/markdown-BC4KBDUO.mjs +29 -0
  16. package/dist/lib/browser/markdown-BC4KBDUO.mjs.map +7 -0
  17. package/dist/lib/browser/meta.json +1 -1
  18. package/dist/lib/browser/operation-resolver-FJ4UWZUM.mjs +79 -0
  19. package/dist/lib/browser/operation-resolver-FJ4UWZUM.mjs.map +7 -0
  20. package/dist/lib/browser/{react-surface-VPLFBQSV.mjs → react-surface-5BXM6TJ3.mjs} +16 -19
  21. package/dist/lib/browser/react-surface-5BXM6TJ3.mjs.map +7 -0
  22. package/dist/lib/browser/types/index.mjs +5 -2
  23. package/dist/lib/node-esm/SheetContainer-YVIDJKP4.mjs +398 -0
  24. package/dist/lib/node-esm/SheetContainer-YVIDJKP4.mjs.map +7 -0
  25. package/dist/lib/node-esm/{anchor-sort-FG3DS4HM.mjs → anchor-sort-C3XFPI6S.mjs} +7 -7
  26. package/dist/lib/node-esm/anchor-sort-C3XFPI6S.mjs.map +7 -0
  27. package/dist/lib/node-esm/chunk-IMWGSIDG.mjs +398 -0
  28. package/dist/lib/node-esm/chunk-IMWGSIDG.mjs.map +7 -0
  29. package/dist/lib/node-esm/{chunk-4QV4AGWK.mjs → chunk-PPOYR7DK.mjs} +5 -5
  30. package/dist/lib/node-esm/chunk-PPOYR7DK.mjs.map +7 -0
  31. package/dist/lib/node-esm/chunk-S7RYX7DG.mjs +1471 -0
  32. package/dist/lib/node-esm/chunk-S7RYX7DG.mjs.map +7 -0
  33. package/dist/lib/node-esm/compute-graph-registry-VXH55GDI.mjs +22 -0
  34. package/dist/lib/node-esm/compute-graph-registry-VXH55GDI.mjs.map +7 -0
  35. package/dist/lib/node-esm/index.mjs +66 -76
  36. package/dist/lib/node-esm/index.mjs.map +4 -4
  37. package/dist/lib/node-esm/markdown-6DGZCJRM.mjs +30 -0
  38. package/dist/lib/node-esm/markdown-6DGZCJRM.mjs.map +7 -0
  39. package/dist/lib/node-esm/meta.json +1 -1
  40. package/dist/lib/node-esm/operation-resolver-OGXEUWHA.mjs +80 -0
  41. package/dist/lib/node-esm/operation-resolver-OGXEUWHA.mjs.map +7 -0
  42. package/dist/lib/node-esm/{react-surface-YLTZQVNL.mjs → react-surface-RLHC6B77.mjs} +16 -19
  43. package/dist/lib/node-esm/react-surface-RLHC6B77.mjs.map +7 -0
  44. package/dist/lib/node-esm/types/index.mjs +5 -2
  45. package/dist/types/src/SheetPlugin.d.ts +2 -1
  46. package/dist/types/src/SheetPlugin.d.ts.map +1 -1
  47. package/dist/types/src/capabilities/anchor-sort/anchor-sort.d.ts +5 -0
  48. package/dist/types/src/capabilities/anchor-sort/anchor-sort.d.ts.map +1 -0
  49. package/dist/types/src/capabilities/anchor-sort/index.d.ts +3 -0
  50. package/dist/types/src/capabilities/anchor-sort/index.d.ts.map +1 -0
  51. package/dist/types/src/capabilities/compute-graph-registry/compute-graph-registry.d.ts +5 -0
  52. package/dist/types/src/capabilities/compute-graph-registry/compute-graph-registry.d.ts.map +1 -0
  53. package/dist/types/src/capabilities/compute-graph-registry/index.d.ts +3 -0
  54. package/dist/types/src/capabilities/compute-graph-registry/index.d.ts.map +1 -0
  55. package/dist/types/src/capabilities/index.d.ts +5 -6
  56. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  57. package/dist/types/src/capabilities/markdown/index.d.ts +3 -0
  58. package/dist/types/src/capabilities/markdown/index.d.ts.map +1 -0
  59. package/dist/types/src/capabilities/markdown/markdown.d.ts +5 -0
  60. package/dist/types/src/capabilities/markdown/markdown.d.ts.map +1 -0
  61. package/dist/types/src/capabilities/operation-resolver/index.d.ts +3 -0
  62. package/dist/types/src/capabilities/operation-resolver/index.d.ts.map +1 -0
  63. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts +5 -0
  64. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts.map +1 -0
  65. package/dist/types/src/capabilities/react-surface/index.d.ts +3 -0
  66. package/dist/types/src/capabilities/react-surface/index.d.ts.map +1 -0
  67. package/dist/types/src/capabilities/react-surface/react-surface.d.ts +5 -0
  68. package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +1 -0
  69. package/dist/types/src/components/GridSheet/GridSheet.d.ts.map +1 -1
  70. package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts.map +1 -1
  71. package/dist/types/src/components/GridSheet/SheetCellEditor.stories.d.ts +1 -1
  72. package/dist/types/src/components/GridSheet/SheetCellEditor.stories.d.ts.map +1 -1
  73. package/dist/types/src/components/RangeList/RangeList.d.ts.map +1 -1
  74. package/dist/types/src/components/SheetContainer/SheetContainer.d.ts +4 -5
  75. package/dist/types/src/components/SheetContainer/SheetContainer.d.ts.map +1 -1
  76. package/dist/types/src/components/SheetContainer/SheetContainer.stories.d.ts +2 -1
  77. package/dist/types/src/components/SheetContainer/SheetContainer.stories.d.ts.map +1 -1
  78. package/dist/types/src/components/SheetToolbar/SheetToolbar.d.ts.map +1 -1
  79. package/dist/types/src/components/SheetToolbar/align.d.ts +12 -19
  80. package/dist/types/src/components/SheetToolbar/align.d.ts.map +1 -1
  81. package/dist/types/src/components/SheetToolbar/style.d.ts +12 -18
  82. package/dist/types/src/components/SheetToolbar/style.d.ts.map +1 -1
  83. package/dist/types/src/components/SheetToolbar/useToolbarState.d.ts +14 -1
  84. package/dist/types/src/components/SheetToolbar/useToolbarState.d.ts.map +1 -1
  85. package/dist/types/src/components/index.d.ts +1 -1
  86. package/dist/types/src/components/index.d.ts.map +1 -1
  87. package/dist/types/src/extensions/compute.stories.d.ts.map +1 -1
  88. package/dist/types/src/extensions/editor/sheet-extension.d.ts.map +1 -1
  89. package/dist/types/src/index.d.ts +1 -1
  90. package/dist/types/src/index.d.ts.map +1 -1
  91. package/dist/types/src/integrations/thread-ranges.d.ts.map +1 -1
  92. package/dist/types/src/meta.d.ts +2 -2
  93. package/dist/types/src/meta.d.ts.map +1 -1
  94. package/dist/types/src/model/sheet-model.d.ts.map +1 -1
  95. package/dist/types/src/testing/testing.d.ts +7 -7
  96. package/dist/types/src/types/Sheet.d.ts +32 -26
  97. package/dist/types/src/types/Sheet.d.ts.map +1 -1
  98. package/dist/types/src/types/capabilities.d.ts +6 -0
  99. package/dist/types/src/types/capabilities.d.ts.map +1 -0
  100. package/dist/types/src/types/index.d.ts +1 -0
  101. package/dist/types/src/types/index.d.ts.map +1 -1
  102. package/dist/types/src/types/types.d.ts +91 -65
  103. package/dist/types/src/types/types.d.ts.map +1 -1
  104. package/dist/types/tsconfig.tsbuildinfo +1 -1
  105. package/package.json +75 -70
  106. package/src/SheetPlugin.tsx +42 -58
  107. package/src/capabilities/anchor-sort/anchor-sort.ts +26 -0
  108. package/src/capabilities/anchor-sort/index.ts +7 -0
  109. package/src/capabilities/compute-graph-registry/compute-graph-registry.ts +27 -0
  110. package/src/capabilities/compute-graph-registry/index.ts +7 -0
  111. package/src/capabilities/index.ts +5 -9
  112. package/src/capabilities/markdown/index.ts +7 -0
  113. package/src/capabilities/markdown/markdown.ts +30 -0
  114. package/src/capabilities/operation-resolver/index.ts +7 -0
  115. package/src/capabilities/operation-resolver/operation-resolver.ts +77 -0
  116. package/src/capabilities/react-surface/index.ts +7 -0
  117. package/src/capabilities/react-surface/react-surface.tsx +43 -0
  118. package/src/components/ComputeGraph/compute-graph.stories.tsx +1 -1
  119. package/src/components/GridSheet/GridSheet.stories.tsx +2 -2
  120. package/src/components/GridSheet/GridSheet.tsx +14 -19
  121. package/src/components/GridSheet/SheetCellEditor.stories.tsx +6 -3
  122. package/src/components/GridSheet/util.ts +1 -1
  123. package/src/components/RangeList/RangeList.tsx +5 -2
  124. package/src/components/SheetContainer/SheetContainer.stories.tsx +41 -21
  125. package/src/components/SheetContainer/SheetContainer.tsx +27 -20
  126. package/src/components/SheetContext/SheetContext.tsx +4 -4
  127. package/src/components/SheetToolbar/SheetToolbar.tsx +29 -18
  128. package/src/components/SheetToolbar/align.ts +41 -16
  129. package/src/components/SheetToolbar/style.ts +45 -15
  130. package/src/components/SheetToolbar/useToolbarState.ts +22 -5
  131. package/src/extensions/compute.stories.tsx +15 -6
  132. package/src/extensions/compute.ts +1 -1
  133. package/src/extensions/editor/sheet-extension.ts +7 -4
  134. package/src/index.ts +1 -1
  135. package/src/integrations/thread-ranges.ts +36 -40
  136. package/src/meta.ts +2 -2
  137. package/src/model/sheet-model.ts +67 -37
  138. package/src/playwright/playwright.config.ts +1 -1
  139. package/src/playwright/sheet.spec.ts +1 -0
  140. package/src/sanity.test.ts +1 -1
  141. package/src/types/Sheet.ts +16 -13
  142. package/src/{capabilities → types}/capabilities.ts +2 -2
  143. package/src/types/index.ts +1 -0
  144. package/src/types/types.ts +81 -37
  145. package/dist/lib/browser/SheetContainer-WDKJPYCB.mjs +0 -349
  146. package/dist/lib/browser/SheetContainer-WDKJPYCB.mjs.map +0 -7
  147. package/dist/lib/browser/anchor-sort-OWOAGQM6.mjs.map +0 -7
  148. package/dist/lib/browser/chunk-6ILNTWSF.mjs +0 -852
  149. package/dist/lib/browser/chunk-6ILNTWSF.mjs.map +0 -7
  150. package/dist/lib/browser/chunk-73AV3NH6.mjs +0 -15
  151. package/dist/lib/browser/chunk-73AV3NH6.mjs.map +0 -7
  152. package/dist/lib/browser/chunk-7VEWYJJN.mjs.map +0 -7
  153. package/dist/lib/browser/chunk-FWFAAGXL.mjs +0 -28
  154. package/dist/lib/browser/chunk-FWFAAGXL.mjs.map +0 -7
  155. package/dist/lib/browser/chunk-GBK6OLCY.mjs +0 -907
  156. package/dist/lib/browser/chunk-GBK6OLCY.mjs.map +0 -7
  157. package/dist/lib/browser/compute-graph-registry-AP5RA7W3.mjs +0 -21
  158. package/dist/lib/browser/compute-graph-registry-AP5RA7W3.mjs.map +0 -7
  159. package/dist/lib/browser/intent-resolver-OMHQGXFL.mjs +0 -56
  160. package/dist/lib/browser/intent-resolver-OMHQGXFL.mjs.map +0 -7
  161. package/dist/lib/browser/markdown-B6VKYY2S.mjs +0 -26
  162. package/dist/lib/browser/markdown-B6VKYY2S.mjs.map +0 -7
  163. package/dist/lib/browser/react-surface-VPLFBQSV.mjs.map +0 -7
  164. package/dist/lib/node-esm/SheetContainer-62MZAU6Q.mjs +0 -350
  165. package/dist/lib/node-esm/SheetContainer-62MZAU6Q.mjs.map +0 -7
  166. package/dist/lib/node-esm/anchor-sort-FG3DS4HM.mjs.map +0 -7
  167. package/dist/lib/node-esm/chunk-44YTKTMP.mjs +0 -16
  168. package/dist/lib/node-esm/chunk-44YTKTMP.mjs.map +0 -7
  169. package/dist/lib/node-esm/chunk-4QV4AGWK.mjs.map +0 -7
  170. package/dist/lib/node-esm/chunk-HILDMVPL.mjs +0 -29
  171. package/dist/lib/node-esm/chunk-HILDMVPL.mjs.map +0 -7
  172. package/dist/lib/node-esm/chunk-KSHCRK5J.mjs +0 -908
  173. package/dist/lib/node-esm/chunk-KSHCRK5J.mjs.map +0 -7
  174. package/dist/lib/node-esm/chunk-QI3PNRCD.mjs +0 -853
  175. package/dist/lib/node-esm/chunk-QI3PNRCD.mjs.map +0 -7
  176. package/dist/lib/node-esm/compute-graph-registry-UMQ5UYCL.mjs +0 -22
  177. package/dist/lib/node-esm/compute-graph-registry-UMQ5UYCL.mjs.map +0 -7
  178. package/dist/lib/node-esm/intent-resolver-DHEHYV3B.mjs +0 -57
  179. package/dist/lib/node-esm/intent-resolver-DHEHYV3B.mjs.map +0 -7
  180. package/dist/lib/node-esm/markdown-VKY7HXU2.mjs +0 -27
  181. package/dist/lib/node-esm/markdown-VKY7HXU2.mjs.map +0 -7
  182. package/dist/lib/node-esm/react-surface-YLTZQVNL.mjs.map +0 -7
  183. package/dist/types/src/capabilities/anchor-sort.d.ts +0 -4
  184. package/dist/types/src/capabilities/anchor-sort.d.ts.map +0 -1
  185. package/dist/types/src/capabilities/capabilities.d.ts +0 -5
  186. package/dist/types/src/capabilities/capabilities.d.ts.map +0 -1
  187. package/dist/types/src/capabilities/compute-graph-registry.d.ts +0 -4
  188. package/dist/types/src/capabilities/compute-graph-registry.d.ts.map +0 -1
  189. package/dist/types/src/capabilities/intent-resolver.d.ts +0 -4
  190. package/dist/types/src/capabilities/intent-resolver.d.ts.map +0 -1
  191. package/dist/types/src/capabilities/markdown.d.ts +0 -4
  192. package/dist/types/src/capabilities/markdown.d.ts.map +0 -1
  193. package/dist/types/src/capabilities/react-surface.d.ts +0 -4
  194. package/dist/types/src/capabilities/react-surface.d.ts.map +0 -1
  195. package/src/capabilities/anchor-sort.ts +0 -21
  196. package/src/capabilities/compute-graph-registry.ts +0 -23
  197. package/src/capabilities/intent-resolver.ts +0 -38
  198. package/src/capabilities/markdown.ts +0 -23
  199. package/src/capabilities/react-surface.tsx +0 -41
@@ -2,15 +2,32 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { useMemo } from 'react';
6
-
7
- import { live } from '@dxos/live-object';
5
+ import { Atom, type Registry, RegistryContext, useAtomValue } from '@effect-atom/atom-react';
6
+ import { useContext, useMemo } from 'react';
8
7
 
9
8
  import { type AlignState } from './align';
10
9
  import { type StyleState } from './style';
11
10
 
12
11
  export type ToolbarState = Partial<StyleState & AlignState>;
12
+ export type ToolbarStateAtom = Atom.Writable<ToolbarState>;
13
+
14
+ /**
15
+ * Creates a reactive toolbar state Atom.
16
+ */
17
+ export const useToolbarState = (initialState: ToolbarState = {}): ToolbarStateAtom => {
18
+ return useMemo(() => Atom.make<ToolbarState>(initialState).pipe(Atom.keepAlive), []);
19
+ };
20
+
21
+ /**
22
+ * Hook to read the current toolbar state value.
23
+ */
24
+ export const useToolbarStateValue = (stateAtom: ToolbarStateAtom): ToolbarState => {
25
+ return useAtomValue(stateAtom);
26
+ };
13
27
 
14
- export const useToolbarState = (initialState: ToolbarState = {}) => {
15
- return useMemo(() => live<ToolbarState>(initialState), []);
28
+ /**
29
+ * Hook to get the registry for updating toolbar state.
30
+ */
31
+ export const useToolbarStateRegistry = (): Registry.Registry => {
32
+ return useContext(RegistryContext);
16
33
  };
@@ -5,21 +5,21 @@
5
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
6
6
  import React, { useEffect, useMemo } from 'react';
7
7
 
8
- import { IntentPlugin } from '@dxos/app-framework';
8
+ import { OperationPlugin, RuntimePlugin } from '@dxos/app-framework';
9
9
  import { withPluginManager } from '@dxos/app-framework/testing';
10
10
  import { PublicKey } from '@dxos/keys';
11
11
  import { useSpace } from '@dxos/react-client/echo';
12
12
  import { withClientProvider } from '@dxos/react-client/testing';
13
13
  import { useThemeContext } from '@dxos/react-ui';
14
14
  import { withTheme } from '@dxos/react-ui/testing';
15
+ import { useTextEditor } from '@dxos/react-ui-editor';
15
16
  import {
16
17
  createBasicExtensions,
17
18
  createMarkdownExtensions,
18
19
  createThemeExtensions,
19
20
  decorateMarkdown,
20
21
  documentId,
21
- useTextEditor,
22
- } from '@dxos/react-ui-editor';
22
+ } from '@dxos/ui-editor';
23
23
  import { isNonNullable } from '@dxos/util';
24
24
 
25
25
  import { GridSheet, SheetProvider, useComputeGraph } from '../components';
@@ -73,7 +73,12 @@ const Grid = () => {
73
73
  const model = useSheetModel(graph, sheet);
74
74
  useEffect(() => {
75
75
  if (model) {
76
- model.setValues({ A1: { value: 100 }, A2: { value: 200 }, A3: { value: 300 }, A5: { value: '=SUM(A1:A3)' } });
76
+ model.setValues({
77
+ A1: { value: 100 },
78
+ A2: { value: 200 },
79
+ A3: { value: 300 },
80
+ A5: { value: '=SUM(A1:A3)' },
81
+ });
77
82
  }
78
83
  }, [model]);
79
84
 
@@ -103,9 +108,13 @@ const meta = {
103
108
  title: 'plugins/plugin-sheet/extensions',
104
109
  decorators: [
105
110
  withTheme,
106
- withClientProvider({ types: [Sheet.Sheet], createIdentity: true, createSpace: true }),
111
+ withClientProvider({
112
+ types: [Sheet.Sheet],
113
+ createIdentity: true,
114
+ createSpace: true,
115
+ }),
107
116
  // TODO(wittjosiah): Try to write story which does not depend on plugin manager.
108
- withPluginManager({ plugins: [IntentPlugin()] }),
117
+ withPluginManager({ plugins: [OperationPlugin(), RuntimePlugin()] }),
109
118
  withComputeGraphDecorator(),
110
119
  ],
111
120
  parameters: {
@@ -23,7 +23,7 @@ import {
23
23
  createSheetName,
24
24
  } from '@dxos/compute';
25
25
  import { invariant } from '@dxos/invariant';
26
- import { documentId, singleValueFacet } from '@dxos/react-ui-editor';
26
+ import { documentId, singleValueFacet } from '@dxos/ui-editor';
27
27
 
28
28
  const LANGUAGE_TAG = 'dx';
29
29
 
@@ -20,8 +20,8 @@ import { spreadsheet } from 'codemirror-lang-spreadsheet';
20
20
 
21
21
  import { type FunctionDefinition } from '@dxos/compute';
22
22
  import { RANGE_NOTATION } from '@dxos/compute';
23
- import { singleValueFacet } from '@dxos/react-ui-editor';
24
- import { mx } from '@dxos/react-ui-theme';
23
+ import { singleValueFacet } from '@dxos/ui-editor';
24
+ import { mx } from '@dxos/ui-theme';
25
25
 
26
26
  /**
27
27
  * https://codemirror.net/examples/styling
@@ -75,7 +75,10 @@ export type SheetExtensionOptions = {
75
75
  * https://hyperformula.handsontable.com/guide/key-concepts.html#grammar
76
76
  */
77
77
  export const sheetExtension = ({ debug, functions = [] }: SheetExtensionOptions): Extension => {
78
- const { extension, language } = spreadsheet({ idiom: 'en-US', decimalSeparator: '.' });
78
+ const { extension, language } = spreadsheet({
79
+ idiom: 'en-US',
80
+ decimalSeparator: '.',
81
+ });
79
82
 
80
83
  const createCompletion = (name: string) => {
81
84
  const { section = 'Custom', description, syntax } = functions.find((value) => value.name === name) ?? {};
@@ -166,7 +169,7 @@ export const sheetExtension = ({ debug, functions = [] }: SheetExtensionOptions)
166
169
  icons: false,
167
170
  tooltipClass: () =>
168
171
  mx(
169
- '!-left-[1px] !top-[33px] !-m-0 border !border-t-0 [&>ul]:!min-w-[198px]',
172
+ '!-left-[1px] !top-[33px] !-m-0 border !border-bs-0 [&>ul]:!min-w-[198px]',
170
173
  '[&>ul>li[aria-selected]]:!bg-accentSurface',
171
174
  'border-separator',
172
175
  ),
package/src/index.ts CHANGED
@@ -2,6 +2,6 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- export { SheetCapabilities } from './capabilities';
5
+ export { SheetCapabilities } from './types';
6
6
  export * from './meta';
7
7
  export * from './SheetPlugin';
@@ -2,18 +2,18 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import * as Function from 'effect/Function';
6
- import * as Schema from 'effect/Schema';
5
+ import * as Effect from 'effect/Effect';
7
6
  import { useCallback, useEffect, useMemo } from 'react';
8
7
 
9
- import { LayoutAction, chain, createIntent, createResolver } from '@dxos/app-framework';
10
- import { useIntentDispatcher, useIntentResolver } from '@dxos/app-framework/react';
8
+ import { Common } from '@dxos/app-framework';
9
+ import { useOperationInvoker, useOperationResolver } from '@dxos/app-framework/react';
11
10
  import { debounce } from '@dxos/async';
12
11
  import { type CellAddress, type CompleteCellRange, inRange } from '@dxos/compute';
13
12
  import { Obj, Relation } from '@dxos/echo';
14
- import { ATTENDABLE_PATH_SEPARATOR, DeckAction } from '@dxos/plugin-deck/types';
15
- import { ThreadAction } from '@dxos/plugin-thread/types';
16
- import { Filter, Query, getSpace, useQuery } from '@dxos/react-client/echo';
13
+ import { OperationResolver } from '@dxos/operation';
14
+ import { ATTENDABLE_PATH_SEPARATOR, DeckOperation } from '@dxos/plugin-deck/types';
15
+ import { ThreadOperation } from '@dxos/plugin-thread/types';
16
+ import { Filter, Query, useQuery } from '@dxos/react-client/echo';
17
17
  import { type DxGridElement, type GridContentProps } from '@dxos/react-ui-grid';
18
18
  import { AnchoredTo, Thread } from '@dxos/types';
19
19
 
@@ -39,43 +39,37 @@ export const parseThreadAnchorAsCellRange = (cursor: string): CompleteCellRange
39
39
 
40
40
  export const useUpdateFocusedCellOnThreadSelection = (grid: DxGridElement | null) => {
41
41
  const { model, setActiveRefs } = useSheetContext();
42
- const scrollIntoViewResolver = useMemo(
42
+ const sheetId = Obj.getDXN(model.sheet).toString();
43
+
44
+ const scrollIntoViewHandler = useMemo(
43
45
  () =>
44
- createResolver({
45
- intent: LayoutAction.ScrollIntoView,
46
+ OperationResolver.make({
47
+ operation: Common.LayoutOperation.ScrollIntoView,
46
48
  position: 'hoist',
47
- filter: (
48
- data,
49
- ): data is {
50
- part: 'current';
51
- subject: string;
52
- options: { cursor: string; ref: GridContentProps['activeRefs'] };
53
- } => {
54
- if (!Schema.is(LayoutAction.ScrollIntoView.fields.input)(data)) {
55
- return false;
56
- }
57
-
58
- return data.subject === Obj.getDXN(model.sheet).toString() && !!data.options?.cursor;
59
- },
60
- resolve: ({ options: { cursor, ref } }) => {
61
- setActiveRefs(ref);
62
- // TODO(Zan): Everywhere we refer to the cursor in a thread context should change to `anchor`.
63
- const range = parseThreadAnchorAsCellRange(cursor!);
64
- range && grid?.setFocus({ ...range.to, plane: 'grid' }, true);
65
- },
49
+ filter: (input) => input.subject === sheetId && !!input.cursor,
50
+ handler: (input) =>
51
+ Effect.sync(() => {
52
+ const { cursor, ref } = input;
53
+ if (cursor) {
54
+ setActiveRefs(ref as GridContentProps['activeRefs']);
55
+ // TODO(Zan): Everywhere we refer to the cursor in a thread context should change to `anchor`.
56
+ const range = parseThreadAnchorAsCellRange(cursor);
57
+ range && grid?.setFocus({ ...range.to, plane: 'grid' }, true);
58
+ }
59
+ }),
66
60
  }),
67
- [model.sheet, setActiveRefs],
61
+ [sheetId, setActiveRefs, grid],
68
62
  );
69
63
 
70
- useIntentResolver(meta.id, scrollIntoViewResolver);
64
+ useOperationResolver(meta.id, scrollIntoViewHandler);
71
65
  };
72
66
 
73
67
  export const useSelectThreadOnCellFocus = () => {
74
68
  const { model, cursor } = useSheetContext();
75
- const { dispatchPromise: dispatch } = useIntentDispatcher();
69
+ const { invokePromise } = useOperationInvoker();
76
70
 
77
- const space = getSpace(model.sheet);
78
- const anchors = useQuery(space, Query.select(Filter.ids(model.sheet.id)).targetOf(AnchoredTo.AnchoredTo));
71
+ const db = Obj.getDatabase(model.sheet);
72
+ const anchors = useQuery(db, Query.select(Filter.id(model.sheet.id)).targetOf(AnchoredTo.AnchoredTo));
79
73
 
80
74
  const selectClosestThread = useCallback(
81
75
  (cellAddress: CellAddress) => {
@@ -95,14 +89,16 @@ export const useSelectThreadOnCellFocus = () => {
95
89
 
96
90
  if (closestThread) {
97
91
  const primary = Obj.getDXN(model.sheet).toString();
98
- const intent = Function.pipe(
99
- createIntent(ThreadAction.Select, { current: Obj.getDXN(closestThread).toString() }),
100
- chain(DeckAction.ChangeCompanion, { primary, companion: `${primary}${ATTENDABLE_PATH_SEPARATOR}comments` }),
101
- );
102
- void dispatch(intent);
92
+ void (async () => {
93
+ await invokePromise(ThreadOperation.Select, { current: Relation.getDXN(closestThread).toString() });
94
+ await invokePromise(DeckOperation.ChangeCompanion, {
95
+ primary,
96
+ companion: `${primary}${ATTENDABLE_PATH_SEPARATOR}comments`,
97
+ });
98
+ })();
103
99
  }
104
100
  },
105
- [dispatch, anchors],
101
+ [invokePromise, anchors],
106
102
  );
107
103
 
108
104
  const debounced = useMemo(() => {
package/src/meta.ts CHANGED
@@ -2,10 +2,10 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { type PluginMeta } from '@dxos/app-framework';
5
+ import { type Plugin } from '@dxos/app-framework';
6
6
  import { trim } from '@dxos/util';
7
7
 
8
- export const meta: PluginMeta = {
8
+ export const meta: Plugin.Meta = {
9
9
  id: 'dxos.org/plugin/sheet',
10
10
  name: 'Sheet',
11
11
  description: trim`
@@ -122,7 +122,9 @@ export class SheetModel extends Resource {
122
122
  */
123
123
  protected override async _open(): Promise<void> {
124
124
  log('initialize', { id: this.id });
125
- initialize(this._sheet);
125
+ Obj.change(this._sheet, (s) => {
126
+ initialize(s);
127
+ });
126
128
 
127
129
  this._graph.update.on((event) => {
128
130
  if (event.type === 'functionsUpdated') {
@@ -181,13 +183,19 @@ export class SheetModel extends Resource {
181
183
  }
182
184
 
183
185
  insertRows(i: number, n = 1): string[] {
184
- const idx = insertIndices(this._sheet.rows, i, n, MAX_ROWS);
186
+ let idx: string[] = [];
187
+ Obj.change(this._sheet, (s) => {
188
+ idx = insertIndices(s.rows, i, n, MAX_ROWS);
189
+ });
185
190
  this.reset();
186
191
  return idx;
187
192
  }
188
193
 
189
194
  insertColumns(i: number, n = 1): string[] {
190
- const idx = insertIndices(this._sheet.columns, i, n, MAX_COLS);
195
+ let idx: string[] = [];
196
+ Obj.change(this._sheet, (s) => {
197
+ idx = insertIndices(s.columns, i, n, MAX_COLS);
198
+ });
191
199
  this.reset();
192
200
  return idx;
193
201
  }
@@ -200,8 +208,10 @@ export class SheetModel extends Resource {
200
208
  const values = this.getCellValues(range).flat();
201
209
  const index = this._sheet.rows.indexOf(rowIndex);
202
210
  this.clear(range);
203
- this._sheet.rows.splice(index, 1);
204
- delete this._sheet.rowMeta[rowIndex];
211
+ Obj.change(this._sheet, (s) => {
212
+ s.rows.splice(index, 1);
213
+ delete s.rowMeta[rowIndex];
214
+ });
205
215
  this.reset();
206
216
  return { axis: 'row', index, axisIndex: rowIndex, axisMeta: this._sheet.rowMeta[rowIndex], values };
207
217
  }
@@ -214,35 +224,41 @@ export class SheetModel extends Resource {
214
224
  const values = this.getCellValues(range).flat();
215
225
  const index = this._sheet.columns.indexOf(colIndex);
216
226
  this.clear(range);
217
- this._sheet.columns.splice(index, 1);
218
- delete this._sheet.columnMeta[colIndex];
227
+ Obj.change(this._sheet, (s) => {
228
+ s.columns.splice(index, 1);
229
+ delete s.columnMeta[colIndex];
230
+ });
219
231
  this.reset();
220
232
  return { axis: 'col', index, axisIndex: colIndex, axisMeta: this._sheet.rowMeta[colIndex], values };
221
233
  }
222
234
 
223
235
  restoreRow({ index, axisIndex, axisMeta, values }: SheetAction.RestoreAxis): void {
224
- this._sheet.rows.splice(index, 0, axisIndex);
225
- values.forEach((value, col) => {
226
- if (value) {
227
- this._sheet.cells[`${this._sheet.columns[col]}@${axisIndex}`] = { value };
236
+ Obj.change(this._sheet, (s) => {
237
+ s.rows.splice(index, 0, axisIndex);
238
+ values.forEach((value, col) => {
239
+ if (value) {
240
+ s.cells[`${s.columns[col]}@${axisIndex}`] = { value };
241
+ }
242
+ });
243
+ if (axisMeta) {
244
+ s.rowMeta[axisIndex] = axisMeta;
228
245
  }
229
246
  });
230
- if (axisMeta) {
231
- this._sheet.rowMeta[axisIndex] = axisMeta;
232
- }
233
247
  this.reset();
234
248
  }
235
249
 
236
250
  restoreColumn({ index, axisIndex, axisMeta, values }: SheetAction.RestoreAxis): void {
237
- this._sheet.columns.splice(index, 0, axisIndex);
238
- values.forEach((value, row) => {
239
- if (value) {
240
- this._sheet.cells[`${axisIndex}@${this._sheet.rows[row]}`] = { value };
251
+ Obj.change(this._sheet, (s) => {
252
+ s.columns.splice(index, 0, axisIndex);
253
+ values.forEach((value, row) => {
254
+ if (value) {
255
+ s.cells[`${axisIndex}@${s.rows[row]}`] = { value };
256
+ }
257
+ });
258
+ if (axisMeta) {
259
+ s.columnMeta[axisIndex] = axisMeta;
241
260
  }
242
261
  });
243
- if (axisMeta) {
244
- this._sheet.columnMeta[axisIndex] = axisMeta;
245
- }
246
262
  this.reset();
247
263
  }
248
264
 
@@ -259,18 +275,22 @@ export class SheetModel extends Resource {
259
275
  const topLeft = getTopLeft(range);
260
276
  const values = this._iterRange(range, () => null);
261
277
  this._node.graph.hf.setCellContents(toSimpleCellAddress(this._node.sheetId, topLeft), values);
262
- this._iterRange(range, (cell) => {
263
- const idx = addressToIndex(this._sheet, cell);
264
- delete this._sheet.cells[idx];
278
+ Obj.change(this._sheet, (s) => {
279
+ this._iterRange(range, (cell) => {
280
+ const idx = addressToIndex(this._sheet, cell);
281
+ delete s.cells[idx];
282
+ });
265
283
  });
266
284
  }
267
285
 
268
286
  cut(range: CellRange): void {
269
287
  invariant(this._node);
270
288
  this._node.graph.hf.cut(toModelRange(this._node.sheetId, range));
271
- this._iterRange(range, (cell) => {
272
- const idx = addressToIndex(this._sheet, cell);
273
- delete this._sheet.cells[idx];
289
+ Obj.change(this._sheet, (s) => {
290
+ this._iterRange(range, (cell) => {
291
+ const idx = addressToIndex(this._sheet, cell);
292
+ delete s.cells[idx];
293
+ });
274
294
  });
275
295
  }
276
296
 
@@ -283,13 +303,15 @@ export class SheetModel extends Resource {
283
303
  invariant(this._node);
284
304
  if (!this._node.graph.hf.isClipboardEmpty()) {
285
305
  const changes = this._node.graph.hf.paste(toSimpleCellAddress(this._node.sheetId, cell));
286
- for (const change of changes) {
287
- if (change instanceof ExportedCellChange) {
288
- const { address, newValue } = change;
289
- const idx = addressToIndex(this._sheet, { row: address.row, col: address.col });
290
- this._sheet.cells[idx] = { value: newValue };
306
+ Obj.change(this._sheet, (s) => {
307
+ for (const change of changes) {
308
+ if (change instanceof ExportedCellChange) {
309
+ const { address, newValue } = change;
310
+ const idx = addressToIndex(this._sheet, { row: address.row, col: address.col });
311
+ s.cells[idx] = { value: newValue };
312
+ }
291
313
  }
292
- }
314
+ });
293
315
  }
294
316
  }
295
317
 
@@ -380,11 +402,15 @@ export class SheetModel extends Resource {
380
402
  // Reallocate if > current bounds.
381
403
  let refresh = false;
382
404
  if (cell.row >= this._sheet.rows.length) {
383
- insertIndices(this._sheet.rows, cell.row, 1, MAX_ROWS);
405
+ Obj.change(this._sheet, (s) => {
406
+ insertIndices(s.rows, cell.row, 1, MAX_ROWS);
407
+ });
384
408
  refresh = true;
385
409
  }
386
410
  if (cell.col >= this._sheet.columns.length) {
387
- insertIndices(this._sheet.columns, cell.col, 1, MAX_COLS);
411
+ Obj.change(this._sheet, (s) => {
412
+ insertIndices(s.columns, cell.col, 1, MAX_COLS);
413
+ });
388
414
  refresh = true;
389
415
  }
390
416
 
@@ -401,13 +427,17 @@ export class SheetModel extends Resource {
401
427
  // Insert into sheet.
402
428
  const idx = addressToIndex(this._sheet, cell);
403
429
  if (value === undefined || value === null) {
404
- delete this._sheet.cells[idx];
430
+ Obj.change(this._sheet, (s) => {
431
+ delete s.cells[idx];
432
+ });
405
433
  } else {
406
434
  if (isFormula(value)) {
407
435
  value = this._graph.mapFunctionBindingToId(mapFormulaRefsToIndices(this._sheet, value));
408
436
  }
409
437
 
410
- this._sheet.cells[idx] = { value };
438
+ Obj.change(this._sheet, (s) => {
439
+ s.cells[idx] = { value };
440
+ });
411
441
  }
412
442
  }
413
443
 
@@ -10,7 +10,7 @@ export default defineConfig({
10
10
  ...e2ePreset(import.meta.dirname),
11
11
  // TODO(wittjosiah): Avoid hard-coding ports.
12
12
  webServer: {
13
- command: 'moon run storybook:serve-e2e -- --port=9005',
13
+ command: 'moon run storybook-react:serve-e2e -- --port=9005',
14
14
  port: 9005,
15
15
  reuseExistingServer: false,
16
16
  },
@@ -16,6 +16,7 @@ test.describe('plugin-sheet', () => {
16
16
  test.beforeEach(async ({ browser }) => {
17
17
  const setup = await setupPage(browser, {
18
18
  url: storybookUrl('plugins-plugin-sheet-sheetcontainer--spec', 9005),
19
+ viewportSize: { width: 1280, height: 720 },
19
20
  });
20
21
  page = setup.page;
21
22
  sheet = new SheetManager(page);
@@ -22,7 +22,7 @@ import { Function } from '@dxos/functions';
22
22
  describe('test', () => {
23
23
  test('test', async () => {
24
24
  const client = new Client();
25
- client.addTypes([Function.Function]);
25
+ await client.addTypes([Function.Function]);
26
26
  await client.initialize();
27
27
  await client.halo.createIdentity();
28
28
 
@@ -70,7 +70,7 @@ export const Sheet = Schema.Struct({
70
70
  // Cell formatting referenced by indexed range.
71
71
  ranges: Schema.Array(Range).pipe(Schema.mutable, FormInputAnnotation.set(false)),
72
72
  }).pipe(
73
- Type.Obj({
73
+ Type.object({
74
74
  typename: 'dxos.org/type/Sheet',
75
75
  version: '0.1.0',
76
76
  }),
@@ -86,18 +86,21 @@ export type SheetProps = {
86
86
  export const make = ({ name, cells = {}, ...size }: SheetProps = {}) => {
87
87
  const sheet = Obj.make(Sheet, { name, cells: {}, rows: [], columns: [], rowMeta: {}, columnMeta: {}, ranges: [] });
88
88
 
89
- initialize(sheet, size);
90
-
91
- if (cells) {
92
- Object.entries(cells).forEach(([key, { value }]) => {
93
- const idx = addressToIndex(sheet, addressFromA1Notation(key));
94
- if (isFormula(value)) {
95
- value = mapFormulaRefsToIndices(sheet, value);
96
- }
97
-
98
- sheet.cells[idx] = { value };
99
- });
100
- }
89
+ // Initialize and set cells within Obj.change to satisfy change context requirements.
90
+ Obj.change(sheet, () => {
91
+ initialize(sheet, size);
92
+
93
+ if (cells) {
94
+ Object.entries(cells).forEach(([key, { value }]) => {
95
+ const idx = addressToIndex(sheet, addressFromA1Notation(key));
96
+ if (isFormula(value)) {
97
+ value = mapFormulaRefsToIndices(sheet, value);
98
+ }
99
+
100
+ sheet.cells[idx] = { value };
101
+ });
102
+ }
103
+ });
101
104
 
102
105
  return sheet;
103
106
  };
@@ -2,13 +2,13 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { defineCapability } from '@dxos/app-framework';
5
+ import { Capability } from '@dxos/app-framework';
6
6
  import { type ComputeGraphRegistry } from '@dxos/compute';
7
7
 
8
8
  import { meta } from '../meta';
9
9
 
10
10
  export namespace SheetCapabilities {
11
- export const ComputeGraphRegistry = defineCapability<ComputeGraphRegistry>(
11
+ export const ComputeGraphRegistry = Capability.make<ComputeGraphRegistry>(
12
12
  `${meta.id}/capability/compute-graph-registry`,
13
13
  );
14
14
  }
@@ -2,6 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
+ export * from './capabilities';
5
6
  export * as Sheet from './Sheet';
6
7
  export * from './sheet-range-types';
7
8
  export * from './types';