@dxos/app-framework 0.6.13 → 0.6.14-main.69511f5

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 (204) hide show
  1. package/dist/lib/browser/chunk-3E7RY3CE.mjs +72 -0
  2. package/dist/lib/browser/chunk-3E7RY3CE.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-653Y45CL.mjs +41 -0
  4. package/dist/lib/browser/chunk-653Y45CL.mjs.map +7 -0
  5. package/dist/lib/browser/{plugin-MM66VRCO.mjs → chunk-CDLQO5K2.mjs} +66 -20
  6. package/dist/lib/browser/chunk-CDLQO5K2.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-EQTQGGE6.mjs +214 -0
  8. package/dist/lib/browser/chunk-EQTQGGE6.mjs.map +7 -0
  9. package/dist/lib/browser/index.mjs +183 -293
  10. package/dist/lib/browser/index.mjs.map +4 -4
  11. package/dist/lib/browser/meta.json +1 -1
  12. package/dist/lib/browser/plugin-intent-Q5KFPKFA.mjs +22 -0
  13. package/dist/lib/browser/plugin-intent-Q5KFPKFA.mjs.map +7 -0
  14. package/dist/lib/browser/plugin-settings-OM3G2QFY.mjs +11 -0
  15. package/dist/lib/browser/plugin-settings-OM3G2QFY.mjs.map +7 -0
  16. package/dist/lib/browser/plugin-surface-ZQXFAL46.mjs +24 -0
  17. package/dist/lib/browser/plugin-surface-ZQXFAL46.mjs.map +7 -0
  18. package/dist/lib/node/chunk-EF67TRWJ.cjs +236 -0
  19. package/dist/lib/node/chunk-EF67TRWJ.cjs.map +7 -0
  20. package/dist/lib/node/chunk-JZ2JVKRY.cjs +58 -0
  21. package/dist/lib/node/chunk-JZ2JVKRY.cjs.map +7 -0
  22. package/dist/lib/node/{chunk-62W6CMGM.cjs → chunk-QBM42OQ6.cjs} +56 -5
  23. package/dist/lib/node/chunk-QBM42OQ6.cjs.map +7 -0
  24. package/dist/lib/node/{plugin-QV7ESETI.cjs → chunk-VOKMWTKO.cjs} +74 -20
  25. package/dist/lib/node/chunk-VOKMWTKO.cjs.map +7 -0
  26. package/dist/lib/node/index.cjs +195 -310
  27. package/dist/lib/node/index.cjs.map +4 -4
  28. package/dist/lib/node/meta.json +1 -1
  29. package/dist/lib/node/plugin-intent-FMC4SDI3.cjs +43 -0
  30. package/dist/lib/node/plugin-intent-FMC4SDI3.cjs.map +7 -0
  31. package/dist/lib/node/plugin-settings-OZ6IKAE5.cjs +32 -0
  32. package/dist/lib/node/plugin-settings-OZ6IKAE5.cjs.map +7 -0
  33. package/dist/lib/node/{chunk-P5GRB4XF.cjs → plugin-surface-B5NHOBSW.cjs} +19 -22
  34. package/dist/lib/node/plugin-surface-B5NHOBSW.cjs.map +7 -0
  35. package/dist/lib/node-esm/chunk-3FCLBEOX.mjs +215 -0
  36. package/dist/lib/node-esm/chunk-3FCLBEOX.mjs.map +7 -0
  37. package/dist/lib/node-esm/chunk-EYCTSFEJ.mjs +74 -0
  38. package/dist/lib/node-esm/chunk-EYCTSFEJ.mjs.map +7 -0
  39. package/dist/lib/node-esm/chunk-MYNXI5VG.mjs +214 -0
  40. package/dist/lib/node-esm/chunk-MYNXI5VG.mjs.map +7 -0
  41. package/dist/lib/node-esm/chunk-YNU7FTGJ.mjs +43 -0
  42. package/dist/lib/node-esm/chunk-YNU7FTGJ.mjs.map +7 -0
  43. package/dist/lib/node-esm/index.mjs +567 -0
  44. package/dist/lib/node-esm/index.mjs.map +7 -0
  45. package/dist/lib/node-esm/meta.json +1 -0
  46. package/dist/lib/node-esm/plugin-intent-KETLP7UL.mjs +23 -0
  47. package/dist/lib/node-esm/plugin-intent-KETLP7UL.mjs.map +7 -0
  48. package/dist/lib/node-esm/plugin-settings-37UVWF2V.mjs +12 -0
  49. package/dist/lib/node-esm/plugin-settings-37UVWF2V.mjs.map +7 -0
  50. package/dist/lib/node-esm/plugin-surface-QXQRR534.mjs +25 -0
  51. package/dist/lib/node-esm/plugin-surface-QXQRR534.mjs.map +7 -0
  52. package/dist/types/src/App.d.ts +5 -5
  53. package/dist/types/src/App.d.ts.map +1 -1
  54. package/dist/types/src/plugins/common/file.d.ts +1 -1
  55. package/dist/types/src/plugins/common/file.d.ts.map +1 -1
  56. package/dist/types/src/plugins/common/graph.d.ts +1 -1
  57. package/dist/types/src/plugins/common/graph.d.ts.map +1 -1
  58. package/dist/types/src/plugins/common/index.d.ts +0 -1
  59. package/dist/types/src/plugins/common/index.d.ts.map +1 -1
  60. package/dist/types/src/plugins/common/layout.d.ts +6 -6
  61. package/dist/types/src/plugins/common/layout.d.ts.map +1 -1
  62. package/dist/types/src/plugins/common/metadata.d.ts +1 -1
  63. package/dist/types/src/plugins/common/metadata.d.ts.map +1 -1
  64. package/dist/types/src/plugins/common/navigation.d.ts +9 -20
  65. package/dist/types/src/plugins/common/navigation.d.ts.map +1 -1
  66. package/dist/types/src/plugins/common/translations.d.ts +1 -1
  67. package/dist/types/src/plugins/common/translations.d.ts.map +1 -1
  68. package/dist/types/src/plugins/helpers.d.ts +20 -5
  69. package/dist/types/src/plugins/helpers.d.ts.map +1 -1
  70. package/dist/types/src/plugins/index.d.ts +4 -3
  71. package/dist/types/src/plugins/index.d.ts.map +1 -1
  72. package/dist/types/src/plugins/plugin-host/HostPlugin.d.ts +21 -0
  73. package/dist/types/src/plugins/plugin-host/HostPlugin.d.ts.map +1 -0
  74. package/dist/types/src/plugins/plugin-host/PluginContainer.d.ts +14 -0
  75. package/dist/types/src/plugins/plugin-host/PluginContainer.d.ts.map +1 -0
  76. package/dist/types/src/plugins/{PluginHost → plugin-host}/PluginContext.d.ts +4 -4
  77. package/dist/types/src/plugins/plugin-host/PluginContext.d.ts.map +1 -0
  78. package/dist/types/src/plugins/plugin-host/index.d.ts +4 -0
  79. package/dist/types/src/plugins/plugin-host/index.d.ts.map +1 -0
  80. package/dist/types/src/plugins/{PluginHost → plugin-host}/plugin.d.ts +37 -83
  81. package/dist/types/src/plugins/plugin-host/plugin.d.ts.map +1 -0
  82. package/dist/types/src/plugins/plugin-host/plugin.test.d.ts.map +1 -0
  83. package/dist/types/src/plugins/plugin-intent/IntentContext.d.ts.map +1 -0
  84. package/dist/types/src/plugins/{IntentPlugin/plugin.d.ts → plugin-intent/IntentPlugin.d.ts} +3 -4
  85. package/dist/types/src/plugins/plugin-intent/IntentPlugin.d.ts.map +1 -0
  86. package/dist/types/src/plugins/plugin-intent/helpers.d.ts.map +1 -0
  87. package/dist/types/src/plugins/plugin-intent/index.d.ts +6 -0
  88. package/dist/types/src/plugins/plugin-intent/index.d.ts.map +1 -0
  89. package/dist/types/src/plugins/{IntentPlugin → plugin-intent}/intent.d.ts +1 -1
  90. package/dist/types/src/plugins/plugin-intent/intent.d.ts.map +1 -0
  91. package/dist/types/src/plugins/plugin-intent/meta.d.ts.map +1 -0
  92. package/dist/types/src/plugins/{IntentPlugin → plugin-intent}/provides.d.ts +2 -2
  93. package/dist/types/src/plugins/plugin-intent/provides.d.ts.map +1 -0
  94. package/dist/types/src/plugins/plugin-settings/SettingsPlugin.d.ts +4 -0
  95. package/dist/types/src/plugins/plugin-settings/SettingsPlugin.d.ts.map +1 -0
  96. package/dist/types/src/plugins/plugin-settings/index.d.ts +4 -0
  97. package/dist/types/src/plugins/plugin-settings/index.d.ts.map +1 -0
  98. package/dist/types/src/plugins/plugin-settings/meta.d.ts +5 -0
  99. package/dist/types/src/plugins/plugin-settings/meta.d.ts.map +1 -0
  100. package/dist/types/src/plugins/plugin-settings/provides.d.ts +13 -0
  101. package/dist/types/src/plugins/plugin-settings/provides.d.ts.map +1 -0
  102. package/dist/types/src/plugins/plugin-surface/ErrorBoundary.d.ts.map +1 -0
  103. package/dist/types/src/plugins/{SurfacePlugin → plugin-surface}/Surface.d.ts +6 -2
  104. package/dist/types/src/plugins/plugin-surface/Surface.d.ts.map +1 -0
  105. package/dist/types/src/plugins/plugin-surface/SurfacePlugin.d.ts +7 -0
  106. package/dist/types/src/plugins/plugin-surface/SurfacePlugin.d.ts.map +1 -0
  107. package/dist/types/src/plugins/{SurfacePlugin → plugin-surface}/SurfaceRootContext.d.ts +15 -2
  108. package/dist/types/src/plugins/plugin-surface/SurfaceRootContext.d.ts.map +1 -0
  109. package/dist/types/src/plugins/plugin-surface/helpers.d.ts.map +1 -0
  110. package/dist/types/src/plugins/{SurfacePlugin → plugin-surface}/index.d.ts +2 -0
  111. package/dist/types/src/plugins/plugin-surface/index.d.ts.map +1 -0
  112. package/dist/types/src/plugins/plugin-surface/meta.d.ts.map +1 -0
  113. package/dist/types/src/plugins/{SurfacePlugin → plugin-surface}/provides.d.ts +1 -1
  114. package/dist/types/src/plugins/plugin-surface/provides.d.ts.map +1 -0
  115. package/package.json +16 -14
  116. package/project.json +3 -8
  117. package/src/App.tsx +18 -16
  118. package/src/plugins/common/file.ts +1 -1
  119. package/src/plugins/common/graph.ts +1 -1
  120. package/src/plugins/common/index.ts +0 -1
  121. package/src/plugins/common/layout.ts +6 -3
  122. package/src/plugins/common/metadata.ts +1 -1
  123. package/src/plugins/common/navigation.ts +10 -15
  124. package/src/plugins/common/translations.ts +2 -8
  125. package/src/plugins/helpers.ts +55 -11
  126. package/src/plugins/index.ts +4 -3
  127. package/src/plugins/plugin-host/HostPlugin.tsx +96 -0
  128. package/src/plugins/plugin-host/PluginContainer.tsx +120 -0
  129. package/src/plugins/{PluginHost → plugin-host}/PluginContext.tsx +9 -14
  130. package/src/plugins/{PluginHost → plugin-host}/index.ts +2 -1
  131. package/src/plugins/{PluginHost → plugin-host}/plugin.test.ts +1 -2
  132. package/src/plugins/{PluginHost → plugin-host}/plugin.ts +45 -52
  133. package/src/plugins/{IntentPlugin/plugin.tsx → plugin-intent/IntentPlugin.tsx} +3 -6
  134. package/src/plugins/{IntentPlugin → plugin-intent}/index.ts +4 -0
  135. package/src/plugins/{IntentPlugin → plugin-intent}/intent.ts +1 -1
  136. package/src/plugins/{IntentPlugin → plugin-intent}/provides.ts +5 -2
  137. package/src/plugins/plugin-settings/SettingsPlugin.tsx +22 -0
  138. package/src/plugins/plugin-settings/index.ts +9 -0
  139. package/src/plugins/plugin-settings/meta.ts +9 -0
  140. package/src/plugins/plugin-settings/provides.ts +29 -0
  141. package/src/plugins/{SurfacePlugin → plugin-surface}/Surface.tsx +74 -40
  142. package/src/plugins/{SurfacePlugin/plugin.tsx → plugin-surface/SurfacePlugin.tsx} +3 -5
  143. package/src/plugins/{SurfacePlugin → plugin-surface}/SurfaceRootContext.tsx +21 -4
  144. package/src/plugins/{SurfacePlugin → plugin-surface}/index.ts +4 -0
  145. package/src/plugins/{SurfacePlugin → plugin-surface}/provides.ts +2 -1
  146. package/tsconfig.json +2 -30
  147. package/vitest.config.ts +9 -0
  148. package/dist/lib/browser/chunk-J45KR4DI.mjs +0 -52
  149. package/dist/lib/browser/chunk-J45KR4DI.mjs.map +0 -7
  150. package/dist/lib/browser/chunk-S5CI6EUQ.mjs +0 -20
  151. package/dist/lib/browser/chunk-S5CI6EUQ.mjs.map +0 -7
  152. package/dist/lib/browser/chunk-YYV26N3W.mjs +0 -26
  153. package/dist/lib/browser/chunk-YYV26N3W.mjs.map +0 -7
  154. package/dist/lib/browser/plugin-K3KCPCTJ.mjs +0 -39
  155. package/dist/lib/browser/plugin-K3KCPCTJ.mjs.map +0 -7
  156. package/dist/lib/browser/plugin-MM66VRCO.mjs.map +0 -7
  157. package/dist/lib/node/chunk-62W6CMGM.cjs.map +0 -7
  158. package/dist/lib/node/chunk-DFST5IG5.cjs +0 -77
  159. package/dist/lib/node/chunk-DFST5IG5.cjs.map +0 -7
  160. package/dist/lib/node/chunk-P5GRB4XF.cjs.map +0 -7
  161. package/dist/lib/node/plugin-QV7ESETI.cjs.map +0 -7
  162. package/dist/lib/node/plugin-RUJ5PEXB.cjs +0 -61
  163. package/dist/lib/node/plugin-RUJ5PEXB.cjs.map +0 -7
  164. package/dist/types/src/plugins/IntentPlugin/IntentContext.d.ts.map +0 -1
  165. package/dist/types/src/plugins/IntentPlugin/helpers.d.ts.map +0 -1
  166. package/dist/types/src/plugins/IntentPlugin/index.d.ts +0 -4
  167. package/dist/types/src/plugins/IntentPlugin/index.d.ts.map +0 -1
  168. package/dist/types/src/plugins/IntentPlugin/intent.d.ts.map +0 -1
  169. package/dist/types/src/plugins/IntentPlugin/meta.d.ts.map +0 -1
  170. package/dist/types/src/plugins/IntentPlugin/plugin.d.ts.map +0 -1
  171. package/dist/types/src/plugins/IntentPlugin/provides.d.ts.map +0 -1
  172. package/dist/types/src/plugins/PluginHost/PluginContext.d.ts.map +0 -1
  173. package/dist/types/src/plugins/PluginHost/PluginHost.d.ts +0 -25
  174. package/dist/types/src/plugins/PluginHost/PluginHost.d.ts.map +0 -1
  175. package/dist/types/src/plugins/PluginHost/index.d.ts +0 -4
  176. package/dist/types/src/plugins/PluginHost/index.d.ts.map +0 -1
  177. package/dist/types/src/plugins/PluginHost/plugin.d.ts.map +0 -1
  178. package/dist/types/src/plugins/PluginHost/plugin.test.d.ts.map +0 -1
  179. package/dist/types/src/plugins/SurfacePlugin/ErrorBoundary.d.ts.map +0 -1
  180. package/dist/types/src/plugins/SurfacePlugin/Surface.d.ts.map +0 -1
  181. package/dist/types/src/plugins/SurfacePlugin/SurfaceRootContext.d.ts.map +0 -1
  182. package/dist/types/src/plugins/SurfacePlugin/helpers.d.ts.map +0 -1
  183. package/dist/types/src/plugins/SurfacePlugin/index.d.ts.map +0 -1
  184. package/dist/types/src/plugins/SurfacePlugin/meta.d.ts.map +0 -1
  185. package/dist/types/src/plugins/SurfacePlugin/plugin.d.ts +0 -8
  186. package/dist/types/src/plugins/SurfacePlugin/plugin.d.ts.map +0 -1
  187. package/dist/types/src/plugins/SurfacePlugin/provides.d.ts.map +0 -1
  188. package/dist/types/src/plugins/common/settings.d.ts +0 -9
  189. package/dist/types/src/plugins/common/settings.d.ts.map +0 -1
  190. package/src/plugins/PluginHost/PluginHost.tsx +0 -198
  191. package/src/plugins/common/settings.ts +0 -22
  192. /package/dist/types/src/plugins/{PluginHost → plugin-host}/plugin.test.d.ts +0 -0
  193. /package/dist/types/src/plugins/{IntentPlugin → plugin-intent}/IntentContext.d.ts +0 -0
  194. /package/dist/types/src/plugins/{IntentPlugin → plugin-intent}/helpers.d.ts +0 -0
  195. /package/dist/types/src/plugins/{IntentPlugin → plugin-intent}/meta.d.ts +0 -0
  196. /package/dist/types/src/plugins/{SurfacePlugin → plugin-surface}/ErrorBoundary.d.ts +0 -0
  197. /package/dist/types/src/plugins/{SurfacePlugin → plugin-surface}/helpers.d.ts +0 -0
  198. /package/dist/types/src/plugins/{SurfacePlugin → plugin-surface}/meta.d.ts +0 -0
  199. /package/src/plugins/{IntentPlugin → plugin-intent}/IntentContext.tsx +0 -0
  200. /package/src/plugins/{IntentPlugin → plugin-intent}/helpers.ts +0 -0
  201. /package/src/plugins/{IntentPlugin → plugin-intent}/meta.ts +0 -0
  202. /package/src/plugins/{SurfacePlugin → plugin-surface}/ErrorBoundary.tsx +0 -0
  203. /package/src/plugins/{SurfacePlugin → plugin-surface}/helpers.ts +0 -0
  204. /package/src/plugins/{SurfacePlugin → plugin-surface}/meta.ts +0 -0
@@ -0,0 +1,22 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { RootSettingsStore } from '@dxos/local-storage';
6
+
7
+ import SettingsMeta from './meta';
8
+ import { type SettingsPluginProvides } from './provides';
9
+ import { type PluginDefinition } from '../plugin-host';
10
+
11
+ export const SettingsPlugin = (): PluginDefinition<SettingsPluginProvides> => {
12
+ // Global settings singleton.
13
+ // TODO(burdon): Make settings storage extensible so that other plugins can decide the persistence of them.
14
+ const settingsStore = new RootSettingsStore();
15
+
16
+ return {
17
+ meta: SettingsMeta,
18
+ provides: {
19
+ settingsStore,
20
+ },
21
+ };
22
+ };
@@ -0,0 +1,9 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { SettingsPlugin } from './SettingsPlugin';
6
+
7
+ export * from './provides';
8
+
9
+ export default SettingsPlugin;
@@ -0,0 +1,9 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ const SettingsMeta = {
6
+ id: 'dxos.org/plugin/settings',
7
+ };
8
+
9
+ export default SettingsMeta;
@@ -0,0 +1,29 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { type SettingsStoreFactory, type SettingsValue } from '@dxos/local-storage';
6
+
7
+ import { type Plugin } from '../plugin-host';
8
+
9
+ export type SettingsProvides<T extends SettingsValue> = {
10
+ settings: T;
11
+ };
12
+
13
+ export type SettingsPluginProvides = {
14
+ settingsStore: SettingsStoreFactory;
15
+ };
16
+
17
+ export const parseSettingsPlugin = (plugin: Plugin) => {
18
+ return typeof (plugin.provides as any).settingsStore === 'object'
19
+ ? (plugin as Plugin<SettingsPluginProvides>)
20
+ : undefined;
21
+ };
22
+
23
+ const SETTINGS_PLUGIN = 'dxos.org/plugin/settings';
24
+
25
+ const SETTINGS_ACTION = `${SETTINGS_PLUGIN}/action`;
26
+
27
+ export enum SettingsAction {
28
+ OPEN = `${SETTINGS_ACTION}/open`,
29
+ }
@@ -3,17 +3,22 @@
3
3
  //
4
4
 
5
5
  import React, {
6
- forwardRef,
7
- type ReactNode,
8
6
  Fragment,
9
7
  type ForwardedRef,
10
8
  type PropsWithChildren,
11
- isValidElement,
9
+ type ReactNode,
12
10
  Suspense,
11
+ createContext,
12
+ forwardRef,
13
+ isValidElement,
14
+ memo,
15
+ useContext,
16
+ useEffect,
17
+ useState,
13
18
  } from 'react';
14
- import { createContext, useContext } from 'react';
15
19
 
16
20
  import { raise } from '@dxos/debug';
21
+ import { log } from '@dxos/log';
17
22
 
18
23
  import { ErrorBoundary } from './ErrorBoundary';
19
24
  import { type SurfaceComponent, type SurfaceResult, useSurfaceRoot } from './SurfaceRootContext';
@@ -27,6 +32,11 @@ export type Direction = 'inline' | 'inline-reverse' | 'block' | 'block-reverse';
27
32
  * SurfaceProps are the props that are passed to the Surface component.
28
33
  */
29
34
  export type SurfaceProps = PropsWithChildren<{
35
+ /**
36
+ * Optional ID for debugging.
37
+ */
38
+ id?: string;
39
+
30
40
  /**
31
41
  * Role defines how the data should be rendered.
32
42
  */
@@ -78,33 +88,55 @@ export type SurfaceProps = PropsWithChildren<{
78
88
  [key: string]: unknown;
79
89
  }>;
80
90
 
91
+ let count = 0;
92
+
81
93
  /**
82
94
  * A surface is a named region of the screen that can be populated by plugins.
83
95
  */
84
- export const Surface = forwardRef<HTMLElement, SurfaceProps>(
85
- ({ role, name = role, fallback, placeholder, ...rest }, forwardedRef) => {
86
- const props = { role, name, fallback, ...rest };
87
- const context = useContext(SurfaceContext);
88
- const data = props.data ?? ((name && context?.surfaces?.[name]?.data) || {});
89
-
90
- const resolver = <SurfaceResolver {...props} ref={forwardedRef} />;
91
- const suspense = placeholder ? <Suspense fallback={placeholder}>{resolver}</Suspense> : resolver;
92
-
93
- return fallback ? (
94
- <ErrorBoundary data={data} fallback={fallback}>
95
- {suspense}
96
- </ErrorBoundary>
97
- ) : (
98
- suspense
99
- );
100
- },
96
+ export const Surface = memo(
97
+ forwardRef<HTMLElement, SurfaceProps>(
98
+ ({ id: _id, role, name = role, fallback, placeholder, ...rest }, forwardedRef) => {
99
+ const props = { role, name, fallback, ...rest };
100
+ const { debugInfo } = useSurfaceRoot();
101
+
102
+ // Track debug info.
103
+ const [id] = useState<string>(() => _id ?? `surface-${++count}`);
104
+ useEffect(() => {
105
+ debugInfo?.set(id, { id, created: Date.now(), name, role, renderCount: 0 });
106
+ return () => {
107
+ debugInfo?.delete(id);
108
+ };
109
+ }, [id]);
110
+
111
+ if (debugInfo?.get(id)) {
112
+ debugInfo.get(id)!.renderCount++;
113
+ }
114
+
115
+ const context = useContext(SurfaceContext);
116
+ const data = props.data ?? ((name && context?.surfaces?.[name]?.data) || {});
117
+
118
+ const resolver = <SurfaceResolver {...props} id={id} ref={forwardedRef} />;
119
+ const suspense = placeholder ? <Suspense fallback={placeholder}>{resolver}</Suspense> : resolver;
120
+
121
+ return fallback ? (
122
+ <ErrorBoundary data={data} fallback={fallback}>
123
+ {suspense}
124
+ </ErrorBoundary>
125
+ ) : (
126
+ suspense
127
+ );
128
+ },
129
+ ),
101
130
  );
102
131
 
103
- const SurfaceContext = createContext<SurfaceProps | null>(null);
132
+ const SurfaceContext = createContext<SurfaceProps | undefined>(undefined);
104
133
 
105
134
  export const useSurface = (): SurfaceProps =>
106
135
  useContext(SurfaceContext) ?? raise(new Error('Surface context not found'));
107
136
 
137
+ /**
138
+ * Root surface component.
139
+ */
108
140
  const SurfaceResolver = forwardRef<HTMLElement, SurfaceProps>((props, forwardedRef) => {
109
141
  const { components } = useSurfaceRoot();
110
142
  const parent = useContext(SurfaceContext);
@@ -120,10 +152,13 @@ const SurfaceResolver = forwardRef<HTMLElement, SurfaceProps>((props, forwardedR
120
152
  return <SurfaceContext.Provider value={currentContext}>{nodes}</SurfaceContext.Provider>;
121
153
  });
122
154
 
155
+ /**
156
+ * Resolve surface nodes from across all component.
157
+ */
123
158
  const resolveNodes = (
124
159
  components: Record<string, SurfaceComponent>,
125
160
  props: SurfaceProps,
126
- context: SurfaceProps | null,
161
+ context: SurfaceProps | undefined,
127
162
  forwardedRef: ForwardedRef<HTMLElement>,
128
163
  ): ReactNode[] => {
129
164
  const data = {
@@ -131,31 +166,30 @@ const resolveNodes = (
131
166
  ...props.data,
132
167
  };
133
168
 
134
- const nodes = Object.entries(components)
169
+ const candidates = Object.entries(components)
135
170
  .map(([key, component]): [string, SurfaceResult] | undefined => {
171
+ // TODO(burdon): Avoid variable return types in plugin contract.
136
172
  const result = component({ ...props, data }, forwardedRef);
137
173
  if (!result || typeof result !== 'object') {
138
174
  return undefined;
139
175
  }
140
176
 
141
- return 'node' in result ? [key, result] : isValidElement(result) ? [key, { node: result }] : undefined;
142
- })
143
- .filter((result): result is [string, SurfaceResult] => Boolean(result))
144
- .sort(([, a], [, b]) => {
145
- const aDisposition = a.disposition ?? 'default';
146
- const bDisposition = b.disposition ?? 'default';
147
-
148
- if (aDisposition === bDisposition) {
149
- return 0;
150
- } else if (aDisposition === 'hoist' || bDisposition === 'fallback') {
151
- return -1;
152
- } else if (bDisposition === 'hoist' || aDisposition === 'fallback') {
153
- return 1;
177
+ // Normalize tuple.
178
+ if ('node' in result) {
179
+ return [key, result];
180
+ } else if (isValidElement(result)) {
181
+ return [key, { node: result }];
182
+ } else {
183
+ log.warn('invalid result', { result });
184
+ return undefined;
154
185
  }
155
-
156
- return 0;
157
186
  })
158
- .map(([key, result]) => <Fragment key={key}>{result.node}</Fragment>);
187
+ .filter((result): result is [string, SurfaceResult] => Boolean(result))
188
+ .sort(([, { disposition: a = 'default' }], [, { disposition: b = 'default' }]) => {
189
+ return a === b ? 0 : a === 'hoist' || b === 'fallback' ? -1 : b === 'hoist' || a === 'fallback' ? 1 : 0;
190
+ });
159
191
 
192
+ // TODO(burdon): Does this prematurely process the node?
193
+ const nodes = candidates.map(([key, result]) => <Fragment key={key}>{result.node}</Fragment>);
160
194
  return props.limit ? nodes.slice(0, props.limit) : nodes;
161
195
  };
@@ -9,14 +9,14 @@ import { create } from '@dxos/echo-schema';
9
9
  import { SurfaceProvider, type SurfaceRootContext } from './SurfaceRootContext';
10
10
  import SurfaceMeta from './meta';
11
11
  import { parseSurfacePlugin, type SurfacePluginProvides } from './provides';
12
- import type { PluginDefinition } from '../PluginHost';
13
12
  import { filterPlugins } from '../helpers';
13
+ import { type PluginDefinition } from '../plugin-host';
14
14
 
15
15
  /**
16
16
  * Provides a registry of surface components.
17
17
  */
18
- const SurfacePlugin = (): PluginDefinition<SurfacePluginProvides> => {
19
- const state = create<SurfaceRootContext>({ components: {} });
18
+ export const SurfacePlugin = (): PluginDefinition<SurfacePluginProvides> => {
19
+ const state = create<SurfaceRootContext>({ components: {}, debugInfo: new Map() });
20
20
 
21
21
  return {
22
22
  meta: SurfaceMeta,
@@ -31,5 +31,3 @@ const SurfacePlugin = (): PluginDefinition<SurfacePluginProvides> => {
31
31
  },
32
32
  };
33
33
  };
34
-
35
- export default SurfacePlugin;
@@ -2,7 +2,9 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { createContext, useContext, type Context, type JSX, type Provider, type ForwardedRef } from 'react';
5
+ import { createContext, useContext, type JSX, type ForwardedRef } from 'react';
6
+
7
+ import { raise } from '@dxos/debug';
6
8
 
7
9
  import { type SurfaceProps } from './Surface';
8
10
 
@@ -18,6 +20,16 @@ type SurfaceComponentProps = WithRequiredProperty<SurfaceProps, 'data'>;
18
20
  */
19
21
  export type SurfaceDisposition = 'hoist' | 'fallback';
20
22
 
23
+ /**
24
+ * Surface debug info.
25
+ * NOTE: Short-term measure to track perf issues.
26
+ */
27
+ export type DebugInfo = {
28
+ id: string;
29
+ created: number;
30
+ renderCount: number;
31
+ } & Pick<SurfaceProps, 'role' | 'name'>;
32
+
21
33
  export type SurfaceResult = {
22
34
  node: JSX.Element;
23
35
  disposition?: SurfaceDisposition;
@@ -35,10 +47,15 @@ export type SurfaceComponent = (
35
47
 
36
48
  export type SurfaceRootContext = {
37
49
  components: Record<string, SurfaceComponent>;
50
+
51
+ /**
52
+ * Debug info.
53
+ */
54
+ debugInfo?: Map<string, DebugInfo>;
38
55
  };
39
56
 
40
- const SurfaceRootContext: Context<SurfaceRootContext> = createContext<SurfaceRootContext>({ components: {} });
57
+ const SurfaceRootContext = createContext<SurfaceRootContext | undefined>(undefined);
41
58
 
42
- export const useSurfaceRoot = () => useContext(SurfaceRootContext);
59
+ export const useSurfaceRoot = () => useContext(SurfaceRootContext) ?? raise(new Error('Missing SurfaceRootContext'));
43
60
 
44
- export const SurfaceProvider: Provider<SurfaceRootContext> = SurfaceRootContext.Provider;
61
+ export const SurfaceProvider = SurfaceRootContext.Provider;
@@ -2,9 +2,13 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ import { SurfacePlugin } from './SurfacePlugin';
6
+
5
7
  export * from './helpers';
6
8
  export * from './provides';
7
9
 
8
10
  export * from './ErrorBoundary';
9
11
  export * from './Surface';
10
12
  export * from './SurfaceRootContext';
13
+
14
+ export default SurfacePlugin;
@@ -3,8 +3,9 @@
3
3
  //
4
4
 
5
5
  import { type SurfaceComponent, type SurfaceRootContext } from './SurfaceRootContext';
6
- import { type Plugin } from '../PluginHost';
6
+ import { type Plugin } from '../plugin-host';
7
7
 
8
+ // TODO(burdon): Predicate based providers?
8
9
  export type SurfaceProvides = {
9
10
  surface: {
10
11
  /**
package/tsconfig.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "extends": "../../../tsconfig.json",
2
+ "extends": "../../../tsconfig.base.json",
3
3
  "compilerOptions": {
4
4
  "esModuleInterop": true,
5
5
  "jsx": "react",
@@ -16,35 +16,7 @@
16
16
  "include": [
17
17
  "src"
18
18
  ],
19
- "references": [
20
- {
21
- "path": "../../common/async"
22
- },
23
- {
24
- "path": "../../common/debug"
25
- },
26
- {
27
- "path": "../../common/invariant"
28
- },
29
- {
30
- "path": "../../common/local-storage"
31
- },
32
- {
33
- "path": "../../common/log"
34
- },
35
- {
36
- "path": "../../common/util"
37
- },
38
- {
39
- "path": "../../core/echo/echo-schema"
40
- },
41
- {
42
- "path": "../app-graph"
43
- },
44
- {
45
- "path": "../client-protocol"
46
- }
47
- ],
19
+ "references": [],
48
20
  "ts-node": {
49
21
  "compilerOptions": {
50
22
  "module": "CommonJS"
@@ -0,0 +1,9 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { defineConfig, mergeConfig } from 'vitest/config';
6
+
7
+ import { baseConfig } from '../../../vitest.shared';
8
+
9
+ export default mergeConfig(baseConfig({ cwd: __dirname }), defineConfig({}));
@@ -1,52 +0,0 @@
1
- // packages/sdk/app-framework/src/plugins/IntentPlugin/provides.ts
2
- var parseIntentPlugin = (plugin) => plugin.provides.intent?.dispatch ? plugin : void 0;
3
- var parseIntentResolverPlugin = (plugin) => plugin.provides.intent?.resolver ? plugin : void 0;
4
- var INTENT_ACTION = "dxos.org/plugin/intent";
5
- var IntentAction;
6
- (function(IntentAction2) {
7
- IntentAction2[IntentAction2["SHOW_UNDO"] = `${INTENT_ACTION}/show-undo`] = "SHOW_UNDO";
8
- })(IntentAction || (IntentAction = {}));
9
-
10
- // packages/sdk/app-framework/src/plugins/IntentPlugin/IntentContext.tsx
11
- import { createContext, useContext } from "react";
12
- import { useEffect } from "react";
13
- var IntentContext = /* @__PURE__ */ createContext({
14
- dispatch: async () => ({}),
15
- undo: async () => ({}),
16
- history: [],
17
- registerResolver: () => () => {
18
- }
19
- });
20
- var useIntent = () => useContext(IntentContext);
21
- var useIntentDispatcher = () => {
22
- const { dispatch } = useIntent();
23
- return dispatch;
24
- };
25
- var useIntentResolver = (plugin, resolver) => {
26
- const { registerResolver } = useIntent();
27
- useEffect(() => {
28
- return registerResolver(plugin, resolver);
29
- }, [
30
- plugin,
31
- resolver
32
- ]);
33
- };
34
- var IntentProvider = IntentContext.Provider;
35
-
36
- // packages/sdk/app-framework/src/plugins/IntentPlugin/meta.ts
37
- var IntentMeta = {
38
- id: "dxos.org/plugin/intent"
39
- };
40
- var meta_default = IntentMeta;
41
-
42
- export {
43
- parseIntentPlugin,
44
- parseIntentResolverPlugin,
45
- IntentAction,
46
- useIntent,
47
- useIntentDispatcher,
48
- useIntentResolver,
49
- IntentProvider,
50
- meta_default
51
- };
52
- //# sourceMappingURL=chunk-J45KR4DI.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/plugins/IntentPlugin/provides.ts", "../../../src/plugins/IntentPlugin/IntentContext.tsx", "../../../src/plugins/IntentPlugin/meta.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { type IntentContext } from './IntentContext';\nimport { type IntentResolver } from './intent';\nimport { type Plugin } from '../PluginHost';\n\nexport type IntentResolverProvides = {\n intent: {\n resolver: IntentResolver;\n };\n};\n\nexport type IntentPluginProvides = {\n intent: IntentContext;\n};\n\nexport const parseIntentPlugin = (plugin: Plugin) =>\n (plugin.provides as any).intent?.dispatch ? (plugin as Plugin<IntentPluginProvides>) : undefined;\n\nexport const parseIntentResolverPlugin = (plugin: Plugin) =>\n (plugin.provides as any).intent?.resolver ? (plugin as Plugin<IntentResolverProvides>) : undefined;\n\n//\n// Intents\n//\n\nconst INTENT_ACTION = 'dxos.org/plugin/intent';\nexport enum IntentAction {\n /**\n * Fired after an intent is dispatched if the intent is undoable.\n */\n SHOW_UNDO = `${INTENT_ACTION}/show-undo`,\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Context, createContext, useContext, type Provider } from 'react';\nimport { useEffect } from 'react';\n\nimport type { UnsubscribeCallback } from '@dxos/async';\n\nimport type { Intent, IntentDispatcher, IntentResolver, IntentResult } from './intent';\n\nexport type IntentExecution = {\n intent: Intent;\n result: IntentResult;\n};\n\nexport type IntentContext = {\n dispatch: IntentDispatcher;\n undo: () => Promise<IntentResult | void>;\n history: IntentExecution[][];\n registerResolver: (pluginId: string, resolver: IntentResolver) => UnsubscribeCallback;\n};\n\nconst IntentContext: Context<IntentContext> = createContext<IntentContext>({\n dispatch: async () => ({}),\n undo: async () => ({}),\n history: [],\n registerResolver: () => () => {},\n});\n\n/**\n * @deprecated Prefer granular hooks.\n */\n// TODO(burdon): Remove. Use useIntentDispatcher.\nexport const useIntent = () => useContext(IntentContext);\n\nexport const useIntentDispatcher = (): IntentDispatcher => {\n const { dispatch } = useIntent();\n return dispatch;\n};\n\nexport const useIntentResolver = (plugin: string, resolver: IntentResolver) => {\n const { registerResolver } = useIntent();\n useEffect(() => {\n return registerResolver(plugin, resolver);\n }, [plugin, resolver]);\n};\n\nexport const IntentProvider: Provider<IntentContext> = IntentContext.Provider;\n", "//\n// Copyright 2023 DXOS.org\n//\n\nconst IntentMeta = {\n id: 'dxos.org/plugin/intent',\n};\n\nexport default IntentMeta;\n"],
5
- "mappings": ";AAkBO,IAAMA,oBAAoB,CAACC,WAC/BA,OAAOC,SAAiBC,QAAQC,WAAYH,SAA0CI;AAElF,IAAMC,4BAA4B,CAACL,WACvCA,OAAOC,SAAiBC,QAAQI,WAAYN,SAA4CI;AAM3F,IAAMG,gBAAgB;;UACVC,eAAAA;AAGT,EAAAA,cAAAA,cAAA,WAAA,IACW,GAAGD,aAAAA,YAAyB,IAAA;GAJ9BC,iBAAAA,eAAAA,CAAAA,EAAAA;;;ACzBZ,SAAuBC,eAAeC,kBAAiC;AACvE,SAASC,iBAAiB;AAkB1B,IAAMC,gBAAwCC,8BAA6B;EACzEC,UAAU,aAAa,CAAC;EACxBC,MAAM,aAAa,CAAC;EACpBC,SAAS,CAAA;EACTC,kBAAkB,MAAM,MAAA;EAAO;AACjC,CAAA;AAMO,IAAMC,YAAY,MAAMC,WAAWP,aAAAA;AAEnC,IAAMQ,sBAAsB,MAAA;AACjC,QAAM,EAAEN,SAAQ,IAAKI,UAAAA;AACrB,SAAOJ;AACT;AAEO,IAAMO,oBAAoB,CAACC,QAAgBC,aAAAA;AAChD,QAAM,EAAEN,iBAAgB,IAAKC,UAAAA;AAC7BM,YAAU,MAAA;AACR,WAAOP,iBAAiBK,QAAQC,QAAAA;EAClC,GAAG;IAACD;IAAQC;GAAS;AACvB;AAEO,IAAME,iBAA0Cb,cAAcc;;;AC5CrE,IAAMC,aAAa;EACjBC,IAAI;AACN;AAEA,IAAA,eAAeD;",
6
- "names": ["parseIntentPlugin", "plugin", "provides", "intent", "dispatch", "undefined", "parseIntentResolverPlugin", "resolver", "INTENT_ACTION", "IntentAction", "createContext", "useContext", "useEffect", "IntentContext", "createContext", "dispatch", "undo", "history", "registerResolver", "useIntent", "useContext", "useIntentDispatcher", "useIntentResolver", "plugin", "resolver", "useEffect", "IntentProvider", "Provider", "IntentMeta", "id"]
7
- }
@@ -1,20 +0,0 @@
1
- // packages/sdk/app-framework/src/plugins/helpers.ts
2
- import { raise } from "@dxos/debug";
3
- var definePlugin = (plugin) => plugin;
4
- var findPlugin = (plugins, id) => {
5
- return plugins.find((plugin) => plugin.meta.id === id || typeof plugin.meta.shortId === "string" && plugin.meta.shortId === id);
6
- };
7
- var getPlugin = (plugins, id) => {
8
- return findPlugin(plugins, id) ?? raise(new Error(`Plugin not found: ${id}`));
9
- };
10
- var filterPlugins = (plugins, predicate) => plugins.map((plugin) => predicate(plugin)).filter((plugin) => !!plugin);
11
- var resolvePlugin = (plugins, predicate) => filterPlugins(plugins, predicate)[0];
12
-
13
- export {
14
- definePlugin,
15
- findPlugin,
16
- getPlugin,
17
- filterPlugins,
18
- resolvePlugin
19
- };
20
- //# sourceMappingURL=chunk-S5CI6EUQ.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/plugins/helpers.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { raise } from '@dxos/debug';\n\nimport { type Plugin } from './PluginHost';\n\n/**\n * Define a plugin\n */\nexport const definePlugin = <TProvides>(plugin: Plugin<TProvides>): Plugin<TProvides> => plugin;\n\n/**\n * Find a plugin by ID.\n */\nexport const findPlugin = <T>(plugins: Plugin[], id: string): Plugin<T> | undefined => {\n return plugins.find(\n (plugin) => plugin.meta.id === id || (typeof plugin.meta.shortId === 'string' && plugin.meta.shortId === id),\n ) as Plugin<T>;\n};\n\n/**\n * Find a plugin by ID, or raise an error if not found.\n */\nexport const getPlugin = <T>(plugins: Plugin[], id: string): Plugin<T> => {\n return findPlugin(plugins, id) ?? raise(new Error(`Plugin not found: ${id}`));\n};\n\n/**\n * Filter a list of plugins to only those that match a predicate.\n */\nexport const filterPlugins = <T>(\n plugins: Plugin[],\n predicate: (plugin: Plugin) => Plugin<T> | undefined,\n): Plugin<T>[] => plugins.map((plugin) => predicate(plugin)).filter((plugin): plugin is Plugin<T> => !!plugin);\n\n/**\n * Resolves a plugin by predicate.\n *\n * @example\n * import { parseIntentPlugin, resolvePlugin } from '@dxos/app-framework';\n * const intentPlugin = resolvePlugin(plugins, parseIntentPlugin);\n */\nexport const resolvePlugin = <T>(\n plugins: Plugin[],\n predicate: (plugin: Plugin) => Plugin<T> | undefined,\n): Plugin<T> | undefined => filterPlugins(plugins, predicate)[0];\n"],
5
- "mappings": ";AAIA,SAASA,aAAa;AAOf,IAAMC,eAAe,CAAYC,WAAiDA;AAKlF,IAAMC,aAAa,CAAIC,SAAmBC,OAAAA;AAC/C,SAAOD,QAAQE,KACb,CAACJ,WAAWA,OAAOK,KAAKF,OAAOA,MAAO,OAAOH,OAAOK,KAAKC,YAAY,YAAYN,OAAOK,KAAKC,YAAYH,EAAAA;AAE7G;AAKO,IAAMI,YAAY,CAAIL,SAAmBC,OAAAA;AAC9C,SAAOF,WAAWC,SAASC,EAAAA,KAAOK,MAAM,IAAIC,MAAM,qBAAqBN,EAAAA,EAAI,CAAA;AAC7E;AAKO,IAAMO,gBAAgB,CAC3BR,SACAS,cACgBT,QAAQU,IAAI,CAACZ,WAAWW,UAAUX,MAAAA,CAAAA,EAASa,OAAO,CAACb,WAAgC,CAAC,CAACA,MAAAA;AAShG,IAAMc,gBAAgB,CAC3BZ,SACAS,cAC0BD,cAAcR,SAASS,SAAAA,EAAW,CAAA;",
6
- "names": ["raise", "definePlugin", "plugin", "findPlugin", "plugins", "id", "find", "meta", "shortId", "getPlugin", "raise", "Error", "filterPlugins", "predicate", "map", "filter", "resolvePlugin"]
7
- }
@@ -1,26 +0,0 @@
1
- // packages/sdk/app-framework/src/plugins/SurfacePlugin/provides.ts
2
- var parseRootSurfacePlugin = (plugin) => plugin?.provides?.surface?.components ? plugin : void 0;
3
- var parseSurfacePlugin = (plugin) => plugin?.provides?.surface?.component ? plugin : void 0;
4
-
5
- // packages/sdk/app-framework/src/plugins/SurfacePlugin/SurfaceRootContext.tsx
6
- import { createContext, useContext } from "react";
7
- var SurfaceRootContext = /* @__PURE__ */ createContext({
8
- components: {}
9
- });
10
- var useSurfaceRoot = () => useContext(SurfaceRootContext);
11
- var SurfaceProvider = SurfaceRootContext.Provider;
12
-
13
- // packages/sdk/app-framework/src/plugins/SurfacePlugin/meta.ts
14
- var SurfaceMeta = {
15
- id: "dxos.org/plugin/surface"
16
- };
17
- var meta_default = SurfaceMeta;
18
-
19
- export {
20
- parseRootSurfacePlugin,
21
- parseSurfacePlugin,
22
- useSurfaceRoot,
23
- SurfaceProvider,
24
- meta_default
25
- };
26
- //# sourceMappingURL=chunk-YYV26N3W.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/plugins/SurfacePlugin/provides.ts", "../../../src/plugins/SurfacePlugin/SurfaceRootContext.tsx", "../../../src/plugins/SurfacePlugin/meta.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { type SurfaceComponent, type SurfaceRootContext } from './SurfaceRootContext';\nimport { type Plugin } from '../PluginHost';\n\nexport type SurfaceProvides = {\n surface: {\n /**\n * Used by the `Surface` resolver to find a component to render.\n */\n component: SurfaceComponent;\n };\n};\n\nexport type SurfacePluginProvides = {\n surface: SurfaceRootContext;\n};\n\nexport const parseRootSurfacePlugin = (plugin?: Plugin) =>\n (plugin?.provides as any)?.surface?.components ? (plugin as Plugin<SurfacePluginProvides>) : undefined;\n\nexport const parseSurfacePlugin = (plugin?: Plugin) =>\n (plugin?.provides as any)?.surface?.component ? (plugin as Plugin<SurfaceProvides>) : undefined;\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { createContext, useContext, type Context, type JSX, type Provider, type ForwardedRef } from 'react';\n\nimport { type SurfaceProps } from './Surface';\n\n// TODO(wittjosiah): Factor out.\ntype WithRequiredProperty<Type, Key extends keyof Type> = Type & {\n [Property in Key]-?: Type[Property];\n};\n\ntype SurfaceComponentProps = WithRequiredProperty<SurfaceProps, 'data'>;\n\n/**\n * Determines the priority of the surface when multiple components are resolved.\n */\nexport type SurfaceDisposition = 'hoist' | 'fallback';\n\nexport type SurfaceResult = {\n node: JSX.Element;\n disposition?: SurfaceDisposition;\n};\n\n/**\n * Function which resolves a Surface.\n *\n * If a null value is returned, the rendering is deferred to other plugins.\n */\nexport type SurfaceComponent = (\n props: SurfaceComponentProps,\n forwardedRef: ForwardedRef<HTMLElement>,\n) => JSX.Element | SurfaceResult | null;\n\nexport type SurfaceRootContext = {\n components: Record<string, SurfaceComponent>;\n};\n\nconst SurfaceRootContext: Context<SurfaceRootContext> = createContext<SurfaceRootContext>({ components: {} });\n\nexport const useSurfaceRoot = () => useContext(SurfaceRootContext);\n\nexport const SurfaceProvider: Provider<SurfaceRootContext> = SurfaceRootContext.Provider;\n", "//\n// Copyright 2023 DXOS.org\n//\n\nconst SurfaceMeta = {\n id: 'dxos.org/plugin/surface',\n};\n\nexport default SurfaceMeta;\n"],
5
- "mappings": ";AAoBO,IAAMA,yBAAyB,CAACC,WACpCA,QAAQC,UAAkBC,SAASC,aAAcH,SAA2CI;AAExF,IAAMC,qBAAqB,CAACL,WAChCA,QAAQC,UAAkBC,SAASI,YAAaN,SAAqCI;;;ACpBxF,SAASG,eAAeC,kBAA4E;AAmCpG,IAAMC,qBAAkDC,8BAAkC;EAAEC,YAAY,CAAC;AAAE,CAAA;AAEpG,IAAMC,iBAAiB,MAAMC,WAAWJ,kBAAAA;AAExC,IAAMK,kBAAgDL,mBAAmBM;;;ACvChF,IAAMC,cAAc;EAClBC,IAAI;AACN;AAEA,IAAA,eAAeD;",
6
- "names": ["parseRootSurfacePlugin", "plugin", "provides", "surface", "components", "undefined", "parseSurfacePlugin", "component", "createContext", "useContext", "SurfaceRootContext", "createContext", "components", "useSurfaceRoot", "useContext", "SurfaceProvider", "Provider", "SurfaceMeta", "id"]
7
- }
@@ -1,39 +0,0 @@
1
- import {
2
- SurfaceProvider,
3
- meta_default,
4
- parseSurfacePlugin
5
- } from "./chunk-YYV26N3W.mjs";
6
- import {
7
- filterPlugins
8
- } from "./chunk-S5CI6EUQ.mjs";
9
-
10
- // packages/sdk/app-framework/src/plugins/SurfacePlugin/plugin.tsx
11
- import React from "react";
12
- import { create } from "@dxos/echo-schema";
13
- var SurfacePlugin = () => {
14
- const state = create({
15
- components: {}
16
- });
17
- return {
18
- meta: meta_default,
19
- ready: async (plugins) => {
20
- state.components = filterPlugins(plugins, parseSurfacePlugin).reduce((acc, plugin) => {
21
- return {
22
- ...acc,
23
- [plugin.meta.id]: plugin.provides.surface.component
24
- };
25
- }, {});
26
- },
27
- provides: {
28
- surface: state,
29
- context: ({ children }) => /* @__PURE__ */ React.createElement(SurfaceProvider, {
30
- value: state
31
- }, children)
32
- }
33
- };
34
- };
35
- var plugin_default = SurfacePlugin;
36
- export {
37
- plugin_default as default
38
- };
39
- //# sourceMappingURL=plugin-K3KCPCTJ.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/plugins/SurfacePlugin/plugin.tsx"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport React from 'react';\n\nimport { create } from '@dxos/echo-schema';\n\nimport { SurfaceProvider, type SurfaceRootContext } from './SurfaceRootContext';\nimport SurfaceMeta from './meta';\nimport { parseSurfacePlugin, type SurfacePluginProvides } from './provides';\nimport type { PluginDefinition } from '../PluginHost';\nimport { filterPlugins } from '../helpers';\n\n/**\n * Provides a registry of surface components.\n */\nconst SurfacePlugin = (): PluginDefinition<SurfacePluginProvides> => {\n const state = create<SurfaceRootContext>({ components: {} });\n\n return {\n meta: SurfaceMeta,\n ready: async (plugins) => {\n state.components = filterPlugins(plugins, parseSurfacePlugin).reduce((acc, plugin) => {\n return { ...acc, [plugin.meta.id]: plugin.provides.surface.component };\n }, {});\n },\n provides: {\n surface: state,\n context: ({ children }) => <SurfaceProvider value={state}>{children}</SurfaceProvider>,\n },\n };\n};\n\nexport default SurfacePlugin;\n"],
5
- "mappings": ";;;;;;;;;;AAIA,OAAOA,WAAW;AAElB,SAASC,cAAc;AAWvB,IAAMC,gBAAgB,MAAA;AACpB,QAAMC,QAAQC,OAA2B;IAAEC,YAAY,CAAC;EAAE,CAAA;AAE1D,SAAO;IACLC,MAAMC;IACNC,OAAO,OAAOC,YAAAA;AACZN,YAAME,aAAaK,cAAcD,SAASE,kBAAAA,EAAoBC,OAAO,CAACC,KAAKC,WAAAA;AACzE,eAAO;UAAE,GAAGD;UAAK,CAACC,OAAOR,KAAKS,EAAE,GAAGD,OAAOE,SAASC,QAAQC;QAAU;MACvE,GAAG,CAAC,CAAA;IACN;IACAF,UAAU;MACRC,SAASd;MACTgB,SAAS,CAAC,EAAEC,SAAQ,MAAO,sBAAA,cAACC,iBAAAA;QAAgBC,OAAOnB;SAAQiB,QAAAA;IAC7D;EACF;AACF;AAEA,IAAA,iBAAelB;",
6
- "names": ["React", "create", "SurfacePlugin", "state", "create", "components", "meta", "SurfaceMeta", "ready", "plugins", "filterPlugins", "parseSurfacePlugin", "reduce", "acc", "plugin", "id", "provides", "surface", "component", "context", "children", "SurfaceProvider", "value"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/plugins/IntentPlugin/plugin.tsx", "../../../src/plugins/IntentPlugin/helpers.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport React from 'react';\n\nimport { create } from '@dxos/echo-schema';\nimport { log } from '@dxos/log';\n\nimport { type IntentContext, IntentProvider, type IntentExecution } from './IntentContext';\nimport { isUndoable } from './helpers';\nimport type { Intent, IntentResolver } from './intent';\nimport IntentMeta from './meta';\nimport {\n type IntentPluginProvides,\n type IntentResolverProvides,\n parseIntentResolverPlugin,\n IntentAction,\n} from './provides';\nimport type { PluginDefinition } from '../PluginHost';\nimport { filterPlugins, findPlugin } from '../helpers';\n\nconst EXECUTION_LIMIT = 1000;\nconst HISTORY_LIMIT = 100;\n\n/**\n * Allows plugins to register intent handlers and routes sent intents to the appropriate plugin.\n * Inspired by https://developer.android.com/reference/android/content/Intent.\n */\nconst IntentPlugin = (): PluginDefinition<IntentPluginProvides> => {\n const state = create<IntentContext>({\n dispatch: async () => ({}),\n undo: async () => ({}),\n history: [],\n registerResolver: () => () => {},\n });\n\n const dynamicResolvers = new Set<{ plugin: string; resolver: IntentResolver }>();\n\n return {\n meta: IntentMeta,\n ready: async (plugins) => {\n // Dispatch intent to associated plugin.\n const dispatch = async (intent: Intent) => {\n log('dispatch', { action: intent.action, intent });\n if (intent.plugin) {\n for (const entry of dynamicResolvers) {\n if (entry.plugin === intent.plugin) {\n const result = await entry.resolver(intent, plugins);\n if (result) {\n return result;\n }\n }\n }\n\n const plugin = findPlugin<IntentResolverProvides>(plugins, intent.plugin);\n const result = plugin?.provides.intent.resolver(intent, plugins);\n return result;\n }\n\n for (const entry of dynamicResolvers) {\n const result = await entry.resolver(intent, plugins);\n if (result) {\n return result;\n }\n }\n\n // Return resolved value from first plugin that handles the intent.\n for (const plugin of filterPlugins(plugins, parseIntentResolverPlugin)) {\n const result = await plugin.provides.intent.resolver(intent, plugins);\n if (result) {\n return result;\n }\n }\n\n // https://vitejs.dev/guide/env-and-mode#env-variables\n // TODO(wittjosiah): How to handle this more generically?\n if (import.meta?.env?.DEV) {\n log.warn('No plugin found to handle intent', intent);\n }\n };\n\n // Sequentially dispatch array of invents.\n const dispatchChain = async (intentOrArray: Intent | Intent[], depth = 0) => {\n if (depth > EXECUTION_LIMIT) {\n return {\n error: new Error(\n `Intent execution limit exceeded (${EXECUTION_LIMIT} iterations). This is likely due to an infinite loop within intent resolvers.`,\n ),\n };\n }\n\n const executionResults: IntentExecution[] = [];\n const chain = Array.isArray(intentOrArray) ? intentOrArray : [intentOrArray];\n for (const intent of chain) {\n const { result: prevResult } = executionResults.at(-1) ?? {};\n const data = intent.data ? { result: prevResult?.data, ...intent.data } : prevResult?.data;\n const result = await dispatch({ ...intent, data });\n\n if (!result || result?.error) {\n break;\n }\n\n executionResults.push({ intent, result });\n\n // TODO(wittjosiah): How does undo work with returned intents?\n result?.intents?.forEach((intents) => {\n void dispatchChain(intents, depth + 1);\n });\n }\n\n state.history.push(executionResults);\n if (state.history.length > HISTORY_LIMIT) {\n state.history.splice(0, state.history.length - HISTORY_LIMIT);\n }\n\n if (isUndoable(executionResults)) {\n void dispatch({ action: IntentAction.SHOW_UNDO, data: { results: executionResults } });\n }\n\n return executionResults.at(-1)?.result;\n };\n\n const undo = async () => {\n const last = state.history.findLastIndex(isUndoable);\n const chain =\n last !== -1 &&\n state.history[last]?.map(({ intent, result }): Intent => {\n const data = result.undoable?.data ? { ...intent.data, ...result.undoable.data } : intent.data;\n return { ...intent, data, undo: true };\n });\n if (chain) {\n const result = await dispatchChain(chain);\n state.history = state.history.filter((_, index) => index !== last);\n return result;\n }\n };\n\n state.dispatch = dispatchChain;\n state.undo = undo;\n state.registerResolver = (plugin, resolver) => {\n const entry = { plugin, resolver };\n dynamicResolvers.add(entry);\n return () => dynamicResolvers.delete(entry);\n };\n },\n provides: {\n intent: state,\n context: ({ children }) => <IntentProvider value={state}>{children}</IntentProvider>,\n },\n };\n};\n\nexport default IntentPlugin;\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { type IntentExecution } from './IntentContext';\n\n/**\n * Check if the chain of intents is undoable.\n */\nexport const isUndoable = (chain: IntentExecution[]): boolean =>\n chain.length > 0 && chain.every(({ result }) => result.undoable);\n"],
5
- "mappings": "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",
6
- "names": ["React", "create", "log", "isUndoable", "chain", "length", "every", "result", "undoable", "EXECUTION_LIMIT", "HISTORY_LIMIT", "IntentPlugin", "state", "create", "dispatch", "undo", "history", "registerResolver", "dynamicResolvers", "Set", "meta", "IntentMeta", "ready", "plugins", "intent", "log", "action", "plugin", "entry", "result", "resolver", "findPlugin", "provides", "filterPlugins", "parseIntentResolverPlugin", "env", "DEV", "warn", "dispatchChain", "intentOrArray", "depth", "error", "Error", "executionResults", "chain", "Array", "isArray", "prevResult", "at", "data", "push", "intents", "forEach", "length", "splice", "isUndoable", "IntentAction", "SHOW_UNDO", "results", "last", "findLastIndex", "map", "undoable", "filter", "_", "index", "add", "delete", "context", "children", "IntentProvider", "value"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/plugins/helpers.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { raise } from '@dxos/debug';\n\nimport { type Plugin } from './PluginHost';\n\n/**\n * Define a plugin\n */\nexport const definePlugin = <TProvides>(plugin: Plugin<TProvides>): Plugin<TProvides> => plugin;\n\n/**\n * Find a plugin by ID.\n */\nexport const findPlugin = <T>(plugins: Plugin[], id: string): Plugin<T> | undefined => {\n return plugins.find(\n (plugin) => plugin.meta.id === id || (typeof plugin.meta.shortId === 'string' && plugin.meta.shortId === id),\n ) as Plugin<T>;\n};\n\n/**\n * Find a plugin by ID, or raise an error if not found.\n */\nexport const getPlugin = <T>(plugins: Plugin[], id: string): Plugin<T> => {\n return findPlugin(plugins, id) ?? raise(new Error(`Plugin not found: ${id}`));\n};\n\n/**\n * Filter a list of plugins to only those that match a predicate.\n */\nexport const filterPlugins = <T>(\n plugins: Plugin[],\n predicate: (plugin: Plugin) => Plugin<T> | undefined,\n): Plugin<T>[] => plugins.map((plugin) => predicate(plugin)).filter((plugin): plugin is Plugin<T> => !!plugin);\n\n/**\n * Resolves a plugin by predicate.\n *\n * @example\n * import { parseIntentPlugin, resolvePlugin } from '@dxos/app-framework';\n * const intentPlugin = resolvePlugin(plugins, parseIntentPlugin);\n */\nexport const resolvePlugin = <T>(\n plugins: Plugin[],\n predicate: (plugin: Plugin) => Plugin<T> | undefined,\n): Plugin<T> | undefined => filterPlugins(plugins, predicate)[0];\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,mBAAsB;AAOf,IAAMA,eAAe,CAAYC,WAAiDA;AAKlF,IAAMC,aAAa,CAAIC,SAAmBC,OAAAA;AAC/C,SAAOD,QAAQE,KACb,CAACJ,WAAWA,OAAOK,KAAKF,OAAOA,MAAO,OAAOH,OAAOK,KAAKC,YAAY,YAAYN,OAAOK,KAAKC,YAAYH,EAAAA;AAE7G;AAKO,IAAMI,YAAY,CAAIL,SAAmBC,OAAAA;AAC9C,SAAOF,WAAWC,SAASC,EAAAA,SAAOK,oBAAM,IAAIC,MAAM,qBAAqBN,EAAAA,EAAI,CAAA;AAC7E;AAKO,IAAMO,gBAAgB,CAC3BR,SACAS,cACgBT,QAAQU,IAAI,CAACZ,WAAWW,UAAUX,MAAAA,CAAAA,EAASa,OAAO,CAACb,WAAgC,CAAC,CAACA,MAAAA;AAShG,IAAMc,gBAAgB,CAC3BZ,SACAS,cAC0BD,cAAcR,SAASS,SAAAA,EAAW,CAAA;",
6
- "names": ["definePlugin", "plugin", "findPlugin", "plugins", "id", "find", "meta", "shortId", "getPlugin", "raise", "Error", "filterPlugins", "predicate", "map", "filter", "resolvePlugin"]
7
- }