@dxos/plugin-sheet 0.7.5-main.9d26e3a → 0.7.5-main.e9bb01b

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 (187) hide show
  1. package/dist/lib/browser/SheetContainer-QE32GHSA.mjs +370 -0
  2. package/dist/lib/browser/SheetContainer-QE32GHSA.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-5IP6N25X.mjs +18 -0
  4. package/dist/lib/browser/chunk-5IP6N25X.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-A374JPWV.mjs → chunk-EEN6LQ77.mjs} +157 -391
  6. package/dist/lib/browser/chunk-EEN6LQ77.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-FOO6NGBM.mjs +229 -0
  8. package/dist/lib/browser/chunk-FOO6NGBM.mjs.map +7 -0
  9. package/dist/lib/browser/{chunk-Q4XS4YWF.mjs → chunk-MW7L2R23.mjs} +2 -2
  10. package/dist/lib/browser/chunk-MW7L2R23.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-NA2WJTDQ.mjs +15 -0
  12. package/dist/lib/browser/chunk-NA2WJTDQ.mjs.map +7 -0
  13. package/dist/lib/browser/compute-graph-registry-5PSCPAJC.mjs +27 -0
  14. package/dist/lib/browser/compute-graph-registry-5PSCPAJC.mjs.map +7 -0
  15. package/dist/lib/browser/index.mjs +80 -218
  16. package/dist/lib/browser/index.mjs.map +4 -4
  17. package/dist/lib/browser/intent-resolver-BIOB22P2.mjs +56 -0
  18. package/dist/lib/browser/intent-resolver-BIOB22P2.mjs.map +7 -0
  19. package/dist/lib/browser/markdown-ZXHPFU4B.mjs +26 -0
  20. package/dist/lib/browser/markdown-ZXHPFU4B.mjs.map +7 -0
  21. package/dist/lib/browser/meta.json +1 -1
  22. package/dist/lib/browser/react-surface-DUNHY5TJ.mjs +52 -0
  23. package/dist/lib/browser/react-surface-DUNHY5TJ.mjs.map +7 -0
  24. package/dist/lib/browser/thread-RSI66HGQ.mjs +17 -0
  25. package/dist/lib/browser/thread-RSI66HGQ.mjs.map +7 -0
  26. package/dist/lib/browser/types/index.mjs +2 -2
  27. package/dist/lib/node/SheetContainer-63QTAGQQ.cjs +364 -0
  28. package/dist/lib/node/SheetContainer-63QTAGQQ.cjs.map +7 -0
  29. package/dist/lib/node/{chunk-TQOJ7DG2.cjs → chunk-6BZ2TACG.cjs} +6 -6
  30. package/dist/lib/node/chunk-6BZ2TACG.cjs.map +7 -0
  31. package/dist/lib/node/{meta.cjs → chunk-6G6HHJOM.cjs} +12 -8
  32. package/dist/lib/node/chunk-6G6HHJOM.cjs.map +7 -0
  33. package/dist/lib/node/{chunk-2ZVZI2KJ.cjs → chunk-AUC5XQEN.cjs} +12 -9
  34. package/dist/lib/node/chunk-AUC5XQEN.cjs.map +7 -0
  35. package/dist/lib/node/{chunk-FDEQ2PGJ.cjs → chunk-K4VMHOR2.cjs} +198 -428
  36. package/dist/lib/node/chunk-K4VMHOR2.cjs.map +7 -0
  37. package/dist/lib/node/chunk-P4KSGZSS.cjs +251 -0
  38. package/dist/lib/node/chunk-P4KSGZSS.cjs.map +7 -0
  39. package/dist/lib/node/compute-graph-registry-IKYGA5ZC.cjs +53 -0
  40. package/dist/lib/node/compute-graph-registry-IKYGA5ZC.cjs.map +7 -0
  41. package/dist/lib/node/index.cjs +81 -215
  42. package/dist/lib/node/index.cjs.map +4 -4
  43. package/dist/lib/node/intent-resolver-EN5ZMUUF.cjs +69 -0
  44. package/dist/lib/node/intent-resolver-EN5ZMUUF.cjs.map +7 -0
  45. package/dist/lib/node/markdown-7NVPUDWI.cjs +40 -0
  46. package/dist/lib/node/markdown-7NVPUDWI.cjs.map +7 -0
  47. package/dist/lib/node/meta.json +1 -1
  48. package/dist/lib/node/react-surface-YGALRCRL.cjs +70 -0
  49. package/dist/lib/node/react-surface-YGALRCRL.cjs.map +7 -0
  50. package/dist/lib/node/thread-7KJVRDUE.cjs +32 -0
  51. package/dist/lib/node/thread-7KJVRDUE.cjs.map +7 -0
  52. package/dist/lib/node/types/index.cjs +30 -30
  53. package/dist/lib/node/types/index.cjs.map +1 -1
  54. package/dist/lib/node-esm/SheetContainer-EUR47CP5.mjs +371 -0
  55. package/dist/lib/node-esm/SheetContainer-EUR47CP5.mjs.map +7 -0
  56. package/dist/lib/node-esm/chunk-6C53G45G.mjs +16 -0
  57. package/dist/lib/node-esm/chunk-6C53G45G.mjs.map +7 -0
  58. package/dist/lib/node-esm/chunk-JFUKD7N4.mjs +20 -0
  59. package/dist/lib/node-esm/chunk-JFUKD7N4.mjs.map +7 -0
  60. package/dist/lib/node-esm/{chunk-NYYIDVR7.mjs → chunk-LGQMXD6K.mjs} +2 -2
  61. package/dist/lib/node-esm/chunk-LGQMXD6K.mjs.map +7 -0
  62. package/dist/lib/node-esm/chunk-PTOI45NK.mjs +231 -0
  63. package/dist/lib/node-esm/chunk-PTOI45NK.mjs.map +7 -0
  64. package/dist/lib/node-esm/{chunk-L5PQHVTX.mjs → chunk-RFGJUSHF.mjs} +157 -391
  65. package/dist/lib/node-esm/chunk-RFGJUSHF.mjs.map +7 -0
  66. package/dist/lib/node-esm/compute-graph-registry-ZSLEFSS5.mjs +28 -0
  67. package/dist/lib/node-esm/compute-graph-registry-ZSLEFSS5.mjs.map +7 -0
  68. package/dist/lib/node-esm/index.mjs +80 -218
  69. package/dist/lib/node-esm/index.mjs.map +4 -4
  70. package/dist/lib/node-esm/intent-resolver-6BCKQA5A.mjs +57 -0
  71. package/dist/lib/node-esm/intent-resolver-6BCKQA5A.mjs.map +7 -0
  72. package/dist/lib/node-esm/markdown-LRZEUBKN.mjs +27 -0
  73. package/dist/lib/node-esm/markdown-LRZEUBKN.mjs.map +7 -0
  74. package/dist/lib/node-esm/meta.json +1 -1
  75. package/dist/lib/node-esm/react-surface-AAT56ZBA.mjs +53 -0
  76. package/dist/lib/node-esm/react-surface-AAT56ZBA.mjs.map +7 -0
  77. package/dist/lib/node-esm/thread-U3RIKVMB.mjs +18 -0
  78. package/dist/lib/node-esm/thread-U3RIKVMB.mjs.map +7 -0
  79. package/dist/lib/node-esm/types/index.mjs +2 -2
  80. package/dist/types/src/SheetPlugin.d.ts +1 -3
  81. package/dist/types/src/SheetPlugin.d.ts.map +1 -1
  82. package/dist/types/src/capabilities/capabilities.d.ts +5 -0
  83. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -0
  84. package/dist/types/src/capabilities/compute-graph-registry.d.ts +4 -0
  85. package/dist/types/src/capabilities/compute-graph-registry.d.ts.map +1 -0
  86. package/dist/types/src/capabilities/index.d.ts +12 -0
  87. package/dist/types/src/capabilities/index.d.ts.map +1 -0
  88. package/dist/types/src/capabilities/intent-resolver.d.ts +4 -0
  89. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -0
  90. package/dist/types/src/capabilities/markdown.d.ts +6 -0
  91. package/dist/types/src/capabilities/markdown.d.ts.map +1 -0
  92. package/dist/types/src/capabilities/react-surface.d.ts +4 -0
  93. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  94. package/dist/types/src/capabilities/thread.d.ts +6 -0
  95. package/dist/types/src/capabilities/thread.d.ts.map +1 -0
  96. package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts.map +1 -1
  97. package/dist/types/src/components/SheetContainer/SheetContainer.d.ts.map +1 -1
  98. package/dist/types/src/components/SheetContainer/SheetContainer.stories.d.ts.map +1 -1
  99. package/dist/types/src/components/SheetToolbar/SheetToolbar.d.ts +7 -0
  100. package/dist/types/src/components/SheetToolbar/SheetToolbar.d.ts.map +1 -0
  101. package/dist/types/src/components/SheetToolbar/SheetToolbar.stories.d.ts +6 -0
  102. package/dist/types/src/components/SheetToolbar/SheetToolbar.stories.d.ts.map +1 -0
  103. package/dist/types/src/components/SheetToolbar/align.d.ts +28 -0
  104. package/dist/types/src/components/SheetToolbar/align.d.ts.map +1 -0
  105. package/dist/types/src/components/SheetToolbar/comment.d.ts +23 -0
  106. package/dist/types/src/components/SheetToolbar/comment.d.ts.map +1 -0
  107. package/dist/types/src/components/SheetToolbar/index.d.ts +2 -0
  108. package/dist/types/src/components/SheetToolbar/index.d.ts.map +1 -0
  109. package/dist/types/src/components/SheetToolbar/style.d.ts +26 -0
  110. package/dist/types/src/components/SheetToolbar/style.d.ts.map +1 -0
  111. package/dist/types/src/components/SheetToolbar/useToolbarAction.d.ts +8 -0
  112. package/dist/types/src/components/SheetToolbar/useToolbarAction.d.ts.map +1 -0
  113. package/dist/types/src/components/SheetToolbar/useToolbarState.d.ts +6 -0
  114. package/dist/types/src/components/SheetToolbar/useToolbarState.d.ts.map +1 -0
  115. package/dist/types/src/components/index.d.ts +1 -2
  116. package/dist/types/src/components/index.d.ts.map +1 -1
  117. package/dist/types/src/index.d.ts +2 -3
  118. package/dist/types/src/index.d.ts.map +1 -1
  119. package/dist/types/src/integrations/thread-ranges.d.ts.map +1 -1
  120. package/dist/types/src/meta.d.ts +2 -2
  121. package/dist/types/src/meta.d.ts.map +1 -1
  122. package/dist/types/src/testing/testing.d.ts +1 -1
  123. package/dist/types/src/testing/testing.d.ts.map +1 -1
  124. package/dist/types/src/types/sheet-range-types.d.ts +1 -1
  125. package/dist/types/src/types/sheet-range-types.d.ts.map +1 -1
  126. package/dist/types/src/types/types.d.ts +0 -11
  127. package/dist/types/src/types/types.d.ts.map +1 -1
  128. package/dist/types/tsconfig.tsbuildinfo +1 -1
  129. package/package.json +45 -52
  130. package/src/SheetPlugin.tsx +55 -103
  131. package/src/capabilities/capabilities.ts +14 -0
  132. package/src/capabilities/compute-graph-registry.ts +25 -0
  133. package/src/capabilities/index.ts +13 -0
  134. package/src/capabilities/intent-resolver.ts +38 -0
  135. package/src/capabilities/markdown.ts +22 -0
  136. package/src/capabilities/react-surface.tsx +37 -0
  137. package/src/capabilities/thread.ts +14 -0
  138. package/src/components/GridSheet/GridSheet.stories.tsx +2 -0
  139. package/src/components/GridSheet/util.ts +1 -1
  140. package/src/components/SheetContainer/SheetContainer.stories.tsx +28 -22
  141. package/src/components/SheetContainer/SheetContainer.tsx +3 -8
  142. package/src/components/{Toolbar/Toolbar.stories.tsx → SheetToolbar/SheetToolbar.stories.tsx} +4 -8
  143. package/src/components/SheetToolbar/SheetToolbar.tsx +48 -0
  144. package/src/components/SheetToolbar/align.ts +68 -0
  145. package/src/components/SheetToolbar/comment.ts +56 -0
  146. package/src/components/{Toolbar → SheetToolbar}/index.ts +1 -1
  147. package/src/components/SheetToolbar/style.ts +72 -0
  148. package/src/components/SheetToolbar/useToolbarAction.ts +87 -0
  149. package/src/components/SheetToolbar/useToolbarState.ts +17 -0
  150. package/src/components/index.ts +0 -1
  151. package/src/index.ts +2 -5
  152. package/src/integrations/thread-ranges.ts +21 -10
  153. package/src/meta.ts +3 -2
  154. package/src/types/sheet-range-types.ts +1 -1
  155. package/src/types/types.ts +0 -26
  156. package/dist/lib/browser/SheetContainer-S4NCLUYL.mjs +0 -290
  157. package/dist/lib/browser/SheetContainer-S4NCLUYL.mjs.map +0 -7
  158. package/dist/lib/browser/chunk-A374JPWV.mjs.map +0 -7
  159. package/dist/lib/browser/chunk-Q4XS4YWF.mjs.map +0 -7
  160. package/dist/lib/browser/chunk-RABELMEQ.mjs +0 -15
  161. package/dist/lib/browser/chunk-RABELMEQ.mjs.map +0 -7
  162. package/dist/lib/browser/meta.mjs +0 -9
  163. package/dist/lib/browser/meta.mjs.map +0 -7
  164. package/dist/lib/node/SheetContainer-TP4GYXZB.cjs +0 -296
  165. package/dist/lib/node/SheetContainer-TP4GYXZB.cjs.map +0 -7
  166. package/dist/lib/node/chunk-2ZVZI2KJ.cjs.map +0 -7
  167. package/dist/lib/node/chunk-FDEQ2PGJ.cjs.map +0 -7
  168. package/dist/lib/node/chunk-TQOJ7DG2.cjs.map +0 -7
  169. package/dist/lib/node/meta.cjs.map +0 -7
  170. package/dist/lib/node-esm/SheetContainer-YB3JBVPZ.mjs +0 -291
  171. package/dist/lib/node-esm/SheetContainer-YB3JBVPZ.mjs.map +0 -7
  172. package/dist/lib/node-esm/chunk-BM2Q3FFC.mjs +0 -17
  173. package/dist/lib/node-esm/chunk-BM2Q3FFC.mjs.map +0 -7
  174. package/dist/lib/node-esm/chunk-L5PQHVTX.mjs.map +0 -7
  175. package/dist/lib/node-esm/chunk-NYYIDVR7.mjs.map +0 -7
  176. package/dist/lib/node-esm/meta.mjs +0 -10
  177. package/dist/lib/node-esm/meta.mjs.map +0 -7
  178. package/dist/types/src/components/SheetObjectSettings.d.ts +0 -7
  179. package/dist/types/src/components/SheetObjectSettings.d.ts.map +0 -1
  180. package/dist/types/src/components/Toolbar/Toolbar.d.ts +0 -48
  181. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +0 -1
  182. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +0 -7
  183. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +0 -1
  184. package/dist/types/src/components/Toolbar/index.d.ts +0 -2
  185. package/dist/types/src/components/Toolbar/index.d.ts.map +0 -1
  186. package/src/components/SheetObjectSettings.tsx +0 -38
  187. package/src/components/Toolbar/Toolbar.tsx +0 -344
@@ -2,119 +2,71 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import React from 'react';
6
-
7
- import { createIntent, createResolver, createSurface, resolvePlugin, type PluginDefinition } from '@dxos/app-framework';
8
- import { type ComputeGraphRegistry } from '@dxos/compute';
5
+ import { Capabilities, contributes, createIntent, defineModule, definePlugin, Events } from '@dxos/app-framework';
9
6
  import { FunctionType } from '@dxos/functions';
10
- import { invariant } from '@dxos/invariant';
11
- import { parseClientPlugin } from '@dxos/plugin-client/types';
12
- import { getSpace } from '@dxos/react-client/echo';
7
+ import { ClientCapabilities, ClientEvents } from '@dxos/plugin-client';
13
8
 
14
- import { ComputeGraphContextProvider, SheetContainer, SheetObjectSettings } from './components';
15
- import { computeGraphFacet } from './extensions';
16
- import meta, { SHEET_PLUGIN } from './meta';
9
+ import { Markdown, Thread, ReactSurface, IntentResolver, ComputeGraphRegistry } from './capabilities';
10
+ import { meta, SHEET_PLUGIN } from './meta';
17
11
  import { serializer } from './serializer';
18
12
  import translations from './translations';
19
- import { compareIndexPositions, createSheet, SheetAction, SheetType, type SheetPluginProvides } from './types';
20
-
21
- export const SheetPlugin = (): PluginDefinition<SheetPluginProvides> => {
22
- let computeGraphRegistry: ComputeGraphRegistry | undefined;
23
-
24
- return {
25
- meta,
26
- ready: async ({ plugins }) => {
27
- const client = resolvePlugin(plugins, parseClientPlugin)?.provides.client;
28
- invariant(client);
29
- let remoteFunctionUrl: string | undefined;
30
- if (client.config.values.runtime?.services?.edge?.url) {
31
- const url = new URL('/functions', client.config.values.runtime?.services?.edge?.url);
32
- url.protocol = 'https';
33
- remoteFunctionUrl = url.toString();
34
- }
13
+ import { SheetAction, SheetType } from './types';
35
14
 
36
- // Async import removes direct dependency on hyperformula.
37
- const { defaultPlugins, ComputeGraphRegistry } = await import('@dxos/compute');
38
- computeGraphRegistry = new ComputeGraphRegistry({ plugins: defaultPlugins, remoteFunctionUrl });
39
- },
40
- provides: {
41
- context: ({ children }) => {
42
- invariant(computeGraphRegistry);
43
- return <ComputeGraphContextProvider registry={computeGraphRegistry}>{children}</ComputeGraphContextProvider>;
44
- },
45
- metadata: {
46
- records: {
47
- [SheetType.typename]: {
15
+ export const SheetPlugin = () =>
16
+ definePlugin(meta, [
17
+ defineModule({
18
+ id: `${meta.id}/module/compute-graph-registry`,
19
+ activatesOn: ClientEvents.ClientReady,
20
+ activate: ComputeGraphRegistry,
21
+ }),
22
+ defineModule({
23
+ id: `${meta.id}/module/translations`,
24
+ activatesOn: Events.SetupTranslations,
25
+ activate: () => contributes(Capabilities.Translations, translations),
26
+ }),
27
+ defineModule({
28
+ id: `${meta.id}/module/metadata`,
29
+ activatesOn: Events.SetupMetadata,
30
+ activate: () =>
31
+ contributes(Capabilities.Metadata, {
32
+ id: SheetType.typename,
33
+ metadata: {
48
34
  createObject: (props: { name?: string }) => createIntent(SheetAction.Create, props),
49
35
  label: (object: any) => (object instanceof SheetType ? object.name : undefined),
50
36
  placeholder: ['sheet title placeholder', { ns: SHEET_PLUGIN }],
51
37
  icon: 'ph--grid-nine--regular',
52
38
  serializer,
53
39
  },
54
- },
55
- },
56
- translations,
57
- echo: {
58
- schema: [SheetType],
40
+ }),
41
+ }),
42
+ defineModule({
43
+ id: `${meta.id}/module/schema`,
44
+ activatesOn: ClientEvents.SetupSchema,
45
+ activate: () => [
46
+ contributes(ClientCapabilities.Schema, [SheetType]),
59
47
  // TODO(wittjosiah): Factor out to common package/plugin.
60
48
  // FunctionType is currently registered here in case script plugin isn't enabled.
61
- system: [FunctionType],
62
- },
63
- markdown: {
64
- extensions: ({ document: doc }) => {
65
- invariant(computeGraphRegistry);
66
- const space = getSpace(doc);
67
- if (space) {
68
- const computeGraph = computeGraphRegistry.getOrCreateGraph(space);
69
- return computeGraphFacet.of(computeGraph);
70
- }
71
- },
72
- },
73
- thread: {
74
- predicate: (data) => data instanceof SheetType,
75
- createSort: (sheet) => (indexA, indexB) =>
76
- !indexA || !indexB ? 0 : compareIndexPositions(sheet, indexA, indexB),
77
- },
78
- surface: {
79
- definitions: () => [
80
- createSurface({
81
- id: `${SHEET_PLUGIN}/sheet`,
82
- role: ['article', 'section'],
83
- filter: (data): data is { subject: SheetType } =>
84
- data.subject instanceof SheetType && !!getSpace(data.subject),
85
- component: ({ data, role }) => (
86
- <SheetContainer space={getSpace(data.subject)!} sheet={data.subject} role={role} />
87
- ),
88
- }),
89
- createSurface({
90
- id: `${SHEET_PLUGIN}/settings`,
91
- role: 'complementary--settings',
92
- filter: (data): data is { subject: SheetType } => data.subject instanceof SheetType,
93
- component: ({ data }) => <SheetObjectSettings sheet={data.subject} />,
94
- }),
95
- ],
96
- },
97
- intent: {
98
- resolvers: () => [
99
- createResolver(SheetAction.Create, ({ name }) => ({ data: { object: createSheet({ name }) } })),
100
- createResolver(SheetAction.InsertAxis, ({ model, axis, index, count }) => {
101
- const _indices = model[axis === 'col' ? 'insertColumns' : 'insertRows'](index, count);
102
- }),
103
- createResolver(SheetAction.DropAxis, ({ model, axis, axisIndex, deletionData }, undo) => {
104
- if (!undo) {
105
- const undoData = model[axis === 'col' ? 'dropColumn' : 'dropRow'](axisIndex);
106
- return {
107
- undoable: {
108
- message: (translations[0]['en-US'][SHEET_PLUGIN] as any)[`${axis} dropped label`],
109
- data: { ...undoData, model },
110
- },
111
- };
112
- } else if (undo && deletionData) {
113
- model[deletionData.axis === 'col' ? 'restoreColumn' : 'restoreRow'](deletionData);
114
- }
115
- }),
116
- ],
117
- },
118
- },
119
- };
120
- };
49
+ contributes(ClientCapabilities.SystemSchema, [FunctionType]),
50
+ ],
51
+ }),
52
+ defineModule({
53
+ id: `${meta.id}/module/markdown`,
54
+ activatesOn: Events.Startup,
55
+ activate: Markdown,
56
+ }),
57
+ defineModule({
58
+ id: `${meta.id}/module/thread`,
59
+ activatesOn: Events.Startup,
60
+ activate: Thread,
61
+ }),
62
+ defineModule({
63
+ id: `${meta.id}/module/react-surface`,
64
+ activatesOn: Events.SetupSurfaces,
65
+ activate: ReactSurface,
66
+ }),
67
+ defineModule({
68
+ id: `${meta.id}/module/intent-resolver`,
69
+ activatesOn: Events.SetupIntents,
70
+ activate: IntentResolver,
71
+ }),
72
+ ]);
@@ -0,0 +1,14 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { defineCapability } from '@dxos/app-framework';
6
+ import { type ComputeGraphRegistry } from '@dxos/compute';
7
+
8
+ import { SHEET_PLUGIN } from '../meta';
9
+
10
+ export namespace SheetCapabilities {
11
+ export const ComputeGraphRegistry = defineCapability<ComputeGraphRegistry>(
12
+ `${SHEET_PLUGIN}/capability/compute-graph-registry`,
13
+ );
14
+ }
@@ -0,0 +1,25 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { contributes, type PluginsContext } from '@dxos/app-framework';
6
+ import { ClientCapabilities } from '@dxos/plugin-client';
7
+
8
+ import { SheetCapabilities } from './capabilities';
9
+
10
+ export default async (context: PluginsContext) => {
11
+ const client = context.requestCapability(ClientCapabilities.Client);
12
+ let remoteFunctionUrl: string | undefined;
13
+ if (client.config.values.runtime?.services?.edge?.url) {
14
+ const url = new URL('/functions', client.config.values.runtime?.services?.edge?.url);
15
+ url.protocol = 'https';
16
+ remoteFunctionUrl = url.toString();
17
+ }
18
+
19
+ // TODO(wittjosiah): This can probably be a module level import now due to lazy capability loading.
20
+ // Async import removes direct dependency on hyperformula.
21
+ const { defaultPlugins, ComputeGraphRegistry } = await import('@dxos/compute');
22
+ const computeGraphRegistry = new ComputeGraphRegistry({ plugins: defaultPlugins, remoteFunctionUrl });
23
+
24
+ return contributes(SheetCapabilities.ComputeGraphRegistry, computeGraphRegistry);
25
+ };
@@ -0,0 +1,13 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { lazy } from '@dxos/app-framework';
6
+
7
+ export const ComputeGraphRegistry = lazy(() => import('./compute-graph-registry'));
8
+ export const IntentResolver = lazy(() => import('./intent-resolver'));
9
+ export const Markdown = lazy(() => import('./markdown'));
10
+ export const ReactSurface = lazy(() => import('./react-surface'));
11
+ export const Thread = lazy(() => import('./thread'));
12
+
13
+ export * from './capabilities';
@@ -0,0 +1,38 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { contributes, Capabilities, createResolver } from '@dxos/app-framework';
6
+
7
+ import { SHEET_PLUGIN } from '../meta';
8
+ import { createSheet, SheetAction } from '../types';
9
+
10
+ export default () =>
11
+ contributes(Capabilities.IntentResolver, [
12
+ createResolver({
13
+ intent: SheetAction.Create,
14
+ resolve: ({ name }) => ({ data: { object: createSheet({ name }) } }),
15
+ }),
16
+ createResolver({
17
+ intent: SheetAction.InsertAxis,
18
+ resolve: ({ model, axis, index, count }) => {
19
+ const _indices = model[axis === 'col' ? 'insertColumns' : 'insertRows'](index, count);
20
+ },
21
+ }),
22
+ createResolver({
23
+ intent: SheetAction.DropAxis,
24
+ resolve: ({ model, axis, axisIndex, deletionData }, undo) => {
25
+ if (!undo) {
26
+ const undoData = model[axis === 'col' ? 'dropColumn' : 'dropRow'](axisIndex);
27
+ return {
28
+ undoable: {
29
+ message: [`${axis} dropped label`, { ns: SHEET_PLUGIN }],
30
+ data: { ...undoData, model },
31
+ },
32
+ };
33
+ } else if (undo && deletionData) {
34
+ model[deletionData.axis === 'col' ? 'restoreColumn' : 'restoreRow'](deletionData);
35
+ }
36
+ },
37
+ }),
38
+ ]);
@@ -0,0 +1,22 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { contributes, type PluginsContext } from '@dxos/app-framework';
6
+ import { getSpace } from '@dxos/client/echo';
7
+ import { MarkdownCapabilities } from '@dxos/plugin-markdown';
8
+
9
+ import { SheetCapabilities } from './capabilities';
10
+ import { computeGraphFacet } from '../extensions';
11
+
12
+ export default (context: PluginsContext) =>
13
+ contributes(MarkdownCapabilities.Extensions, [
14
+ ({ document: doc }) => {
15
+ const computeGraphRegistry = context.requestCapability(SheetCapabilities.ComputeGraphRegistry);
16
+ const space = getSpace(doc);
17
+ if (space) {
18
+ const computeGraph = computeGraphRegistry.getOrCreateGraph(space);
19
+ return computeGraphFacet.of(computeGraph);
20
+ }
21
+ },
22
+ ]);
@@ -0,0 +1,37 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { Capabilities, contributes, createSurface, useCapability } from '@dxos/app-framework';
8
+ import { getSpace } from '@dxos/react-client/echo';
9
+
10
+ import { SheetCapabilities } from './capabilities';
11
+ import { ComputeGraphContextProvider, RangeList, SheetContainer } from '../components';
12
+ import { SHEET_PLUGIN } from '../meta';
13
+ import { SheetType } from '../types';
14
+
15
+ export default () =>
16
+ contributes(Capabilities.ReactSurface, [
17
+ createSurface({
18
+ id: `${SHEET_PLUGIN}/sheet`,
19
+ role: ['article', 'section'],
20
+ filter: (data): data is { subject: SheetType } => data.subject instanceof SheetType && !!getSpace(data.subject),
21
+ component: ({ data, role }) => {
22
+ const computeGraphRegistry = useCapability(SheetCapabilities.ComputeGraphRegistry);
23
+
24
+ return (
25
+ <ComputeGraphContextProvider registry={computeGraphRegistry}>
26
+ <SheetContainer space={getSpace(data.subject)!} sheet={data.subject} role={role} />
27
+ </ComputeGraphContextProvider>
28
+ );
29
+ },
30
+ }),
31
+ createSurface({
32
+ id: `${SHEET_PLUGIN}/settings`,
33
+ role: 'complementary--settings',
34
+ filter: (data): data is { subject: SheetType } => data.subject instanceof SheetType,
35
+ component: ({ data }) => <RangeList sheet={data.subject} />,
36
+ }),
37
+ ]);
@@ -0,0 +1,14 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { contributes } from '@dxos/app-framework';
6
+ import { ThreadCapabilities } from '@dxos/plugin-space';
7
+
8
+ import { compareIndexPositions, SheetType } from '../types';
9
+
10
+ export default () =>
11
+ contributes(ThreadCapabilities.Thread, {
12
+ predicate: (data) => data instanceof SheetType,
13
+ createSort: (sheet) => (indexA, indexB) => (!indexA || !indexB ? 0 : compareIndexPositions(sheet, indexA, indexB)),
14
+ });
@@ -7,6 +7,7 @@ import '@dxos-theme';
7
7
  import { type Meta } from '@storybook/react';
8
8
  import React from 'react';
9
9
 
10
+ import { withPluginManager } from '@dxos/app-framework/testing';
10
11
  import { useSpace } from '@dxos/react-client/echo';
11
12
  import { withClientProvider } from '@dxos/react-client/testing';
12
13
  import { withTheme, withLayout } from '@dxos/storybook-utils';
@@ -41,6 +42,7 @@ const meta: Meta = {
41
42
  withComputeGraphDecorator(),
42
43
  withTheme,
43
44
  withLayout({ fullscreen: true, tooltips: true, classNames: 'grid' }),
45
+ withPluginManager(),
44
46
  ],
45
47
  parameters: { translations },
46
48
  };
@@ -89,7 +89,7 @@ const gridCellGetter = (model: SheetModel) => {
89
89
 
90
90
  export const rowLabelCell = (row: number) => ({
91
91
  value: rowToA1Notation(row),
92
- className: 'text-end !pie-1 text-subdued',
92
+ className: 'text-end pie-1 text-subdued',
93
93
  resizeHandle: 'row',
94
94
  });
95
95
 
@@ -7,10 +7,12 @@ import '@dxos-theme';
7
7
  import { type Meta } from '@storybook/react';
8
8
  import React from 'react';
9
9
 
10
- import { type AnyIntentChain, type IntentContext, IntentProvider } from '@dxos/app-framework';
11
- import { todo } from '@dxos/debug';
12
- import { useSpace, create } from '@dxos/react-client/echo';
10
+ import { Capabilities, contributes, createResolver, IntentPlugin } from '@dxos/app-framework';
11
+ import { withPluginManager } from '@dxos/app-framework/testing';
12
+ import { fullyQualifiedId, useSpace } from '@dxos/react-client/echo';
13
13
  import { withClientProvider } from '@dxos/react-client/testing';
14
+ import { AttendableContainer } from '@dxos/react-ui-attention';
15
+ import { withAttention } from '@dxos/react-ui-attention/testing';
14
16
  import { withTheme, withLayout } from '@dxos/storybook-utils';
15
17
 
16
18
  import { SheetContainer } from './SheetContainer';
@@ -20,22 +22,6 @@ import { SheetAction, SheetType } from '../../types';
20
22
  import { useComputeGraph } from '../ComputeGraph';
21
23
  import { RangeList } from '../RangeList';
22
24
 
23
- // TODO(thure via wittjosiah): stories/components should be written such that the dependency on intents is external and provided via callback and then the story can implement it differently.
24
- const storybookIntentValue = create<IntentContext>({
25
- dispatch: () => todo(),
26
- dispatchPromise: async (intentChain: AnyIntentChain): Promise<any> => {
27
- switch (intentChain.first.action) {
28
- case SheetAction.DropAxis._tag: {
29
- const { model, axis, axisIndex } = intentChain.first.data as SheetAction.DropAxis['input'];
30
- model[axis === 'col' ? 'dropColumn' : 'dropRow'](axisIndex);
31
- }
32
- }
33
- },
34
- undo: () => todo(),
35
- undoPromise: () => todo(),
36
- registerResolver: () => () => {},
37
- });
38
-
39
25
  export const Basic = () => {
40
26
  const space = useSpace();
41
27
  const graph = useComputeGraph(space);
@@ -44,7 +30,11 @@ export const Basic = () => {
44
30
  return null;
45
31
  }
46
32
 
47
- return <SheetContainer space={space} sheet={sheet} role='article' ignoreAttention />;
33
+ return (
34
+ <AttendableContainer id={fullyQualifiedId(sheet)} classNames='contents'>
35
+ <SheetContainer space={space} sheet={sheet} role='article' ignoreAttention />
36
+ </AttendableContainer>
37
+ );
48
38
  };
49
39
 
50
40
  export const Spec = () => {
@@ -56,14 +46,14 @@ export const Spec = () => {
56
46
  }
57
47
 
58
48
  return (
59
- <IntentProvider value={storybookIntentValue}>
49
+ <AttendableContainer id={fullyQualifiedId(sheet)} classNames='contents'>
60
50
  <div role='none' className='grid grid-rows-[66%_33%] grid-cols-1'>
61
51
  <SheetContainer space={space} sheet={sheet} role='article' ignoreAttention />
62
52
  <div role='none' data-testid='grid.range-list'>
63
53
  <RangeList sheet={sheet} />
64
54
  </div>
65
55
  </div>
66
- </IntentProvider>
56
+ </AttendableContainer>
67
57
  );
68
58
  };
69
59
 
@@ -79,6 +69,22 @@ const meta: Meta = {
79
69
  tooltips: true,
80
70
  classNames: 'grid',
81
71
  }),
72
+ withAttention,
73
+ // TODO(wittjosiah): Consider whether we should refactor component so story doesn't need to depend on intents.
74
+ withPluginManager({
75
+ plugins: [IntentPlugin()],
76
+ capabilities: [
77
+ contributes(
78
+ Capabilities.IntentResolver,
79
+ createResolver({
80
+ intent: SheetAction.DropAxis,
81
+ resolve: ({ model, axis, axisIndex }) => {
82
+ model[axis === 'col' ? 'dropColumn' : 'dropRow'](axisIndex);
83
+ },
84
+ }),
85
+ ),
86
+ ],
87
+ }),
82
88
  ],
83
89
  parameters: { translations },
84
90
  };
@@ -4,7 +4,7 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import { type Space } from '@dxos/react-client/echo';
7
+ import { fullyQualifiedId, type Space } from '@dxos/react-client/echo';
8
8
  import { StackItem } from '@dxos/react-ui-stack';
9
9
 
10
10
  import { type SheetType } from '../../types';
@@ -12,7 +12,7 @@ import { useComputeGraph } from '../ComputeGraph';
12
12
  import { FunctionEditor } from '../FunctionEditor';
13
13
  import { GridSheet } from '../GridSheet';
14
14
  import { SheetProvider } from '../SheetContext';
15
- import { Toolbar } from '../Toolbar';
15
+ import { SheetToolbar } from '../SheetToolbar';
16
16
 
17
17
  export const SheetContainer = ({
18
18
  space,
@@ -30,12 +30,7 @@ export const SheetContainer = ({
30
30
  return graph ? (
31
31
  <SheetProvider sheet={sheet} graph={graph} ignoreAttention={ignoreAttention}>
32
32
  <StackItem.Content toolbar statusbar {...(role === 'section' && { classNames: 'aspect-video' })}>
33
- <Toolbar.Root role={role}>
34
- <Toolbar.Styles />
35
- <Toolbar.Alignment />
36
- <Toolbar.Separator />
37
- <Toolbar.Actions />
38
- </Toolbar.Root>
33
+ <SheetToolbar attendableId={fullyQualifiedId(sheet)} />
39
34
  <GridSheet />
40
35
  <FunctionEditor />
41
36
  </StackItem.Content>
@@ -10,22 +10,18 @@ import React from 'react';
10
10
  import { textBlockWidth } from '@dxos/react-ui-theme';
11
11
  import { withLayout, withTheme } from '@dxos/storybook-utils';
12
12
 
13
- import { Toolbar } from './Toolbar';
13
+ import { SheetToolbar } from './SheetToolbar';
14
14
  import translations from '../../translations';
15
15
 
16
16
  const DefaultStory = () => {
17
- return (
18
- <Toolbar.Root classNames={textBlockWidth}>
19
- <Toolbar.Alignment />
20
- </Toolbar.Root>
21
- );
17
+ return <SheetToolbar classNames={textBlockWidth} />;
22
18
  };
23
19
 
24
20
  export const Default = {};
25
21
 
26
- const meta: Meta<typeof Toolbar.Root> = {
22
+ const meta: Meta = {
27
23
  title: 'plugins/plugin-sheet/Toolbar',
28
- component: Toolbar.Root,
24
+ component: SheetToolbar,
29
25
  render: DefaultStory,
30
26
  decorators: [withTheme, withLayout({ tooltips: true })],
31
27
  parameters: { translations, layout: 'fullscreen' },
@@ -0,0 +1,48 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { type PropsWithChildren, useCallback } from 'react';
6
+
7
+ import { type ThemedClassName } from '@dxos/react-ui';
8
+ import { createGapSeparator, MenuProvider, ToolbarMenu, useMenuActions } from '@dxos/react-ui-menu';
9
+
10
+ import { createAlign, useAlignState } from './align';
11
+ import { createComment, useCommentState } from './comment';
12
+ import { createStyle, useStyleState } from './style';
13
+ import { useToolbarAction } from './useToolbarAction';
14
+ import { type ToolbarState, useToolbarState } from './useToolbarState';
15
+
16
+ //
17
+ // Root
18
+ //
19
+
20
+ export type SheetToolbarProps = ThemedClassName<PropsWithChildren<{ attendableId?: string }>>;
21
+
22
+ const createToolbarActions = (state: ToolbarState) => {
23
+ const align = createAlign(state);
24
+ const style = createStyle(state);
25
+ const gap = createGapSeparator();
26
+ const comment = createComment(state);
27
+ return {
28
+ nodes: [...align.nodes, ...style.nodes, ...gap.nodes, ...comment.nodes],
29
+ edges: [...align.edges, ...style.edges, ...gap.edges, ...comment.edges],
30
+ };
31
+ };
32
+
33
+ export const SheetToolbar = ({ attendableId, classNames }: SheetToolbarProps) => {
34
+ const state = useToolbarState({});
35
+ useAlignState(state);
36
+ useStyleState(state);
37
+ useCommentState(state);
38
+
39
+ const actionsCreator = useCallback(() => createToolbarActions(state), [state]);
40
+ const menu = useMenuActions(actionsCreator);
41
+ const handleAction = useToolbarAction(state);
42
+
43
+ return (
44
+ <MenuProvider {...menu} attendableId={attendableId} onAction={handleAction}>
45
+ <ToolbarMenu classNames={classNames} />
46
+ </MenuProvider>
47
+ );
48
+ };
@@ -0,0 +1,68 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { useEffect } from 'react';
6
+
7
+ import { inRange } from '@dxos/compute';
8
+ import { createMenuAction, createMenuItemGroup, type ToolbarMenuActionGroupProperties } from '@dxos/react-ui-menu';
9
+
10
+ import { SHEET_PLUGIN } from '../../meta';
11
+ import { type AlignKey, alignKey, type AlignValue, rangeFromIndex } from '../../types';
12
+ import { useSheetContext } from '../SheetContext';
13
+
14
+ export type AlignAction = { key: AlignKey; value: AlignValue };
15
+
16
+ export type AlignState = { [alignKey]: AlignValue | undefined };
17
+
18
+ const aligns: Record<AlignValue, string> = {
19
+ start: 'ph--text-align-left--regular',
20
+ center: 'ph--text-align-center--regular',
21
+ end: 'ph--text-align-right--regular',
22
+ };
23
+
24
+ export const useAlignState = (state: Partial<AlignState>) => {
25
+ const { cursor, model } = useSheetContext();
26
+ useEffect(() => {
27
+ // TODO(thure): Can this O(n) call be memoized?
28
+ state[alignKey] = (
29
+ cursor
30
+ ? model.sheet.ranges?.findLast(
31
+ ({ range, key }) => key === alignKey && inRange(rangeFromIndex(model.sheet, range), cursor),
32
+ )?.value
33
+ : undefined
34
+ ) as AlignValue | undefined;
35
+ }, [cursor, model.sheet]);
36
+ };
37
+
38
+ const createAlignGroupAction = (value?: AlignValue) =>
39
+ createMenuItemGroup('align', {
40
+ label: ['align label', { ns: SHEET_PLUGIN }],
41
+ variant: 'toggleGroup',
42
+ selectCardinality: 'single',
43
+ value: `${alignKey}--${value}`,
44
+ } as ToolbarMenuActionGroupProperties);
45
+
46
+ const createAlignActions = (value?: AlignValue) =>
47
+ Object.entries(aligns).map(([alignValue, icon]) => {
48
+ return createMenuAction<AlignAction>(`${alignKey}--${alignValue}`, {
49
+ key: alignKey,
50
+ value: alignValue as AlignValue,
51
+ checked: value === alignValue,
52
+ label: [`range value ${alignValue} label`, { ns: SHEET_PLUGIN }],
53
+ icon,
54
+ testId: `grid.toolbar.${alignKey}.${alignValue}`,
55
+ });
56
+ });
57
+
58
+ export const createAlign = ({ [alignKey]: alignValue }: Partial<AlignState>) => {
59
+ const alignGroup = createAlignGroupAction(alignValue);
60
+ const alignActions = createAlignActions(alignValue);
61
+ return {
62
+ nodes: [alignGroup, ...alignActions],
63
+ edges: [
64
+ { source: 'root', target: 'align' },
65
+ ...alignActions.map(({ id }) => ({ source: alignGroup.id, target: id })),
66
+ ],
67
+ };
68
+ };