@dxos/app-framework 0.7.4 → 0.7.5-main.9cb18ac

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 (128) hide show
  1. package/dist/lib/browser/chunk-QG25ZU2N.mjs +320 -0
  2. package/dist/lib/browser/chunk-QG25ZU2N.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-SPDTXTOV.mjs +163 -0
  4. package/dist/lib/browser/chunk-SPDTXTOV.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-653Y45CL.mjs → chunk-WBOXEHBE.mjs} +12 -2
  6. package/dist/lib/browser/chunk-WBOXEHBE.mjs.map +7 -0
  7. package/dist/lib/browser/index.mjs +224 -109
  8. package/dist/lib/browser/index.mjs.map +4 -4
  9. package/dist/lib/browser/meta.json +1 -1
  10. package/dist/lib/browser/{plugin-intent-LU4KL2RO.mjs → plugin-intent-T7Y3MJ5C.mjs} +14 -4
  11. package/dist/lib/browser/{plugin-settings-OM3G2QFY.mjs → plugin-settings-5U2L2NRU.mjs} +6 -2
  12. package/dist/lib/browser/{plugin-surface-LECZMKSQ.mjs → plugin-surface-OKPF3EQI.mjs} +4 -4
  13. package/dist/lib/node/{chunk-SOVLKUWI.cjs → chunk-BW3RNEVI.cjs} +51 -102
  14. package/dist/lib/node/chunk-BW3RNEVI.cjs.map +7 -0
  15. package/dist/lib/node/{chunk-JZ2JVKRY.cjs → chunk-FCMHRU3M.cjs} +17 -5
  16. package/dist/lib/node/chunk-FCMHRU3M.cjs.map +7 -0
  17. package/dist/lib/node/chunk-VWHAALIN.cjs +344 -0
  18. package/dist/lib/node/chunk-VWHAALIN.cjs.map +7 -0
  19. package/dist/lib/node/index.cjs +232 -114
  20. package/dist/lib/node/index.cjs.map +4 -4
  21. package/dist/lib/node/meta.json +1 -1
  22. package/dist/lib/node/plugin-intent-F3TQZIUR.cjs +53 -0
  23. package/dist/lib/node/plugin-intent-F3TQZIUR.cjs.map +7 -0
  24. package/dist/lib/node/{plugin-settings-OZ6IKAE5.cjs → plugin-settings-W6UHMH5M.cjs} +12 -8
  25. package/dist/lib/node/plugin-settings-W6UHMH5M.cjs.map +7 -0
  26. package/dist/lib/node/{plugin-surface-YWDRXQTD.cjs → plugin-surface-CCSIONYW.cjs} +15 -15
  27. package/dist/lib/node/plugin-surface-CCSIONYW.cjs.map +7 -0
  28. package/dist/lib/node-esm/{chunk-YNU7FTGJ.mjs → chunk-3T5UIJY3.mjs} +12 -2
  29. package/dist/lib/node-esm/chunk-3T5UIJY3.mjs.map +7 -0
  30. package/dist/lib/node-esm/chunk-4GX7V5ZE.mjs +164 -0
  31. package/dist/lib/node-esm/chunk-4GX7V5ZE.mjs.map +7 -0
  32. package/dist/lib/node-esm/chunk-CFOUYXQ6.mjs +321 -0
  33. package/dist/lib/node-esm/chunk-CFOUYXQ6.mjs.map +7 -0
  34. package/dist/lib/node-esm/index.mjs +224 -109
  35. package/dist/lib/node-esm/index.mjs.map +4 -4
  36. package/dist/lib/node-esm/meta.json +1 -1
  37. package/dist/lib/node-esm/{plugin-intent-V7ER24Y6.mjs → plugin-intent-W2HQC6LC.mjs} +14 -4
  38. package/dist/lib/node-esm/{plugin-settings-37UVWF2V.mjs → plugin-settings-H5RHNFVC.mjs} +6 -2
  39. package/dist/lib/node-esm/{plugin-surface-TEU42XQN.mjs → plugin-surface-V3YET3UL.mjs} +4 -4
  40. package/dist/types/src/plugins/common/layout.d.ts +145 -171
  41. package/dist/types/src/plugins/common/layout.d.ts.map +1 -1
  42. package/dist/types/src/plugins/common/navigation.d.ts +77 -30
  43. package/dist/types/src/plugins/common/navigation.d.ts.map +1 -1
  44. package/dist/types/src/plugins/plugin-host/HostPlugin.d.ts +2 -7
  45. package/dist/types/src/plugins/plugin-host/HostPlugin.d.ts.map +1 -1
  46. package/dist/types/src/plugins/plugin-host/index.d.ts +2 -0
  47. package/dist/types/src/plugins/plugin-host/index.d.ts.map +1 -1
  48. package/dist/types/src/plugins/plugin-host/plugin.d.ts +7 -1
  49. package/dist/types/src/plugins/plugin-host/plugin.d.ts.map +1 -1
  50. package/dist/types/src/plugins/plugin-intent/IntentContext.d.ts +7 -20
  51. package/dist/types/src/plugins/plugin-intent/IntentContext.d.ts.map +1 -1
  52. package/dist/types/src/plugins/plugin-intent/IntentPlugin.d.ts.map +1 -1
  53. package/dist/types/src/plugins/plugin-intent/index.d.ts +1 -0
  54. package/dist/types/src/plugins/plugin-intent/index.d.ts.map +1 -1
  55. package/dist/types/src/plugins/plugin-intent/intent-dispatcher.d.ts +107 -0
  56. package/dist/types/src/plugins/plugin-intent/intent-dispatcher.d.ts.map +1 -0
  57. package/dist/types/src/plugins/plugin-intent/intent-dispatcher.test.d.ts +2 -0
  58. package/dist/types/src/plugins/plugin-intent/intent-dispatcher.test.d.ts.map +1 -0
  59. package/dist/types/src/plugins/plugin-intent/intent.d.ts +65 -58
  60. package/dist/types/src/plugins/plugin-intent/intent.d.ts.map +1 -1
  61. package/dist/types/src/plugins/plugin-intent/meta.d.ts +1 -0
  62. package/dist/types/src/plugins/plugin-intent/meta.d.ts.map +1 -1
  63. package/dist/types/src/plugins/plugin-intent/provides.d.ts +6 -10
  64. package/dist/types/src/plugins/plugin-intent/provides.d.ts.map +1 -1
  65. package/dist/types/src/plugins/plugin-settings/provides.d.ts +15 -2
  66. package/dist/types/src/plugins/plugin-settings/provides.d.ts.map +1 -1
  67. package/dist/types/src/plugins/plugin-surface/Surface.d.ts +2 -57
  68. package/dist/types/src/plugins/plugin-surface/Surface.d.ts.map +1 -1
  69. package/dist/types/src/plugins/plugin-surface/SurfaceContext.d.ts +85 -0
  70. package/dist/types/src/plugins/plugin-surface/SurfaceContext.d.ts.map +1 -0
  71. package/dist/types/src/plugins/plugin-surface/SurfacePlugin.d.ts.map +1 -1
  72. package/dist/types/src/plugins/plugin-surface/index.d.ts +1 -1
  73. package/dist/types/src/plugins/plugin-surface/index.d.ts.map +1 -1
  74. package/dist/types/src/plugins/plugin-surface/provides.d.ts +5 -4
  75. package/dist/types/src/plugins/plugin-surface/provides.d.ts.map +1 -1
  76. package/dist/types/tsconfig.tsbuildinfo +1 -0
  77. package/package.json +14 -12
  78. package/src/plugins/common/layout.ts +125 -107
  79. package/src/plugins/common/navigation.ts +59 -30
  80. package/src/plugins/plugin-host/HostPlugin.tsx +2 -10
  81. package/src/plugins/plugin-host/PluginContainer.tsx +1 -1
  82. package/src/plugins/plugin-host/index.ts +4 -0
  83. package/src/plugins/plugin-host/plugin.ts +8 -1
  84. package/src/plugins/plugin-intent/IntentContext.tsx +13 -36
  85. package/src/plugins/plugin-intent/IntentPlugin.tsx +44 -120
  86. package/src/plugins/plugin-intent/index.ts +1 -0
  87. package/src/plugins/plugin-intent/intent-dispatcher.test.ts +279 -0
  88. package/src/plugins/plugin-intent/intent-dispatcher.ts +285 -0
  89. package/src/plugins/plugin-intent/intent.ts +126 -65
  90. package/src/plugins/plugin-intent/meta.ts +3 -1
  91. package/src/plugins/plugin-intent/provides.ts +8 -20
  92. package/src/plugins/plugin-settings/provides.ts +10 -5
  93. package/src/plugins/plugin-surface/Surface.tsx +25 -158
  94. package/src/plugins/plugin-surface/SurfaceContext.ts +112 -0
  95. package/src/plugins/plugin-surface/SurfacePlugin.tsx +19 -7
  96. package/src/plugins/plugin-surface/index.ts +1 -1
  97. package/src/plugins/plugin-surface/provides.ts +8 -7
  98. package/tsconfig.json +38 -1
  99. package/dist/lib/browser/chunk-653Y45CL.mjs.map +0 -7
  100. package/dist/lib/browser/chunk-FRXJ25VI.mjs +0 -214
  101. package/dist/lib/browser/chunk-FRXJ25VI.mjs.map +0 -7
  102. package/dist/lib/browser/chunk-YXM35XRE.mjs +0 -213
  103. package/dist/lib/browser/chunk-YXM35XRE.mjs.map +0 -7
  104. package/dist/lib/node/chunk-JZ2JVKRY.cjs.map +0 -7
  105. package/dist/lib/node/chunk-QSVP5HOW.cjs +0 -238
  106. package/dist/lib/node/chunk-QSVP5HOW.cjs.map +0 -7
  107. package/dist/lib/node/chunk-SOVLKUWI.cjs.map +0 -7
  108. package/dist/lib/node/plugin-intent-FVFR2LKB.cjs +0 -43
  109. package/dist/lib/node/plugin-intent-FVFR2LKB.cjs.map +0 -7
  110. package/dist/lib/node/plugin-settings-OZ6IKAE5.cjs.map +0 -7
  111. package/dist/lib/node/plugin-surface-YWDRXQTD.cjs.map +0 -7
  112. package/dist/lib/node-esm/chunk-2R4GVK7O.mjs +0 -215
  113. package/dist/lib/node-esm/chunk-2R4GVK7O.mjs.map +0 -7
  114. package/dist/lib/node-esm/chunk-YFMFQBB4.mjs +0 -214
  115. package/dist/lib/node-esm/chunk-YFMFQBB4.mjs.map +0 -7
  116. package/dist/lib/node-esm/chunk-YNU7FTGJ.mjs.map +0 -7
  117. package/dist/types/src/plugins/plugin-intent/helpers.d.ts +0 -6
  118. package/dist/types/src/plugins/plugin-intent/helpers.d.ts.map +0 -1
  119. package/dist/types/src/plugins/plugin-surface/SurfaceRootContext.d.ts +0 -39
  120. package/dist/types/src/plugins/plugin-surface/SurfaceRootContext.d.ts.map +0 -1
  121. package/src/plugins/plugin-intent/helpers.ts +0 -11
  122. package/src/plugins/plugin-surface/SurfaceRootContext.tsx +0 -60
  123. /package/dist/lib/browser/{plugin-intent-LU4KL2RO.mjs.map → plugin-intent-T7Y3MJ5C.mjs.map} +0 -0
  124. /package/dist/lib/browser/{plugin-settings-OM3G2QFY.mjs.map → plugin-settings-5U2L2NRU.mjs.map} +0 -0
  125. /package/dist/lib/browser/{plugin-surface-LECZMKSQ.mjs.map → plugin-surface-OKPF3EQI.mjs.map} +0 -0
  126. /package/dist/lib/node-esm/{plugin-intent-V7ER24Y6.mjs.map → plugin-intent-W2HQC6LC.mjs.map} +0 -0
  127. /package/dist/lib/node-esm/{plugin-settings-37UVWF2V.mjs.map → plugin-settings-H5RHNFVC.mjs.map} +0 -0
  128. /package/dist/lib/node-esm/{plugin-surface-TEU42XQN.mjs.map → plugin-surface-V3YET3UL.mjs.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"provides.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/plugin-surface/provides.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACtF,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAG7C,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE;QACP;;WAEG;QACH,SAAS,EAAE,gBAAgB,CAAC;KAC7B,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,kBAAkB,CAAC;CAC7B,CAAC;AAEF,eAAO,MAAM,sBAAsB,YAAa,MAAM,8CACkD,CAAC;AAEzG,eAAO,MAAM,kBAAkB,YAAa,MAAM,wCAC+C,CAAC"}
1
+ {"version":3,"file":"provides.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/plugin-surface/provides.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACpF,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE/D,MAAM,MAAM,kBAAkB,GAAG,iBAAiB,GAAG,iBAAiB,EAAE,GAAG,kBAAkB,EAAE,CAAC;AAEhG,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE;QACP;;WAEG;QACH,WAAW,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,kBAAkB,CAAC;KAC3D,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,mBAAmB,CAAC;CAC9B,CAAC;AAEF,eAAO,MAAM,sBAAsB,YAAa,MAAM,8CACgD,CAAC;AAEvG,eAAO,MAAM,kBAAkB,YAAa,MAAM,wCACiD,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":"5.7.2"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/app-framework",
3
- "version": "0.7.4",
3
+ "version": "0.7.5-main.9cb18ac",
4
4
  "description": "A framework for building applications from composible plugins.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -22,18 +22,20 @@
22
22
  "@effect/schema": "^0.75.5",
23
23
  "@phosphor-icons/react": "^2.1.5",
24
24
  "@preact/signals-core": "^1.6.0",
25
+ "effect": "^3.12.1",
25
26
  "zod": "^3.22.4",
26
- "@dxos/app-graph": "0.7.4",
27
- "@dxos/client-protocol": "0.7.4",
28
- "@dxos/async": "0.7.4",
29
- "@dxos/context": "0.7.4",
30
- "@dxos/debug": "0.7.4",
31
- "@dxos/echo-schema": "0.7.4",
32
- "@dxos/invariant": "0.7.4",
33
- "@dxos/live-object": "0.7.4",
34
- "@dxos/local-storage": "0.7.4",
35
- "@dxos/log": "0.7.4",
36
- "@dxos/util": "0.7.4"
27
+ "@dxos/app-graph": "0.7.5-main.9cb18ac",
28
+ "@dxos/async": "0.7.5-main.9cb18ac",
29
+ "@dxos/client-protocol": "0.7.5-main.9cb18ac",
30
+ "@dxos/context": "0.7.5-main.9cb18ac",
31
+ "@dxos/debug": "0.7.5-main.9cb18ac",
32
+ "@dxos/invariant": "0.7.5-main.9cb18ac",
33
+ "@dxos/echo-schema": "0.7.5-main.9cb18ac",
34
+ "@dxos/live-object": "0.7.5-main.9cb18ac",
35
+ "@dxos/local-storage": "0.7.5-main.9cb18ac",
36
+ "@dxos/react-hooks": "0.7.5-main.9cb18ac",
37
+ "@dxos/log": "0.7.5-main.9cb18ac",
38
+ "@dxos/util": "0.7.5-main.9cb18ac"
37
39
  },
38
40
  "devDependencies": {
39
41
  "@types/react": "~18.2.0",
@@ -2,29 +2,29 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { z } from 'zod';
5
+ import { S } from '@dxos/echo-schema';
6
6
 
7
7
  import { type Plugin } from '../plugin-host';
8
- import { type IntentData } from '../plugin-intent';
8
+ import { Label } from '../plugin-intent';
9
9
 
10
10
  //
11
11
  // Provides
12
12
  //
13
13
 
14
- export const Toast = z.object({
15
- id: z.string(),
16
- title: z.string().optional(),
17
- description: z.string().optional(),
18
- // TODO(wittjosiah): `icon` should be string to be parsed by an `Icon` component.
19
- icon: z.any().optional(),
20
- duration: z.number().optional(),
21
- closeLabel: z.string().optional(),
22
- actionLabel: z.string().optional(),
23
- actionAlt: z.string().optional(),
24
- onAction: z.function().optional(),
14
+ export const Toast = S.Struct({
15
+ id: S.String,
16
+ title: S.optional(Label),
17
+ description: S.optional(Label),
18
+ icon: S.optional(S.String),
19
+ duration: S.optional(S.Number),
20
+ closeLabel: S.optional(Label),
21
+ actionLabel: S.optional(Label),
22
+ actionAlt: S.optional(Label),
23
+ // TODO(wittjosiah): Make class with customizable method?
24
+ onAction: S.optional(S.Any),
25
25
  });
26
26
 
27
- export type Toast = z.infer<typeof Toast>;
27
+ export type Toast = S.Schema.Type<typeof Toast>;
28
28
 
29
29
  /**
30
30
  * Basic state provided by a layout plugin.
@@ -34,43 +34,47 @@ export type Toast = z.infer<typeof Toast>;
34
34
  * For other landmarks, such as toasts, rendering them in the layout prevents them from unmounting when navigating.
35
35
  */
36
36
 
37
- const LayoutMode = z.union([z.literal('deck'), z.literal('solo'), z.literal('fullscreen')]);
38
- export const isLayoutMode = (value: any): value is LayoutMode => LayoutMode.safeParse(value).success;
39
- export type LayoutMode = z.infer<typeof LayoutMode>;
40
-
41
- // TODO(wittjosiah): Replace Zod w/ Effect Schema to align with ECHO.
42
- export const Layout = z.object({
43
- layoutMode: z.union([z.literal('deck'), z.literal('solo'), z.literal('fullscreen')]),
44
-
45
- sidebarOpen: z.boolean(),
46
- complementarySidebarOpen: z.boolean(),
47
- /**
48
- * @deprecated
49
- */
50
- complementarySidebarContent: z
51
- .any()
52
- .optional()
53
- .describe('DEPRECATED. Data to be passed to the complementary sidebar Surface.'),
54
-
55
- dialogOpen: z.boolean(),
56
- dialogContent: z.any().optional().describe('Data to be passed to the dialog Surface.'),
57
- // TODO(wittjosiah): Custom properties?
58
- dialogBlockAlign: z.union([z.literal('start'), z.literal('center')]).optional(),
59
- dialogType: z.union([z.literal('default'), z.literal('alert')]).optional(),
60
-
61
- popoverOpen: z.boolean(),
62
- popoverContent: z.any().optional().describe('Data to be passed to the popover Surface.'),
63
- popoverAnchorId: z.string().optional(),
64
-
65
- toasts: z.array(Toast),
66
-
67
- scrollIntoView: z
68
- .string()
69
- .optional()
70
- .describe('The identifier of a component to scroll into view when it is mounted.'),
71
- });
37
+ const LayoutMode = S.Union(S.Literal('deck'), S.Literal('solo'), S.Literal('fullscreen'));
38
+ export const isLayoutMode = (value: any): value is LayoutMode => S.is(LayoutMode)(value);
39
+ export type LayoutMode = S.Schema.Type<typeof LayoutMode>;
40
+
41
+ export const Layout = S.mutable(
42
+ S.Struct({
43
+ layoutMode: LayoutMode,
44
+
45
+ sidebarOpen: S.Boolean,
46
+ complementarySidebarOpen: S.Boolean,
47
+ /**
48
+ * @deprecated Data to be passed to the complementary sidebar Surface.
49
+ */
50
+ complementarySidebarContent: S.optional(S.Any),
72
51
 
73
- export type Layout = z.infer<typeof Layout>;
52
+ dialogOpen: S.Boolean,
53
+ /**
54
+ * Data to be passed to the dialog Surface.
55
+ */
56
+ dialogContent: S.optional(S.Any),
57
+ // TODO(wittjosiah): Custom properties?
58
+ dialogBlockAlign: S.optional(S.Literal('start', 'center')),
59
+ dialogType: S.optional(S.Literal('default', 'alert')),
60
+
61
+ popoverOpen: S.Boolean,
62
+ /**
63
+ * Data to be passed to the popover Surface.
64
+ */
65
+ popoverContent: S.optional(S.Any),
66
+ popoverAnchorId: S.optional(S.String),
67
+
68
+ toasts: S.mutable(S.Array(Toast)),
69
+
70
+ /**
71
+ * The identifier of a component to scroll into view when it is mounted.
72
+ */
73
+ scrollIntoView: S.optional(S.String),
74
+ }),
75
+ );
76
+
77
+ export type Layout = S.Schema.Type<typeof Layout>;
74
78
 
75
79
  /**
76
80
  * Provides for a plugin that can manage the app layout.
@@ -83,7 +87,7 @@ export type LayoutProvides = {
83
87
  * Type guard for layout plugins.
84
88
  */
85
89
  export const parseLayoutPlugin = (plugin: Plugin) => {
86
- const { success } = Layout.safeParse((plugin.provides as any).layout);
90
+ const success = S.is(Layout)((plugin.provides as any).layout);
87
91
  return success ? (plugin as Plugin<LayoutProvides>) : undefined;
88
92
  };
89
93
 
@@ -91,65 +95,79 @@ export const parseLayoutPlugin = (plugin: Plugin) => {
91
95
  // Intents
92
96
  //
93
97
 
94
- const LAYOUT_PLUGIN = 'dxos.org/plugin/layout';
95
-
96
- const LAYOUT_ACTION = `${LAYOUT_PLUGIN}/action`;
97
-
98
- export enum LayoutAction {
99
- SET_LAYOUT = `${LAYOUT_ACTION}/set-layout`,
100
- SET_LAYOUT_MODE = `${LAYOUT_ACTION}/set-layout-mode`,
101
- SCROLL_INTO_VIEW = `${LAYOUT_ACTION}/scroll-into-view`,
102
- UPDATE_PLANK_SIZE = `${LAYOUT_ACTION}/update-plank-size`,
103
- }
98
+ export const LAYOUT_PLUGIN = 'dxos.org/plugin/layout';
99
+ export const LAYOUT_ACTION = `${LAYOUT_PLUGIN}/action`;
104
100
 
105
101
  /**
106
102
  * Expected payload for layout actions.
107
103
  */
108
104
  export namespace LayoutAction {
109
- export type SetLayoutMode = IntentData<{
110
- layoutMode?: LayoutMode;
111
- revert?: boolean;
112
- }>;
113
-
114
- export type SetLayout = IntentData<{
115
- /**
116
- * Element to set the state of.
117
- */
118
- element: 'fullscreen' | 'sidebar' | 'complementary' | 'dialog' | 'popover' | 'toast';
119
-
120
- /**
121
- * Whether the element is on or off.
122
- *
123
- * If omitted, the element's state will be toggled or set based on other provided data.
124
- * For example, if `component` is provided, the state will be set to `true`.
125
- */
126
- state?: boolean;
127
-
128
- /**
129
- * Component to render in the dialog or popover.
130
- */
131
- component?: string;
132
-
133
- /**
134
- * Data to be passed to the dialog or popover Surface.
135
- */
136
- subject?: any;
137
-
138
- /**
139
- * Anchor ID for the popover.
140
- */
141
- anchorId?: string;
142
-
143
- // TODO(wittjosiah): Custom properties?
144
-
145
- /**
146
- * Block alignment for the dialog.
147
- */
148
- dialogBlockAlign?: 'start' | 'center';
149
-
150
- /**
151
- * Type of dialog.
152
- */
153
- dialogType?: 'default' | 'alert';
154
- }>;
105
+ export class SetLayout extends S.TaggedClass<SetLayout>()(`${LAYOUT_ACTION}/set-layout`, {
106
+ input: S.Struct({
107
+ /**
108
+ * Element to set the state of.
109
+ */
110
+ element: S.Literal('fullscreen', 'sidebar', 'complementary', 'dialog', 'popover', 'toast'),
111
+
112
+ /**
113
+ * Whether the element is on or off.
114
+ *
115
+ * If omitted, the element's state will be toggled or set based on other provided data.
116
+ * For example, if `component` is provided, the state will be set to `true`.
117
+ */
118
+ state: S.optional(S.Boolean),
119
+
120
+ /**
121
+ * Component to render in the dialog or popover.
122
+ */
123
+ component: S.optional(S.String),
124
+
125
+ /**
126
+ * Data to be passed to the dialog or popover Surface.
127
+ */
128
+ subject: S.optional(S.Any),
129
+
130
+ /**
131
+ * Anchor ID for the popover.
132
+ */
133
+ anchorId: S.optional(S.String),
134
+
135
+ // TODO(wittjosiah): Custom properties?
136
+
137
+ /**
138
+ * Block alignment for the dialog.
139
+ */
140
+ dialogBlockAlign: S.optional(S.Literal('start', 'center')),
141
+
142
+ /**
143
+ * Type of dialog.
144
+ */
145
+ dialogType: S.optional(S.Literal('default', 'alert')),
146
+ }),
147
+ output: S.Void,
148
+ }) {}
149
+
150
+ // TODO(wittjosiah): Do all these need to be separate actions?
151
+
152
+ export class SetLayoutMode extends S.TaggedClass<SetLayoutMode>()(`${LAYOUT_ACTION}/set-layout-mode`, {
153
+ input: S.Union(
154
+ S.Struct({
155
+ layoutMode: LayoutMode,
156
+ }),
157
+ S.Struct({
158
+ revert: S.Literal(true),
159
+ }),
160
+ ),
161
+ output: S.Void,
162
+ }) {}
163
+
164
+ export class ScrollIntoView extends S.TaggedClass<ScrollIntoView>()(`${LAYOUT_ACTION}/scroll-into-view`, {
165
+ input: S.Struct({
166
+ id: S.optional(S.String),
167
+ // TODO(wittjosiah): Factor out to thread scroll into view action?
168
+ cursor: S.optional(S.String),
169
+ ref: S.optional(S.String),
170
+ }),
171
+ output: S.Void,
172
+ }) {}
155
173
  }
@@ -3,12 +3,10 @@
3
3
  //
4
4
 
5
5
  import { Schema as S } from '@effect/schema';
6
- import { z } from 'zod';
7
6
 
8
7
  import { pick } from '@dxos/util';
9
8
 
10
9
  import { type Plugin } from '../plugin-host';
11
- import { type IntentData } from '../plugin-intent';
12
10
 
13
11
  // NOTE(thure): These are chosen from RFC 1738’s `safe` characters: http://www.faqs.org/rfcs/rfc1738.html
14
12
  export const SLUG_LIST_SEPARATOR = '+';
@@ -39,7 +37,14 @@ export type LayoutParts = S.Schema.Type<typeof LayoutPartsSchema>;
39
37
  const LayoutCoordinateSchema = S.mutable(S.Struct({ part: LayoutPartSchema, entryId: S.String }));
40
38
  export type LayoutCoordinate = S.Schema.Type<typeof LayoutCoordinateSchema>;
41
39
 
42
- const PartAdjustmentSchema = S.Union(S.Literal('increment-start'), S.Literal('increment-end'), S.Literal('solo'));
40
+ const PartAdjustmentSchema = S.Union(
41
+ S.Literal('increment-start'),
42
+ S.Literal('increment-end'),
43
+ S.Literal('pin-start'),
44
+ S.Literal('pin-end'),
45
+ S.Literal('close'),
46
+ S.Literal('solo'),
47
+ );
43
48
  export type PartAdjustment = S.Schema.Type<typeof PartAdjustmentSchema>;
44
49
 
45
50
  const LayoutAdjustmentSchema = S.mutable(
@@ -48,8 +53,8 @@ const LayoutAdjustmentSchema = S.mutable(
48
53
  export type LayoutAdjustment = S.Schema.Type<typeof LayoutAdjustmentSchema>;
49
54
 
50
55
  /** @deprecated */
51
- export const ActiveParts = z.record(z.string(), z.union([z.string(), z.array(z.string())]));
52
- export type ActiveParts = z.infer<typeof ActiveParts>;
56
+ export const ActiveParts = S.Record({ key: S.String, value: S.Union(S.String, S.mutable(S.Array(S.String))) });
57
+ export type ActiveParts = S.Schema.Type<typeof ActiveParts>;
53
58
 
54
59
  // TODO(burdon): Where should this go?
55
60
  export type LayoutContainerProps<T> = T & { role?: string; coordinate?: LayoutCoordinate };
@@ -135,51 +140,75 @@ export const partLength = (layout: LayoutParts | undefined, part: LayoutPart | u
135
140
  // Intents
136
141
  //
137
142
 
138
- const NAVIGATION_PLUGIN = 'dxos.org/plugin/navigation';
139
-
140
- const NAVIGATION_ACTION = `${NAVIGATION_PLUGIN}/action`;
141
-
142
- export enum NavigationAction {
143
- OPEN = `${NAVIGATION_ACTION}/open`,
144
- ADD_TO_ACTIVE = `${NAVIGATION_ACTION}/add-to-active`,
145
- SET = `${NAVIGATION_ACTION}/set`,
146
- ADJUST = `${NAVIGATION_ACTION}/adjust`,
147
- CLOSE = `${NAVIGATION_ACTION}/close`,
148
- EXPOSE = `${NAVIGATION_ACTION}/expose`,
149
- }
143
+ export const NAVIGATION_PLUGIN = 'dxos.org/plugin/navigation';
144
+ export const NAVIGATION_ACTION = `${NAVIGATION_PLUGIN}/action`;
150
145
 
151
146
  /**
152
147
  * Expected payload for navigation actions.
153
148
  */
149
+ // TODO(wittjosiah): These seem to be too deck-specific.
154
150
  export namespace NavigationAction {
155
151
  /**
156
152
  * An additive overlay to apply to `location.active` (i.e. the result is a union of previous active and the argument)
157
153
  */
158
- export type Open = IntentData<{ activeParts: ActiveParts }>;
154
+ export class Open extends S.TaggedClass<Open>()(`${NAVIGATION_ACTION}/open`, {
155
+ input: S.Struct({
156
+ activeParts: ActiveParts,
157
+ noToggle: S.optional(S.Boolean),
158
+ }),
159
+ output: S.Struct({
160
+ open: S.Array(S.String),
161
+ }),
162
+ }) {}
159
163
 
160
164
  /**
161
165
  * Payload for adding an item to the active items.
162
166
  */
163
- export type AddToActive = IntentData<{
164
- part: LayoutPart;
165
- id: string;
166
- scrollIntoView?: boolean;
167
- pivotId?: string;
168
- positioning?: 'start' | 'end';
169
- }>;
167
+ export class AddToActive extends S.TaggedClass<AddToActive>()(`${NAVIGATION_ACTION}/add-to-active`, {
168
+ input: S.Struct({
169
+ id: S.String,
170
+ part: LayoutPartSchema,
171
+ scrollIntoView: S.optional(S.Boolean),
172
+ pivotId: S.optional(S.String),
173
+ positioning: S.optional(S.Literal('start', 'end')),
174
+ }),
175
+ output: S.Void,
176
+ }) {}
170
177
 
171
178
  /**
172
- * A subtractive overlay to apply to `location.active` (i.e. the result is a subtraction from the previous active of the argument)
179
+ * The active parts to directly set, to be used when working with URLs or restoring a specific state.
173
180
  */
174
- export type Close = IntentData<{ activeParts: ActiveParts; noToggle?: boolean }>;
181
+ export class Set extends S.TaggedClass<Set>()(`${NAVIGATION_ACTION}/set`, {
182
+ input: S.Struct({
183
+ activeParts: ActiveParts,
184
+ }),
185
+ output: S.Void,
186
+ }) {}
175
187
 
176
188
  /**
177
- * The active parts to directly set, to be used when working with URLs or restoring a specific state.
189
+ * A subtractive overlay to apply to `location.active` (i.e. the result is a subtraction from the previous active of the argument)
178
190
  */
179
- export type Set = IntentData<{ activeParts: ActiveParts }>;
191
+ export class Close extends S.TaggedClass<Close>()(`${NAVIGATION_ACTION}/close`, {
192
+ input: S.Struct({
193
+ activeParts: ActiveParts,
194
+ noToggle: S.optional(S.Boolean),
195
+ }),
196
+ output: S.Void,
197
+ }) {}
180
198
 
181
199
  /**
182
200
  * An atomic transaction to apply to `location.active`, describing which element to (attempt to) move to which location.
183
201
  */
184
- export type Adjust = IntentData<LayoutAdjustment>;
202
+ export class Adjust extends S.TaggedClass<Adjust>()(`${NAVIGATION_ACTION}/adjust`, {
203
+ input: LayoutAdjustmentSchema,
204
+ output: S.Void,
205
+ }) {}
206
+
207
+ // TODO(wittjosiah): This action seems unrelated to the others.
208
+ export class Expose extends S.TaggedClass<Expose>()(`${NAVIGATION_ACTION}/expose`, {
209
+ input: S.Struct({
210
+ id: S.String,
211
+ }),
212
+ output: S.Void,
213
+ }) {}
185
214
  }
@@ -8,7 +8,7 @@ import { LocalStorageStore } from '@dxos/local-storage';
8
8
 
9
9
  import { PluginContainer } from './PluginContainer';
10
10
  import { type PluginContext, PluginProvider } from './PluginContext';
11
- import { type Plugin, type PluginDefinition, type PluginMeta } from './plugin';
11
+ import { type PluginDefinition, type PluginMeta } from './plugin';
12
12
  import { ErrorBoundary } from '../plugin-surface';
13
13
 
14
14
  export type HostPluginParams = {
@@ -21,13 +21,6 @@ export type HostPluginParams = {
21
21
  placeholder?: ReactNode;
22
22
  };
23
23
 
24
- export type HostPluginProvides = {
25
- plugins: PluginContext;
26
- };
27
-
28
- export const parsePluginHost = (plugin: Plugin) =>
29
- (plugin.provides as HostPluginProvides).plugins ? (plugin as Plugin<HostPluginProvides>) : undefined;
30
-
31
24
  const HOST_PLUGIN = 'dxos.org/plugin/host';
32
25
 
33
26
  /**
@@ -40,7 +33,7 @@ export const HostPlugin = ({
40
33
  defaults = [],
41
34
  fallback = DefaultFallback,
42
35
  placeholder = null,
43
- }: HostPluginParams): PluginDefinition<HostPluginProvides> => {
36
+ }: HostPluginParams): PluginDefinition => {
44
37
  const state = new LocalStorageStore<PluginContext>(HOST_PLUGIN, {
45
38
  ready: false,
46
39
  core,
@@ -67,7 +60,6 @@ export const HostPlugin = ({
67
60
  name: 'Plugin host',
68
61
  },
69
62
  provides: {
70
- plugins: state.values,
71
63
  context: ({ children }) => {
72
64
  return <PluginProvider value={state.values}>{children}</PluginProvider>;
73
65
  },
@@ -49,7 +49,7 @@ export const PluginContainer = ({ plugins: definitions, core, state, placeholder
49
49
  const initialized = plugins.filter((plugin): plugin is Plugin => Boolean(plugin));
50
50
  log('plugins initialized', { plugins: initialized });
51
51
 
52
- await Promise.all(enabled.map((plugin) => plugin.ready?.(initialized)));
52
+ await Promise.all(enabled.map((plugin) => plugin.ready?.({ plugins: initialized })));
53
53
  log('plugins ready', { plugins: initialized });
54
54
 
55
55
  state.plugins = initialized;
@@ -2,7 +2,11 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ import { HostPlugin } from './HostPlugin';
6
+
5
7
  export * from './plugin';
6
8
 
7
9
  export * from './HostPlugin';
8
10
  export * from './PluginContext';
11
+
12
+ export default HostPlugin;
@@ -4,6 +4,13 @@
4
4
 
5
5
  import type { FC, PropsWithChildren } from 'react';
6
6
 
7
+ /**
8
+ * Application context to be provided to plugin callbacks.
9
+ */
10
+ export type HostContext = {
11
+ plugins: Plugin[];
12
+ };
13
+
7
14
  /**
8
15
  * Capabilities provided by a plugin.
9
16
  * The base surface capabilities are always included.
@@ -105,7 +112,7 @@ export type PluginDefinition<TProvides = {}, TInitializeProvides = {}> = Omit<Pl
105
112
  * @param plugins All plugins which successfully initialized.
106
113
  */
107
114
  // TODO(wittjosiah): Rename `ready` to a verb?
108
- ready?: (plugins: Plugin[]) => Promise<void>;
115
+ ready?: (context: HostContext) => Promise<void>;
109
116
 
110
117
  /**
111
118
  * Called when the plugin is unloaded.
@@ -2,48 +2,25 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { type Context, createContext, useContext, type Provider } from 'react';
6
- import { useEffect } from 'react';
5
+ import { type Context, createContext, useContext, type Provider, useEffect } from 'react';
7
6
 
8
- import type { UnsubscribeCallback } from '@dxos/async';
7
+ import { raise } from '@dxos/debug';
8
+ import { pick } from '@dxos/util';
9
9
 
10
- import type { Intent, IntentDispatcher, IntentResolver, IntentResult } from './intent';
10
+ import { type AnyIntentResolver, type IntentContext } from './intent-dispatcher';
11
11
 
12
- export type IntentExecution = {
13
- intent: Intent;
14
- result: IntentResult;
15
- };
16
-
17
- export type IntentContext = {
18
- dispatch: IntentDispatcher;
19
- undo: () => Promise<IntentResult | void>;
20
- history: IntentExecution[][];
21
- registerResolver: (pluginId: string, resolver: IntentResolver) => UnsubscribeCallback;
22
- };
23
-
24
- const IntentContext: Context<IntentContext> = createContext<IntentContext>({
25
- dispatch: async () => ({}),
26
- undo: async () => ({}),
27
- history: [],
28
- registerResolver: () => () => {},
29
- });
30
-
31
- /**
32
- * @deprecated Prefer granular hooks.
33
- */
34
- // TODO(burdon): Remove. Use useIntentDispatcher.
35
- export const useIntent = () => useContext(IntentContext);
12
+ const IntentContext: Context<IntentContext | undefined> = createContext<IntentContext | undefined>(undefined);
36
13
 
37
- export const useIntentDispatcher = (): IntentDispatcher => {
38
- const { dispatch } = useIntent();
39
- return dispatch;
14
+ export const useIntentDispatcher = (): Pick<IntentContext, 'dispatch' | 'dispatchPromise'> => {
15
+ const context = useContext(IntentContext) ?? raise(new Error('IntentContext not found'));
16
+ return pick(context, ['dispatch', 'dispatchPromise']);
40
17
  };
41
18
 
42
- export const useIntentResolver = (plugin: string, resolver: IntentResolver) => {
43
- const { registerResolver } = useIntent();
19
+ export const useIntentResolver = (pluginId: string, resolver: AnyIntentResolver) => {
20
+ const { registerResolver } = useContext(IntentContext) ?? raise(new Error('IntentContext not found'));
44
21
  useEffect(() => {
45
- return registerResolver(plugin, resolver);
46
- }, [plugin, resolver]);
22
+ return registerResolver(pluginId, resolver);
23
+ }, [pluginId, resolver]);
47
24
  };
48
25
 
49
- export const IntentProvider: Provider<IntentContext> = IntentContext.Provider;
26
+ export const IntentProvider: Provider<IntentContext | undefined> = IntentContext.Provider;