@dxos/app-framework 0.7.5-labs.e27f9b9 → 0.7.5-main.2567c87

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 (184) hide show
  1. package/dist/lib/browser/{chunk-G3HBVVT5.mjs → chunk-GNLU3GAU.mjs} +819 -627
  2. package/dist/lib/browser/chunk-GNLU3GAU.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +74 -57
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +3 -10
  7. package/dist/lib/browser/testing/index.mjs.map +3 -3
  8. package/dist/lib/node/chunk-FBA4BB3J.cjs +1639 -0
  9. package/dist/lib/node/chunk-FBA4BB3J.cjs.map +7 -0
  10. package/dist/lib/node/index.cjs +118 -106
  11. package/dist/lib/node/index.cjs.map +4 -4
  12. package/dist/lib/node/meta.json +1 -1
  13. package/dist/lib/node/testing/index.cjs +8 -15
  14. package/dist/lib/node/testing/index.cjs.map +3 -3
  15. package/dist/lib/node-esm/{chunk-ZTB4TA6Q.mjs → chunk-KPMTPXQI.mjs} +819 -627
  16. package/dist/lib/node-esm/chunk-KPMTPXQI.mjs.map +7 -0
  17. package/dist/lib/node-esm/index.mjs +74 -57
  18. package/dist/lib/node-esm/index.mjs.map +4 -4
  19. package/dist/lib/node-esm/meta.json +1 -1
  20. package/dist/lib/node-esm/testing/index.mjs +3 -10
  21. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  22. package/dist/types/src/App.d.ts.map +1 -1
  23. package/dist/types/src/common/capabilities.d.ts +110 -66
  24. package/dist/types/src/common/capabilities.d.ts.map +1 -1
  25. package/dist/types/src/common/events.d.ts +1 -8
  26. package/dist/types/src/common/events.d.ts.map +1 -1
  27. package/dist/types/src/common/file.d.ts +1 -1
  28. package/dist/types/src/common/file.d.ts.map +1 -1
  29. package/dist/types/src/common/graph.d.ts +2 -2
  30. package/dist/types/src/common/graph.d.ts.map +1 -1
  31. package/dist/types/src/common/index.d.ts +1 -0
  32. package/dist/types/src/common/index.d.ts.map +1 -1
  33. package/dist/types/src/common/layout.d.ts +121 -204
  34. package/dist/types/src/common/layout.d.ts.map +1 -1
  35. package/dist/types/src/common/navigation.d.ts +241 -0
  36. package/dist/types/src/common/navigation.d.ts.map +1 -0
  37. package/dist/types/src/common/surface.d.ts +3 -3
  38. package/dist/types/src/common/surface.d.ts.map +1 -1
  39. package/dist/types/src/common/translations.d.ts +7 -7
  40. package/dist/types/src/common/translations.d.ts.map +1 -1
  41. package/dist/types/src/core/capabilities.d.ts +2 -6
  42. package/dist/types/src/core/capabilities.d.ts.map +1 -1
  43. package/dist/types/src/core/manager.d.ts +9 -2
  44. package/dist/types/src/core/manager.d.ts.map +1 -1
  45. package/dist/types/src/core/plugin.d.ts +2 -5
  46. package/dist/types/src/core/plugin.d.ts.map +1 -1
  47. package/dist/types/src/playground/generator/Toolbar.d.ts.map +1 -1
  48. package/dist/types/src/playground/generator/generator.d.ts +0 -2
  49. package/dist/types/src/playground/generator/generator.d.ts.map +1 -1
  50. package/dist/types/src/playground/generator/plugin.d.ts.map +1 -1
  51. package/dist/types/src/playground/logger/Toolbar.d.ts.map +1 -1
  52. package/dist/types/src/playground/logger/plugin.d.ts.map +1 -1
  53. package/dist/types/src/playground/logger/schema.d.ts +1 -1
  54. package/dist/types/src/playground/logger/schema.d.ts.map +1 -1
  55. package/dist/types/src/{react → plugin-intent}/IntentContext.d.ts +1 -1
  56. package/dist/types/src/plugin-intent/IntentContext.d.ts.map +1 -0
  57. package/dist/types/src/plugin-intent/IntentPlugin.d.ts.map +1 -1
  58. package/dist/types/src/plugin-intent/actions.d.ts +1 -1
  59. package/dist/types/src/plugin-intent/actions.d.ts.map +1 -1
  60. package/dist/types/src/plugin-intent/index.d.ts +1 -0
  61. package/dist/types/src/plugin-intent/index.d.ts.map +1 -1
  62. package/dist/types/src/plugin-intent/intent-dispatcher.d.ts +20 -27
  63. package/dist/types/src/plugin-intent/intent-dispatcher.d.ts.map +1 -1
  64. package/dist/types/src/plugin-intent/intent.d.ts +3 -3
  65. package/dist/types/src/plugin-intent/intent.d.ts.map +1 -1
  66. package/dist/types/src/plugin-settings/SettingsPlugin.d.ts.map +1 -1
  67. package/dist/types/src/plugin-settings/actions.d.ts +1 -11
  68. package/dist/types/src/plugin-settings/actions.d.ts.map +1 -1
  69. package/dist/types/src/react/Surface.d.ts.map +1 -1
  70. package/dist/types/src/react/index.d.ts +0 -2
  71. package/dist/types/src/react/index.d.ts.map +1 -1
  72. package/dist/types/src/react/useCapabilities.d.ts.map +1 -1
  73. package/dist/types/src/testing/withPluginManager.d.ts +1 -1
  74. package/dist/types/src/testing/withPluginManager.d.ts.map +1 -1
  75. package/package.json +21 -28
  76. package/project.json +3 -3
  77. package/src/App.tsx +14 -15
  78. package/src/common/capabilities.ts +11 -26
  79. package/src/common/events.ts +1 -10
  80. package/src/common/file.ts +1 -1
  81. package/src/common/graph.ts +2 -2
  82. package/src/common/index.ts +1 -0
  83. package/src/common/layout.ts +126 -194
  84. package/src/common/navigation.ts +199 -0
  85. package/src/common/surface.ts +2 -2
  86. package/src/common/translations.ts +8 -7
  87. package/src/core/capabilities.ts +7 -16
  88. package/src/core/manager.test.ts +73 -22
  89. package/src/core/manager.ts +91 -105
  90. package/src/core/plugin.ts +3 -6
  91. package/src/playground/debug/plugin.ts +1 -1
  92. package/src/playground/generator/Toolbar.tsx +11 -11
  93. package/src/playground/generator/generator.ts +0 -25
  94. package/src/playground/generator/plugin.ts +1 -6
  95. package/src/playground/layout/plugin.ts +1 -1
  96. package/src/playground/logger/Toolbar.tsx +1 -2
  97. package/src/playground/logger/plugin.ts +3 -6
  98. package/src/playground/logger/schema.ts +1 -1
  99. package/src/{react → plugin-intent}/IntentContext.tsx +2 -2
  100. package/src/plugin-intent/IntentPlugin.tsx +43 -3
  101. package/src/plugin-intent/actions.ts +1 -1
  102. package/src/plugin-intent/errors.ts +1 -1
  103. package/src/plugin-intent/index.ts +1 -0
  104. package/src/plugin-intent/intent-dispatcher.test.ts +29 -48
  105. package/src/plugin-intent/intent-dispatcher.ts +41 -76
  106. package/src/plugin-intent/intent.ts +5 -5
  107. package/src/plugin-settings/SettingsPlugin.ts +13 -19
  108. package/src/plugin-settings/actions.ts +1 -11
  109. package/src/react/Surface.tsx +8 -11
  110. package/src/react/index.ts +0 -2
  111. package/src/react/useCapabilities.ts +0 -1
  112. package/src/testing/withPluginManager.tsx +3 -11
  113. package/tsconfig.json +3 -6
  114. package/dist/lib/browser/app-graph-builder-MOLT4EHG.mjs +0 -137
  115. package/dist/lib/browser/app-graph-builder-MOLT4EHG.mjs.map +0 -7
  116. package/dist/lib/browser/chunk-G3HBVVT5.mjs.map +0 -7
  117. package/dist/lib/browser/chunk-LDJ3T4V3.mjs +0 -32
  118. package/dist/lib/browser/chunk-LDJ3T4V3.mjs.map +0 -7
  119. package/dist/lib/browser/chunk-TGOF2WQZ.mjs +0 -285
  120. package/dist/lib/browser/chunk-TGOF2WQZ.mjs.map +0 -7
  121. package/dist/lib/browser/intent-dispatcher-LJKNIGAM.mjs +0 -11
  122. package/dist/lib/browser/intent-dispatcher-LJKNIGAM.mjs.map +0 -7
  123. package/dist/lib/browser/intent-resolver-Z724VAMC.mjs +0 -38
  124. package/dist/lib/browser/intent-resolver-Z724VAMC.mjs.map +0 -7
  125. package/dist/lib/browser/store-NWCY7LAP.mjs +0 -19
  126. package/dist/lib/browser/store-NWCY7LAP.mjs.map +0 -7
  127. package/dist/lib/browser/worker.mjs +0 -77
  128. package/dist/lib/browser/worker.mjs.map +0 -7
  129. package/dist/lib/node/app-graph-builder-G7SRXDFD.cjs +0 -146
  130. package/dist/lib/node/app-graph-builder-G7SRXDFD.cjs.map +0 -7
  131. package/dist/lib/node/chunk-55KIQ6YK.cjs +0 -1437
  132. package/dist/lib/node/chunk-55KIQ6YK.cjs.map +0 -7
  133. package/dist/lib/node/chunk-5GABBW2Q.cjs +0 -308
  134. package/dist/lib/node/chunk-5GABBW2Q.cjs.map +0 -7
  135. package/dist/lib/node/chunk-QLVQ6PND.cjs +0 -58
  136. package/dist/lib/node/chunk-QLVQ6PND.cjs.map +0 -7
  137. package/dist/lib/node/intent-dispatcher-CGUK3BCJ.cjs +0 -32
  138. package/dist/lib/node/intent-dispatcher-CGUK3BCJ.cjs.map +0 -7
  139. package/dist/lib/node/intent-resolver-7GNKPRWT.cjs +0 -45
  140. package/dist/lib/node/intent-resolver-7GNKPRWT.cjs.map +0 -7
  141. package/dist/lib/node/store-WMJSEQPC.cjs +0 -34
  142. package/dist/lib/node/store-WMJSEQPC.cjs.map +0 -7
  143. package/dist/lib/node/worker.cjs +0 -99
  144. package/dist/lib/node/worker.cjs.map +0 -7
  145. package/dist/lib/node-esm/app-graph-builder-MKLYH3NE.mjs +0 -138
  146. package/dist/lib/node-esm/app-graph-builder-MKLYH3NE.mjs.map +0 -7
  147. package/dist/lib/node-esm/chunk-47FG42II.mjs +0 -286
  148. package/dist/lib/node-esm/chunk-47FG42II.mjs.map +0 -7
  149. package/dist/lib/node-esm/chunk-CNJYZNSL.mjs +0 -34
  150. package/dist/lib/node-esm/chunk-CNJYZNSL.mjs.map +0 -7
  151. package/dist/lib/node-esm/chunk-ZTB4TA6Q.mjs.map +0 -7
  152. package/dist/lib/node-esm/intent-dispatcher-RZAWA4XD.mjs +0 -12
  153. package/dist/lib/node-esm/intent-dispatcher-RZAWA4XD.mjs.map +0 -7
  154. package/dist/lib/node-esm/intent-resolver-UIU37CKJ.mjs +0 -39
  155. package/dist/lib/node-esm/intent-resolver-UIU37CKJ.mjs.map +0 -7
  156. package/dist/lib/node-esm/store-YUWINFBN.mjs +0 -20
  157. package/dist/lib/node-esm/store-YUWINFBN.mjs.map +0 -7
  158. package/dist/lib/node-esm/worker.mjs +0 -78
  159. package/dist/lib/node-esm/worker.mjs.map +0 -7
  160. package/dist/types/src/plugin-settings/app-graph-builder.d.ts +0 -197
  161. package/dist/types/src/plugin-settings/app-graph-builder.d.ts.map +0 -1
  162. package/dist/types/src/plugin-settings/intent-resolver.d.ts +0 -4
  163. package/dist/types/src/plugin-settings/intent-resolver.d.ts.map +0 -1
  164. package/dist/types/src/plugin-settings/store.d.ts +0 -5
  165. package/dist/types/src/plugin-settings/store.d.ts.map +0 -1
  166. package/dist/types/src/plugin-settings/translations.d.ts +0 -11
  167. package/dist/types/src/plugin-settings/translations.d.ts.map +0 -1
  168. package/dist/types/src/react/IntentContext.d.ts.map +0 -1
  169. package/dist/types/src/react/Surface.stories.d.ts +0 -16
  170. package/dist/types/src/react/Surface.stories.d.ts.map +0 -1
  171. package/dist/types/src/react/common.d.ts +0 -12
  172. package/dist/types/src/react/common.d.ts.map +0 -1
  173. package/dist/types/src/react/useIntentResolver.d.ts +0 -3
  174. package/dist/types/src/react/useIntentResolver.d.ts.map +0 -1
  175. package/dist/types/src/worker.d.ts +0 -4
  176. package/dist/types/src/worker.d.ts.map +0 -1
  177. package/src/plugin-settings/app-graph-builder.ts +0 -122
  178. package/src/plugin-settings/intent-resolver.ts +0 -28
  179. package/src/plugin-settings/store.ts +0 -20
  180. package/src/plugin-settings/translations.ts +0 -17
  181. package/src/react/Surface.stories.tsx +0 -96
  182. package/src/react/common.ts +0 -12
  183. package/src/react/useIntentResolver.ts +0 -22
  184. package/src/worker.ts +0 -11
@@ -1,94 +1,3 @@
1
- // packages/sdk/app-framework/src/plugin-intent/intent-dispatcher.ts
2
- import { Effect as Effect2, Option, pipe as pipe2, Ref } from "effect";
3
- import { create as create3 } from "@dxos/live-object";
4
- import { byPosition } from "@dxos/util";
5
-
6
- // packages/sdk/app-framework/src/plugin-intent/actions.ts
7
- import { Schema as S2 } from "@effect/schema";
8
-
9
- // packages/sdk/app-framework/src/plugin-intent/intent.ts
10
- import { Schema as S } from "@effect/schema";
11
- var createIntent = (schema, data = {}, params = {}) => {
12
- const _ = S.validateSync(schema.fields.input)(data);
13
- const intent = {
14
- ...params,
15
- _schema: schema,
16
- id: schema._tag,
17
- data
18
- };
19
- return {
20
- first: intent,
21
- last: intent,
22
- all: [
23
- intent
24
- ]
25
- };
26
- };
27
- var chain = (schema, data = {}, params = {}) => (intent) => {
28
- const intents = "all" in intent ? intent.all : [
29
- intent
30
- ];
31
- const first = intents[0];
32
- const last = {
33
- ...params,
34
- _schema: schema,
35
- id: schema._tag,
36
- data
37
- };
38
- return {
39
- first,
40
- last,
41
- all: [
42
- ...intents,
43
- last
44
- ]
45
- };
46
- };
47
- var Label = S.Union(S.String, S.mutable(S.Tuple(S.String, S.mutable(S.Struct({
48
- ns: S.String,
49
- count: S.optional(S.Number)
50
- })))));
51
-
52
- // packages/sdk/app-framework/src/plugin-intent/actions.ts
53
- var INTENT_PLUGIN = "dxos.org/plugin/intent";
54
- var INTENT_ACTION = `${INTENT_PLUGIN}/action`;
55
- var IntentAction;
56
- (function(IntentAction2) {
57
- class ShowUndo extends S2.TaggedClass()(`${INTENT_ACTION}/show-undo`, {
58
- input: S2.Struct({
59
- message: Label
60
- }),
61
- output: S2.Void
62
- }) {
63
- }
64
- IntentAction2.ShowUndo = ShowUndo;
65
- })(IntentAction || (IntentAction = {}));
66
-
67
- // packages/sdk/app-framework/src/plugin-intent/errors.ts
68
- var BaseError = class extends Error {
69
- constructor(code, message, context) {
70
- super(message ?? code, {
71
- cause: context
72
- });
73
- this.code = code;
74
- this.context = context;
75
- this.name = code;
76
- Object.setPrototypeOf(this, new.target.prototype);
77
- }
78
- };
79
- var NoResolversError = class extends BaseError {
80
- constructor(action) {
81
- super("NO_RESOLVERS", "No resolvers were found for the action", {
82
- action
83
- });
84
- }
85
- };
86
- var CycleDetectedError = class extends BaseError {
87
- constructor(context) {
88
- super("CYCLE_DETECTED", "Intent execution limit exceeded. This is likely due to an infinite loop within intent resolvers.", context);
89
- }
90
- };
91
-
92
1
  // packages/sdk/app-framework/src/core/capabilities.ts
93
2
  import { effect, untracked } from "@preact/signals-core";
94
3
  import { Trigger } from "@dxos/async";
@@ -115,10 +24,9 @@ var contributes = (interfaceDef, implementation, deactivate) => {
115
24
  deactivate
116
25
  };
117
26
  };
118
- var lazy = (c) => async (props) => {
119
- const { default: getCapability } = await c();
120
- return async () => getCapability(props);
121
- };
27
+ var lazy = (c) => (props) => c().then(({ default: getCapability }) => {
28
+ return getCapability(props);
29
+ });
122
30
  var PluginsContext = class {
123
31
  constructor({ activate, reset }) {
124
32
  this._definedCapabilities = /* @__PURE__ */ new Map();
@@ -140,11 +48,10 @@ var PluginsContext = class {
140
48
  current.push(new CapabilityImpl(moduleId, implementation));
141
49
  log("capability contributed", {
142
50
  id: interfaceDef.identifier,
143
- moduleId,
144
51
  count: untracked(() => current.length)
145
52
  }, {
146
53
  F: __dxlog_file,
147
- L: 142,
54
+ L: 139,
148
55
  S: this,
149
56
  C: (f, a) => f(...a)
150
57
  });
@@ -165,16 +72,7 @@ var PluginsContext = class {
165
72
  count: untracked(() => current.length)
166
73
  }, {
167
74
  F: __dxlog_file,
168
- L: 161,
169
- S: this,
170
- C: (f, a) => f(...a)
171
- });
172
- } else {
173
- log.warn("capability not removed", {
174
- id: interfaceDef.identifier
175
- }, {
176
- F: __dxlog_file,
177
- L: 163,
75
+ L: 154,
178
76
  S: this,
179
77
  C: (f, a) => f(...a)
180
78
  });
@@ -207,7 +105,7 @@ var PluginsContext = class {
207
105
  const capability = this.requestCapabilities(interfaceDef, filter)[0];
208
106
  invariant(capability, `No capability found for ${interfaceDef.identifier}`, {
209
107
  F: __dxlog_file,
210
- L: 199,
108
+ L: 190,
211
109
  S: this,
212
110
  A: [
213
111
  "capability",
@@ -258,7 +156,7 @@ var getEvents = (events) => "type" in events ? events.events : [
258
156
 
259
157
  // packages/sdk/app-framework/src/core/manager.ts
260
158
  import { untracked as untracked2 } from "@preact/signals-core";
261
- import { Array as A, Effect, Either, Match, pipe } from "effect";
159
+ import { Effect, Either, Match } from "effect";
262
160
  import { Event } from "@dxos/async";
263
161
  import { create as create2 } from "@dxos/live-object";
264
162
  import { log as log2 } from "@dxos/log";
@@ -281,6 +179,7 @@ var PluginManager = class {
281
179
  enabled,
282
180
  modules: [],
283
181
  active: [],
182
+ pendingRemoval: [],
284
183
  pendingReset: [],
285
184
  eventsFired: []
286
185
  });
@@ -329,6 +228,14 @@ var PluginManager = class {
329
228
  return this._state.active;
330
229
  }
331
230
  /**
231
+ * Ids of modules which are pending removal.
232
+ *
233
+ * @reactive
234
+ */
235
+ get pendingRemoval() {
236
+ return this._state.pendingRemoval;
237
+ }
238
+ /**
332
239
  * Ids of events which have been fired.
333
240
  *
334
241
  * @reactive
@@ -354,7 +261,7 @@ var PluginManager = class {
354
261
  id
355
262
  }, {
356
263
  F: __dxlog_file2,
357
- L: 146,
264
+ L: 157,
358
265
  S: this,
359
266
  C: (f, a) => f(...a)
360
267
  });
@@ -368,12 +275,12 @@ var PluginManager = class {
368
275
  * @param id The id of the plugin.
369
276
  */
370
277
  enable(id) {
371
- return untracked2(async () => {
278
+ return untracked2(() => {
372
279
  log2("enable plugin", {
373
280
  id
374
281
  }, {
375
282
  F: __dxlog_file2,
376
- L: 159,
283
+ L: 170,
377
284
  S: this,
378
285
  C: (f, a) => f(...a)
379
286
  });
@@ -388,19 +295,6 @@ var PluginManager = class {
388
295
  this._addModule(module);
389
296
  this._setPendingResetByModule(module);
390
297
  });
391
- log2("pending reset", {
392
- events: [
393
- ...this.pendingReset
394
- ]
395
- }, {
396
- F: __dxlog_file2,
397
- L: 174,
398
- S: this,
399
- C: (f, a) => f(...a)
400
- });
401
- await Effect.runPromise(Effect.all(this.pendingReset.map((event) => this._activate(event)), {
402
- concurrency: "unbounded"
403
- }));
404
298
  return true;
405
299
  });
406
300
  }
@@ -414,7 +308,7 @@ var PluginManager = class {
414
308
  id
415
309
  }, {
416
310
  F: __dxlog_file2,
417
- L: 192,
311
+ L: 194,
418
312
  S: this,
419
313
  C: (f, a) => f(...a)
420
314
  });
@@ -431,12 +325,12 @@ var PluginManager = class {
431
325
  * @param id The id of the plugin.
432
326
  */
433
327
  disable(id) {
434
- return untracked2(async () => {
328
+ return untracked2(() => {
435
329
  log2("disable plugin", {
436
330
  id
437
331
  }, {
438
332
  F: __dxlog_file2,
439
- L: 209,
333
+ L: 211,
440
334
  S: this,
441
335
  C: (f, a) => f(...a)
442
336
  });
@@ -450,9 +344,15 @@ var PluginManager = class {
450
344
  const enabledIndex = this._state.enabled.findIndex((enabled) => enabled === id);
451
345
  if (enabledIndex !== -1) {
452
346
  this._state.enabled.splice(enabledIndex, 1);
453
- await Effect.runPromise(this._deactivate(id));
454
347
  plugin.modules.forEach((module) => {
455
- this._removeModule(module.id);
348
+ if (this._state.active.includes(module.id)) {
349
+ this._setPendingResetByModule(module);
350
+ if (!this._state.pendingRemoval.includes(module.id)) {
351
+ this._state.pendingRemoval.push(module.id);
352
+ }
353
+ } else {
354
+ this._removeModule(module.id);
355
+ }
456
356
  });
457
357
  }
458
358
  return true;
@@ -488,7 +388,7 @@ var PluginManager = class {
488
388
  id: plugin.meta.id
489
389
  }, {
490
390
  F: __dxlog_file2,
491
- L: 262,
391
+ L: 270,
492
392
  S: this,
493
393
  C: (f, a) => f(...a)
494
394
  });
@@ -503,7 +403,7 @@ var PluginManager = class {
503
403
  id
504
404
  }, {
505
405
  F: __dxlog_file2,
506
- L: 271,
406
+ L: 279,
507
407
  S: this,
508
408
  C: (f, a) => f(...a)
509
409
  });
@@ -519,7 +419,7 @@ var PluginManager = class {
519
419
  id: module.id
520
420
  }, {
521
421
  F: __dxlog_file2,
522
- L: 281,
422
+ L: 289,
523
423
  S: this,
524
424
  C: (f, a) => f(...a)
525
425
  });
@@ -534,7 +434,7 @@ var PluginManager = class {
534
434
  id
535
435
  }, {
536
436
  F: __dxlog_file2,
537
- L: 290,
437
+ L: 298,
538
438
  S: this,
539
439
  C: (f, a) => f(...a)
540
440
  });
@@ -562,13 +462,20 @@ var PluginManager = class {
562
462
  _setPendingResetByModule(module) {
563
463
  return untracked2(() => {
564
464
  const activationEvents = getEvents(module.activatesOn).map(eventKey).filter((key) => this._state.eventsFired.includes(key));
565
- const pendingReset = Array.from(new Set(activationEvents)).filter((event) => !this._state.pendingReset.includes(event));
465
+ const parentEvents = activationEvents.flatMap((event) => {
466
+ const modules = this._getActiveModules().filter((module2) => module2.activatesBefore?.map(eventKey).includes(event));
467
+ return modules.flatMap((module2) => getEvents(module2.activatesOn)).map(eventKey);
468
+ });
469
+ const pendingReset = Array.from(/* @__PURE__ */ new Set([
470
+ ...activationEvents,
471
+ ...parentEvents
472
+ ])).filter((event) => !this._state.pendingReset.includes(event));
566
473
  if (pendingReset.length > 0) {
567
474
  log2("pending reset", {
568
475
  events: pendingReset
569
476
  }, {
570
477
  F: __dxlog_file2,
571
- L: 328,
478
+ L: 342,
572
479
  S: this,
573
480
  C: (f, a) => f(...a)
574
481
  });
@@ -576,87 +483,59 @@ var PluginManager = class {
576
483
  }
577
484
  });
578
485
  }
579
- /**
580
- * @internal
581
- */
582
486
  // TODO(wittjosiah): Improve error typing.
583
487
  _activate(event) {
584
- return Effect.gen(this, function* () {
488
+ const self = this;
489
+ return Effect.gen(function* () {
585
490
  const key = typeof event === "string" ? event : eventKey(event);
586
491
  log2("activating", {
587
492
  key
588
493
  }, {
589
494
  F: __dxlog_file2,
590
- L: 341,
495
+ L: 353,
591
496
  S: this,
592
497
  C: (f, a) => f(...a)
593
498
  });
594
- const pendingIndex = this._state.pendingReset.findIndex((event2) => event2 === key);
499
+ const pendingIndex = self._state.pendingReset.findIndex((event2) => event2 === key);
595
500
  if (pendingIndex !== -1) {
596
- this._state.pendingReset.splice(pendingIndex, 1);
501
+ self._state.pendingReset.splice(pendingIndex, 1);
597
502
  }
598
- const modules = this._getInactiveModulesByEvent(key).filter((module) => {
599
- const allOf2 = isAllOf(module.activatesOn);
600
- if (!allOf2) {
601
- return true;
602
- }
603
- const events = module.activatesOn.events.filter((event2) => eventKey(event2) !== key);
604
- return events.every((event2) => this._state.eventsFired.includes(eventKey(event2)));
605
- });
503
+ const modules = self._getInactiveModulesByEvent(key);
606
504
  if (modules.length === 0) {
607
505
  log2("no modules to activate", {
608
506
  key
609
507
  }, {
610
508
  F: __dxlog_file2,
611
- L: 357,
509
+ L: 361,
612
510
  S: this,
613
511
  C: (f, a) => f(...a)
614
512
  });
615
- if (!this._state.eventsFired.includes(key)) {
616
- this._state.eventsFired.push(key);
617
- }
618
513
  return false;
619
514
  }
620
- log2("activating modules", {
621
- key,
622
- modules: modules.map((module) => module.id)
623
- }, {
624
- F: __dxlog_file2,
625
- L: 364,
626
- S: this,
627
- C: (f, a) => f(...a)
628
- });
629
- this.activation.emit({
515
+ self.activation.emit({
630
516
  event: key,
631
517
  state: "activating"
632
518
  });
633
- const getCapabilities = yield* Effect.all(modules.map(({ activate }) => Effect.tryPromise({
634
- try: async () => activate(this.context),
635
- catch: (error) => error
636
- })), {
637
- concurrency: "unbounded"
638
- });
639
- const result = yield* pipe(
640
- modules,
641
- A.zip(getCapabilities),
642
- A.map(([module, getCapabilities2]) => this._activateModule(module, getCapabilities2)),
643
- // TODO(wittjosiah): This currently can't be run in parallel.
644
- // Running this with concurrency causes races with `allOf` activation events.
645
- Effect.all,
646
- Effect.either
647
- );
648
- if (Either.isLeft(result)) {
649
- this.activation.emit({
650
- event: key,
651
- state: "error",
652
- error: result.left
653
- });
654
- yield* Effect.fail(result.left);
519
+ for (const module of modules) {
520
+ if (isAllOf(module.activatesOn) && !module.activatesOn.events.filter((event2) => eventKey(event2) !== key).every((event2) => self._state.eventsFired.includes(eventKey(event2)))) {
521
+ continue;
522
+ }
523
+ yield* Effect.all(module.activatesBefore?.map((event2) => self._activate(event2)) ?? []);
524
+ const result = yield* self._activateModule(module).pipe(Effect.either);
525
+ if (Either.isLeft(result)) {
526
+ self.activation.emit({
527
+ event: key,
528
+ state: "error",
529
+ error: result.left
530
+ });
531
+ yield* Effect.fail(result.left);
532
+ }
533
+ yield* Effect.all(module.activatesAfter?.map((event2) => self._activate(event2)) ?? []);
655
534
  }
656
- if (!this._state.eventsFired.includes(key)) {
657
- this._state.eventsFired.push(key);
535
+ if (!self._state.eventsFired.includes(key)) {
536
+ self._state.eventsFired.push(key);
658
537
  }
659
- this.activation.emit({
538
+ self.activation.emit({
660
539
  event: key,
661
540
  state: "activated"
662
541
  });
@@ -664,105 +543,79 @@ var PluginManager = class {
664
543
  key
665
544
  }, {
666
545
  F: __dxlog_file2,
667
- L: 398,
546
+ L: 393,
668
547
  S: this,
669
548
  C: (f, a) => f(...a)
670
549
  });
671
550
  return true;
672
551
  });
673
552
  }
674
- _activateModule(module, getCapabilities) {
675
- return Effect.gen(this, function* () {
676
- yield* Effect.all(module.activatesBefore?.map((event) => this._activate(event)) ?? [], {
677
- concurrency: "unbounded"
678
- });
679
- log2("activating module...", {
680
- module: module.id
681
- }, {
682
- F: __dxlog_file2,
683
- L: 413,
684
- S: this,
685
- C: (f, a) => f(...a)
686
- });
687
- const maybeCapabilities = typeof getCapabilities === "function" ? getCapabilities() : getCapabilities;
688
- const resolvedCapabilities = yield* Match.value(maybeCapabilities).pipe(
689
- // TODO(wittjosiah): Activate with an effect?
690
- // Match.when(Effect.isEffect, (effect) => effect),
691
- Match.when(isPromise, (promise) => Effect.tryPromise({
692
- try: () => promise,
693
- catch: (error) => error
694
- })),
695
- Match.orElse((program) => Effect.succeed(program))
696
- );
697
- const capabilities = Match.value(resolvedCapabilities).pipe(Match.when(Array.isArray, (array) => array), Match.orElse((value) => [
553
+ _activateModule(module) {
554
+ const self = this;
555
+ return Effect.gen(function* () {
556
+ const program = module.activate(self.context);
557
+ const maybeCapabilities = yield* Match.value(program).pipe(Match.when(Effect.isEffect, (effect3) => effect3), Match.when(isPromise, (promise) => Effect.tryPromise({
558
+ try: () => promise,
559
+ catch: (error) => error
560
+ })), Match.orElse((program2) => Effect.succeed(program2)));
561
+ const capabilities = Match.value(maybeCapabilities).pipe(Match.when(Array.isArray, (array) => array), Match.orElse((value) => [
698
562
  value
699
563
  ]));
700
564
  capabilities.forEach((capability) => {
701
- this.context.contributeCapability({
565
+ self.context.contributeCapability({
702
566
  module: module.id,
703
567
  ...capability
704
568
  });
705
569
  });
706
- this._state.active.push(module.id);
707
- this._capabilities.set(module.id, capabilities);
708
- log2("activated module", {
709
- module: module.id
710
- }, {
711
- F: __dxlog_file2,
712
- L: 436,
713
- S: this,
714
- C: (f, a) => f(...a)
715
- });
716
- yield* Effect.all(module.activatesAfter?.map((event) => this._activate(event)) ?? [], {
717
- concurrency: "unbounded"
718
- });
570
+ self._state.active.push(module.id);
571
+ self._capabilities.set(module.id, capabilities);
719
572
  });
720
573
  }
721
574
  _deactivate(id) {
722
- return Effect.gen(this, function* () {
723
- const plugin = this._getPlugin(id);
575
+ const self = this;
576
+ return Effect.gen(function* () {
577
+ const plugin = self._getPlugin(id);
724
578
  if (!plugin) {
725
579
  return false;
726
580
  }
727
581
  const modules = plugin.modules;
728
- const results = yield* Effect.all(modules.map((module) => this._deactivateModule(module)), {
729
- concurrency: "unbounded"
730
- });
582
+ const results = yield* Effect.all(modules.map((module) => self._deactivateModule(module)));
731
583
  return results.every((result) => result);
732
584
  });
733
585
  }
734
586
  _deactivateModule(module) {
735
- return Effect.gen(this, function* () {
587
+ const self = this;
588
+ return Effect.gen(function* () {
736
589
  const id = module.id;
737
590
  log2("deactivating", {
738
591
  id
739
592
  }, {
740
593
  F: __dxlog_file2,
741
- L: 463,
594
+ L: 444,
742
595
  S: this,
743
596
  C: (f, a) => f(...a)
744
597
  });
745
- const capabilities = this._capabilities.get(id);
598
+ const capabilities = self._capabilities.get(id);
746
599
  if (capabilities) {
747
600
  for (const capability of capabilities) {
748
- this.context.removeCapability(capability.interface, capability.implementation);
601
+ self.context.removeCapability(capability.interface, capability.implementation);
749
602
  const program = capability.deactivate?.();
750
- yield* Match.value(program).pipe(Match.when(Effect.isEffect, (effect2) => effect2), Match.when(isPromise, (promise) => Effect.tryPromise({
603
+ yield* Match.value(program).pipe(Match.when(Effect.isEffect, (effect3) => effect3), Match.when(isPromise, (promise) => Effect.tryPromise({
751
604
  try: () => promise,
752
605
  catch: (error) => error
753
606
  })), Match.orElse((program2) => Effect.succeed(program2)));
754
607
  }
755
- this._capabilities.delete(id);
608
+ self._capabilities.delete(id);
756
609
  }
757
- const activeIndex = this._state.active.findIndex((event) => event === id);
610
+ const activeIndex = self._state.active.findIndex((event) => event === id);
758
611
  if (activeIndex !== -1) {
759
- this._state.active.splice(activeIndex, 1);
612
+ self._state.active.splice(activeIndex, 1);
760
613
  }
761
614
  log2("deactivated", {
762
615
  id
763
616
  }, {
764
617
  F: __dxlog_file2,
765
- L: 489,
618
+ L: 470,
766
619
  S: this,
767
620
  C: (f, a) => f(...a)
768
621
  });
@@ -770,22 +623,27 @@ var PluginManager = class {
770
623
  });
771
624
  }
772
625
  _reset(event) {
773
- return Effect.gen(this, function* () {
626
+ const self = this;
627
+ return Effect.gen(function* () {
774
628
  const key = typeof event === "string" ? event : eventKey(event);
775
629
  log2("reset", {
776
630
  key
777
631
  }, {
778
632
  F: __dxlog_file2,
779
- L: 497,
633
+ L: 479,
780
634
  S: this,
781
635
  C: (f, a) => f(...a)
782
636
  });
783
- const modules = this._getActiveModulesByEvent(key);
784
- const results = yield* Effect.all(modules.map((module) => this._deactivateModule(module)), {
785
- concurrency: "unbounded"
786
- });
637
+ const modules = self._getActiveModulesByEvent(key);
638
+ const results = yield* Effect.all(modules.map((module) => self._deactivateModule(module)));
639
+ if (self._state.pendingRemoval.length > 0) {
640
+ self._state.pendingRemoval.forEach((id) => {
641
+ self._removeModule(id);
642
+ });
643
+ self._state.pendingRemoval.splice(0, self._state.pendingRemoval.length);
644
+ }
787
645
  if (results.every((result) => result)) {
788
- return yield* this._activate(key);
646
+ return yield* self._activate(key);
789
647
  } else {
790
648
  return false;
791
649
  }
@@ -825,6 +683,9 @@ var Capabilities;
825
683
  Capabilities2.IntentResolver = defineCapability("dxos.org/app-framework/capability/intent-resolver");
826
684
  Capabilities2.IntentDispatcher = defineCapability("dxos.org/app-framework/capability/intent-dispatcher");
827
685
  Capabilities2.Layout = defineCapability("dxos.org/app-framework/capability/layout");
686
+ Capabilities2.MutableLayout = defineCapability("dxos.org/app-framework/capability/layout");
687
+ Capabilities2.Location = defineCapability("dxos.org/app-framework/capability/location");
688
+ Capabilities2.MutableLocation = defineCapability("dxos.org/app-framework/capability/location");
828
689
  Capabilities2.Translations = defineCapability("dxos.org/app-framework/capability/translations");
829
690
  Capabilities2.AppGraph = defineCapability("dxos.org/app-framework/capability/app-graph");
830
691
  Capabilities2.AppGraphBuilder = defineCapability("dxos.org/app-framework/capability/app-graph-builder");
@@ -832,8 +693,6 @@ var Capabilities;
832
693
  Capabilities2.SettingsStore = defineCapability("dxos.org/app-framework/capability/settings-store");
833
694
  Capabilities2.Settings = defineCapability("dxos.org/app-framework/capability/settings");
834
695
  Capabilities2.Metadata = defineCapability("dxos.org/app-framework/capability/metadata");
835
- Capabilities2.Tools = defineCapability("dxos.org/app-framework/capability/tools");
836
- Capabilities2.ArtifactDefinition = defineCapability("dxos.org/app-framework/capability/artifact-definition");
837
696
  Capabilities2.FileUploader = defineCapability("dxos.org/app-framework/capability/file-uploader");
838
697
  })(Capabilities || (Capabilities = {}));
839
698
 
@@ -841,8 +700,6 @@ var Capabilities;
841
700
  var Events;
842
701
  (function(Events2) {
843
702
  Events2.Startup = defineEvent("dxos.org/app-framework/event/startup");
844
- Events2.SetupSurfaces = defineEvent("dxos.org/app-framework/event/setup-surfaces");
845
- Events2.SetupMetadata = defineEvent("dxos.org/app-framework/event/setup-metadata");
846
703
  Events2.SetupIntents = defineEvent("dxos.org/app-framework/event/setup-intents");
847
704
  Events2.SetupSettings = defineEvent("dxos.org/app-framework/event/setup-settings");
848
705
  Events2.SetupAppGraph = defineEvent("dxos.org/app-framework/event/setup-graph");
@@ -852,10 +709,11 @@ var Events;
852
709
  Events2.AppGraphReady = defineEvent("dxos.org/app-framework/event/graph-ready");
853
710
  Events2.createStateEvent = (specifier) => defineEvent("dxos.org/app-framework/event/state", specifier);
854
711
  Events2.LayoutReady = Events2.createStateEvent(Capabilities.Layout.identifier);
712
+ Events2.LocationReady = Events2.createStateEvent(Capabilities.Location.identifier);
855
713
  })(Events || (Events = {}));
856
714
 
857
715
  // packages/sdk/app-framework/src/common/file.ts
858
- import { Schema as S3 } from "@effect/schema";
716
+ import { S } from "@dxos/echo-schema";
859
717
  var defaultFileTypes = {
860
718
  images: [
861
719
  "png",
@@ -875,367 +733,127 @@ var defaultFileTypes = {
875
733
  "md"
876
734
  ]
877
735
  };
878
- var FileInfoSchema = S3.Struct({
879
- name: S3.String,
880
- type: S3.String,
881
- url: S3.optional(S3.String),
882
- cid: S3.optional(S3.String)
736
+ var FileInfoSchema = S.Struct({
737
+ name: S.String,
738
+ type: S.String,
739
+ url: S.optional(S.String),
740
+ cid: S.optional(S.String)
883
741
  });
884
742
 
885
- // packages/sdk/app-framework/src/common/layout.ts
886
- import { Schema as S4 } from "@effect/schema";
887
-
888
- // packages/sdk/app-framework/src/plugin-intent/IntentPlugin.tsx
889
- var IntentPlugin = () => definePlugin({
890
- id: INTENT_PLUGIN
891
- }, [
892
- defineModule({
893
- id: `${INTENT_PLUGIN}/module/dispatcher`,
894
- // TODO(wittjosiah): This will mean that startup needs to be reset when intents are added or removed.
895
- // This is fine for now because it's how it worked prior to capabilities api anyways.
896
- // In the future, the intent dispatcher should be able to be reset without resetting the entire app.
897
- activatesOn: Events.Startup,
898
- activatesAfter: [
899
- Events.DispatcherReady
900
- ],
901
- activate: lazy(() => import("./intent-dispatcher-LJKNIGAM.mjs"))
902
- })
903
- ]);
743
+ // packages/sdk/app-framework/src/plugin-intent/intent.ts
744
+ import { S as S2 } from "@dxos/echo-schema";
745
+ var createIntent = (schema, data = {}, params = {}) => {
746
+ const _ = S2.validateSync(schema.fields.input)(data);
747
+ const intent = {
748
+ ...params,
749
+ _schema: schema,
750
+ action: schema._tag,
751
+ data
752
+ };
753
+ return {
754
+ first: intent,
755
+ last: intent,
756
+ all: [
757
+ intent
758
+ ]
759
+ };
760
+ };
761
+ var chain = (schema, data = {}, params = {}) => (intent) => {
762
+ const intents = "all" in intent ? intent.all : [
763
+ intent
764
+ ];
765
+ const first = intents[0];
766
+ const last = {
767
+ ...params,
768
+ _schema: schema,
769
+ action: schema._tag,
770
+ data
771
+ };
772
+ return {
773
+ first,
774
+ last,
775
+ all: [
776
+ ...intents,
777
+ last
778
+ ]
779
+ };
780
+ };
781
+ var Label = S2.Union(S2.String, S2.mutable(S2.Tuple(S2.String, S2.mutable(S2.Struct({
782
+ ns: S2.String,
783
+ count: S2.optional(S2.Number)
784
+ })))));
904
785
 
905
- // packages/sdk/app-framework/src/common/layout.ts
906
- var LAYOUT_PLUGIN = "dxos.org/plugin/layout";
907
- var LAYOUT_ACTION = `${LAYOUT_PLUGIN}/action`;
908
- var LayoutAction;
909
- (function(LayoutAction2) {
910
- LayoutAction2.UPDATE_LAYOUT = `${LAYOUT_ACTION}/update-layout`;
911
- class UpdateLayout extends S4.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
912
- input: S4.Struct({
913
- part: S4.String.annotations({
914
- description: "The part of the layout to mutate."
915
- }),
916
- subject: S4.optional(S4.Any.annotations({
917
- description: "The subject of the layout update."
918
- })),
919
- options: S4.optional(S4.Record({
920
- key: S4.String,
921
- value: S4.Any
922
- }).annotations({
923
- description: "Additional options for the layout action."
924
- }))
925
- }),
926
- output: S4.Void
927
- }) {
928
- }
929
- LayoutAction2.UpdateLayout = UpdateLayout;
930
- class SetLayoutMode extends S4.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
931
- input: S4.Struct({
932
- part: S4.Literal("mode").annotations({
933
- description: "Setting the layout mode."
934
- }),
935
- subject: S4.optional(S4.String.annotations({
936
- description: "Item which is the subject of the new layout mode."
937
- })),
938
- options: S4.Union(S4.Struct({
939
- mode: S4.String.annotations({
940
- description: "The new layout mode."
941
- })
942
- }), S4.Struct({
943
- revert: S4.Boolean.annotations({
944
- description: "Revert to the previous layout mode."
945
- })
946
- }))
947
- }),
948
- output: S4.Void
949
- }) {
950
- }
951
- LayoutAction2.SetLayoutMode = SetLayoutMode;
952
- class UpdateSidebar extends S4.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
953
- input: S4.Struct({
954
- part: S4.Literal("sidebar").annotations({
955
- description: "Updating the sidebar."
956
- }),
957
- subject: S4.optional(S4.String.annotations({
958
- description: "URI of the component to display in the sidebar."
959
- })),
960
- options: S4.optional(S4.Struct({
961
- state: S4.Literal("closed", "collapsed", "expanded").annotations({
962
- description: "Whether the sidebar is closed, collapsed, or expanded."
963
- })
964
- }))
965
- }),
966
- output: S4.Void
967
- }) {
968
- }
969
- LayoutAction2.UpdateSidebar = UpdateSidebar;
970
- class UpdateComplementary extends S4.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
971
- input: S4.Struct({
972
- part: S4.Literal("complementary").annotations({
973
- description: "Updating the complementary sidebar."
974
- }),
975
- subject: S4.optional(S4.String.annotations({
976
- description: "URI of the component to display in the complementary area."
977
- })),
978
- options: S4.optional(S4.Struct({
979
- state: S4.Literal("closed", "collapsed", "expanded").annotations({
980
- description: "Whether the complementary sidebar is closed, collapsed, or expanded."
981
- })
982
- }))
983
- }),
984
- output: S4.Void
985
- }) {
986
- }
987
- LayoutAction2.UpdateComplementary = UpdateComplementary;
988
- class UpdateDialog extends S4.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
989
- input: S4.Struct({
990
- part: S4.Literal("dialog").annotations({
991
- description: "Updating the dialog."
992
- }),
993
- subject: S4.optional(S4.String.annotations({
994
- description: "URI of the component to display in the dialog."
995
- })),
996
- options: S4.Struct({
997
- state: S4.optional(S4.Boolean.annotations({
998
- description: "Whether the dialog is open or closed."
999
- })),
1000
- blockAlign: S4.optional(S4.Literal("start", "center").annotations({
1001
- description: "The alignment of the dialog."
1002
- })),
1003
- type: S4.optional(S4.Literal("default", "alert").annotations({
1004
- description: "The type of dialog."
1005
- })),
1006
- props: S4.optional(S4.Record({
1007
- key: S4.String,
1008
- value: S4.Any
1009
- }).annotations({
1010
- description: "Additional props for the dialog."
1011
- }))
1012
- })
1013
- }),
1014
- output: S4.Void
1015
- }) {
1016
- }
1017
- LayoutAction2.UpdateDialog = UpdateDialog;
1018
- class UpdatePopover extends S4.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
1019
- input: S4.Struct({
1020
- part: S4.Literal("popover").annotations({
1021
- description: "Updating the popover."
1022
- }),
1023
- subject: S4.optional(S4.String.annotations({
1024
- description: "URI of the component to display in the popover."
1025
- })),
1026
- options: S4.Struct({
1027
- anchorId: S4.String.annotations({
1028
- description: "The id of the element to anchor the popover to."
1029
- }),
1030
- state: S4.optional(S4.Boolean.annotations({
1031
- description: "Whether the popover is open or closed."
1032
- })),
1033
- props: S4.optional(S4.Record({
1034
- key: S4.String,
1035
- value: S4.Any
1036
- }).annotations({
1037
- description: "Additional props for the popover."
1038
- }))
1039
- })
1040
- }),
1041
- output: S4.Void
1042
- }) {
1043
- }
1044
- LayoutAction2.UpdatePopover = UpdatePopover;
1045
- LayoutAction2.Toast = S4.Struct({
1046
- id: S4.String.annotations({
1047
- description: "The id of the toast."
1048
- }),
1049
- title: S4.optional(Label.annotations({
1050
- description: "The title of the toast."
1051
- })),
1052
- description: S4.optional(Label.annotations({
1053
- description: "The description of the toast."
1054
- })),
1055
- icon: S4.optional(S4.String.annotations({
1056
- description: "The icon of the toast."
1057
- })),
1058
- duration: S4.optional(S4.Number.annotations({
1059
- description: "The duration of the toast."
1060
- })),
1061
- closeLabel: S4.optional(Label.annotations({
1062
- description: "The label of the close button."
1063
- })),
1064
- actionLabel: S4.optional(Label.annotations({
1065
- description: "The label of the action button."
1066
- })),
1067
- actionAlt: S4.optional(Label.annotations({
1068
- description: "The alt text of the action button."
1069
- })),
1070
- onAction: S4.optional(S4.Any.annotations({
1071
- description: "The action to perform when the action button is clicked."
1072
- }))
1073
- });
1074
- class AddToast extends S4.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
1075
- input: S4.Struct({
1076
- part: S4.Literal("toast").annotations({
1077
- description: "Adding a toast."
1078
- }),
1079
- subject: LayoutAction2.Toast.annotations({
1080
- description: "The toast to add."
1081
- })
1082
- }),
1083
- output: S4.Void
1084
- }) {
1085
- }
1086
- LayoutAction2.AddToast = AddToast;
1087
- class SwitchWorkspace extends S4.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
1088
- input: S4.Struct({
1089
- part: S4.Literal("workspace").annotations({
1090
- description: "Switching the workspace."
1091
- }),
1092
- subject: S4.String.annotations({
1093
- description: "The id of the workspace to switch to."
1094
- })
1095
- }),
1096
- output: S4.Void
1097
- }) {
1098
- }
1099
- LayoutAction2.SwitchWorkspace = SwitchWorkspace;
1100
- class Open extends S4.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
1101
- input: S4.Struct({
1102
- part: S4.Literal("main").annotations({
1103
- description: "Opening an item in the main content area."
1104
- }),
1105
- subject: S4.Array(S4.String.annotations({
1106
- description: "Ids of the items to open."
1107
- })),
1108
- options: S4.optional(S4.Struct({
1109
- state: S4.optional(S4.Literal(true).annotations({
1110
- description: "The items are being added."
1111
- })),
1112
- key: S4.optional(S4.String.annotations({
1113
- description: "If provided, will replace item with a matching key (id prefix)."
1114
- })),
1115
- scrollIntoView: S4.optional(S4.Boolean.annotations({
1116
- description: "Scroll the items into view."
1117
- })),
1118
- pivotId: S4.optional(S4.String.annotations({
1119
- description: "The id of the item to place new items next to."
1120
- })),
1121
- positioning: S4.optional(S4.Union(S4.Literal("start").annotations({
1122
- description: "The items are being added before the pivot item."
1123
- }), S4.Literal("end").annotations({
1124
- description: "The items are being added after the pivot item."
1125
- })))
1126
- }))
1127
- }),
1128
- output: S4.Void
1129
- }) {
1130
- }
1131
- LayoutAction2.Open = Open;
1132
- class Set2 extends S4.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
1133
- input: S4.Struct({
1134
- part: S4.Literal("main").annotations({
1135
- description: "Setting items in the main content area."
1136
- }),
1137
- subject: S4.Array(S4.String.annotations({
1138
- description: "Ids of the items to set."
1139
- })),
1140
- options: S4.Struct({
1141
- override: S4.Literal(true).annotations({
1142
- description: "Override the current items in the main content area."
1143
- })
1144
- })
786
+ // packages/sdk/app-framework/src/plugin-intent/actions.ts
787
+ import { S as S3 } from "@dxos/echo-schema";
788
+ var INTENT_PLUGIN = "dxos.org/plugin/intent";
789
+ var INTENT_ACTION = `${INTENT_PLUGIN}/action`;
790
+ var IntentAction;
791
+ (function(IntentAction2) {
792
+ class ShowUndo extends S3.TaggedClass()(`${INTENT_ACTION}/show-undo`, {
793
+ input: S3.Struct({
794
+ message: Label
1145
795
  }),
1146
- output: S4.Void
796
+ output: S3.Void
1147
797
  }) {
1148
798
  }
1149
- LayoutAction2.Set = Set2;
1150
- class Close extends S4.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
1151
- input: S4.Struct({
1152
- part: S4.Literal("main").annotations({
1153
- description: "Closing items in the main content area."
1154
- }),
1155
- subject: S4.Array(S4.String.annotations({
1156
- description: "Ids of the items to close."
1157
- })),
1158
- options: S4.Struct({
1159
- state: S4.Literal(false).annotations({
1160
- description: "The items are being removed."
1161
- })
1162
- })
1163
- }),
1164
- output: S4.Void
1165
- }) {
799
+ IntentAction2.ShowUndo = ShowUndo;
800
+ })(IntentAction || (IntentAction = {}));
801
+
802
+ // packages/sdk/app-framework/src/plugin-intent/intent-dispatcher.ts
803
+ import { Effect as Effect2, Option, pipe, Ref } from "effect";
804
+ import { byDisposition } from "@dxos/util";
805
+
806
+ // packages/sdk/app-framework/src/plugin-intent/errors.ts
807
+ var BaseError = class extends Error {
808
+ constructor(code, message, context) {
809
+ super(message ?? code);
810
+ this.code = code;
811
+ this.context = context;
812
+ this.name = code;
813
+ Object.setPrototypeOf(this, new.target.prototype);
1166
814
  }
1167
- LayoutAction2.Close = Close;
1168
- class ScrollIntoView extends S4.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
1169
- input: S4.Struct({
1170
- part: S4.Literal("current").annotations({
1171
- description: "Setting the current item"
1172
- }),
1173
- subject: S4.optional(S4.String.annotations({
1174
- description: "The id of the item to set as current."
1175
- })),
1176
- options: S4.optional(S4.Record({
1177
- key: S4.String,
1178
- value: S4.Any
1179
- }).annotations({
1180
- description: "Additional options for the scroll into view."
1181
- }))
1182
- }),
1183
- output: S4.Void
1184
- }) {
815
+ };
816
+ var NoResolversError = class extends BaseError {
817
+ constructor(action) {
818
+ super("NO_RESOLVERS", "No resolvers were found for the action", {
819
+ action
820
+ });
1185
821
  }
1186
- LayoutAction2.ScrollIntoView = ScrollIntoView;
1187
- class Expose extends S4.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
1188
- input: S4.Struct({
1189
- part: S4.Literal("navigation").annotations({
1190
- description: "Exposing an item in the navigation area."
1191
- }),
1192
- subject: S4.String.annotations({
1193
- description: "The id of the item to expose."
1194
- })
1195
- }),
1196
- output: S4.Void
1197
- }) {
822
+ };
823
+ var CycleDetectedError = class extends BaseError {
824
+ constructor(context) {
825
+ super("CYCLE_DETECTED", "Intent execution limit exceeded. This is likely due to an infinite loop within intent resolvers.", context);
1198
826
  }
1199
- LayoutAction2.Expose = Expose;
1200
- })(LayoutAction || (LayoutAction = {}));
1201
-
1202
- // packages/sdk/app-framework/src/common/surface.ts
1203
- var createSurface = (definition) => definition;
1204
-
1205
- // packages/sdk/app-framework/src/common/translations.ts
1206
- import { Schema as S5 } from "@effect/schema";
1207
- var ResourceKey = S5.Union(S5.String, S5.Record({
1208
- key: S5.String,
1209
- value: S5.Any
1210
- }));
1211
- var ResourceLanguage = S5.Record({
1212
- key: S5.String,
1213
- value: ResourceKey
1214
- });
1215
- var Resource = S5.Record({
1216
- key: S5.String,
1217
- value: ResourceLanguage
1218
- });
827
+ };
1219
828
 
1220
829
  // packages/sdk/app-framework/src/plugin-intent/intent-dispatcher.ts
1221
830
  var EXECUTION_LIMIT = 100;
1222
831
  var HISTORY_LIMIT = 100;
1223
- var createResolver = (resolver) => resolver;
832
+ var createResolver = (schema, effect3, params = {}) => ({
833
+ action: schema._tag,
834
+ effect: effect3,
835
+ ...params
836
+ });
1224
837
  var isUndoable = (historyEntry) => historyEntry.length > 0 && historyEntry.every(({ undoable }) => !!undoable);
1225
838
  var createDispatcher = (getResolvers, { executionLimit = EXECUTION_LIMIT, historyLimit = HISTORY_LIMIT } = {}) => {
1226
839
  const historyRef = Effect2.runSync(Ref.make([]));
1227
- const handleIntent = (intent) => Effect2.gen(function* () {
1228
- const candidates = getResolvers(intent.module).filter((r) => r.intent._tag === intent.id).filter((r) => !r.filter || r.filter(intent.data)).toSorted(byPosition);
1229
- if (candidates.length === 0) {
1230
- yield* Effect2.fail(new NoResolversError(intent.id));
1231
- }
1232
- const effect2 = candidates[0].resolve(intent.data, intent.undo ?? false);
1233
- const result = Effect2.isEffect(effect2) ? yield* effect2 : yield* Effect2.promise(async () => effect2);
1234
- return {
1235
- _intent: intent,
1236
- ...result
1237
- };
1238
- });
840
+ const handleIntent = (intent) => {
841
+ return Effect2.gen(function* () {
842
+ const candidates = getResolvers(intent.module).filter((r) => r.action === intent.action).filter((r) => !r.filter || r.filter(intent.data)).toSorted(byDisposition);
843
+ if (candidates.length === 0) {
844
+ return {
845
+ _intent: intent,
846
+ error: new NoResolversError(intent.action)
847
+ };
848
+ }
849
+ const effect3 = candidates[0].effect(intent.data, intent.undo ?? false);
850
+ const result = Effect2.isEffect(effect3) ? yield* effect3 : yield* Effect2.promise(async () => effect3);
851
+ return {
852
+ _intent: intent,
853
+ ...result
854
+ };
855
+ });
856
+ };
1239
857
  const dispatch = (intentChain, depth = 0) => {
1240
858
  return Effect2.gen(function* () {
1241
859
  if (depth > executionLimit) {
@@ -1277,7 +895,7 @@ var createDispatcher = (getResolvers, { executionLimit = EXECUTION_LIMIT, histor
1277
895
  return next;
1278
896
  });
1279
897
  if (result.undoable && isUndoable(results)) {
1280
- yield* pipe2(dispatch(createIntent(IntentAction.ShowUndo, {
898
+ yield* pipe(dispatch(createIntent(IntentAction.ShowUndo, {
1281
899
  message: result.undoable.message
1282
900
  })), Effect2.catchSome((err) => err instanceof NoResolversError ? Option.some(Effect2.succeed(void 0)) : Option.none()));
1283
901
  }
@@ -1333,32 +951,578 @@ var createDispatcher = (getResolvers, { executionLimit = EXECUTION_LIMIT, histor
1333
951
  undoPromise
1334
952
  };
1335
953
  };
1336
- var defaultEffect = () => Effect2.fail(new Error("Intent runtime not ready"));
1337
- var defaultPromise = () => Effect2.runPromise(defaultEffect());
1338
- var intent_dispatcher_default = (context) => {
1339
- const state = create3({
1340
- dispatch: defaultEffect,
1341
- dispatchPromise: defaultPromise,
1342
- undo: defaultEffect,
1343
- undoPromise: defaultPromise
954
+
955
+ // packages/sdk/app-framework/src/react/ErrorBoundary.tsx
956
+ import React, { Component } from "react";
957
+ var ErrorBoundary = class extends Component {
958
+ constructor(props) {
959
+ super(props);
960
+ this.state = {
961
+ error: void 0
962
+ };
963
+ }
964
+ static getDerivedStateFromError(error) {
965
+ return {
966
+ error
967
+ };
968
+ }
969
+ componentDidUpdate(prevProps) {
970
+ if (prevProps.data !== this.props.data) {
971
+ this.resetError();
972
+ }
973
+ }
974
+ render() {
975
+ if (this.state.error) {
976
+ return /* @__PURE__ */ React.createElement(this.props.fallback, {
977
+ data: this.props.data,
978
+ error: this.state.error,
979
+ reset: this.resetError
980
+ });
981
+ }
982
+ return this.props.children;
983
+ }
984
+ resetError() {
985
+ this.setState({
986
+ error: void 0
987
+ });
988
+ }
989
+ };
990
+
991
+ // packages/sdk/app-framework/src/react/PluginManagerProvider.ts
992
+ import { createContext, useContext } from "react";
993
+ import { raise } from "@dxos/debug";
994
+ var PluginManagerContext = createContext(void 0);
995
+ var usePluginManager = () => useContext(PluginManagerContext) ?? raise(new Error("Missing PluginManagerContext"));
996
+ var PluginManagerProvider = PluginManagerContext.Provider;
997
+
998
+ // packages/sdk/app-framework/src/react/useCapabilities.ts
999
+ import { computed } from "@preact/signals-core";
1000
+ import { useMemo } from "react";
1001
+ var useCapabilities = (interfaceDef, filter) => {
1002
+ const manager = usePluginManager();
1003
+ const signal = useMemo(() => computed(() => manager.context.requestCapabilities(interfaceDef, filter)), [
1004
+ interfaceDef
1005
+ ]);
1006
+ return signal.value;
1007
+ };
1008
+ var useCapability = (interfaceDef, filter) => {
1009
+ const manager = usePluginManager();
1010
+ const signal = useMemo(() => computed(() => manager.context.requestCapability(interfaceDef, filter)), [
1011
+ interfaceDef
1012
+ ]);
1013
+ return signal.value;
1014
+ };
1015
+
1016
+ // packages/sdk/app-framework/src/react/Surface.tsx
1017
+ import React3, { memo, forwardRef, Suspense, useMemo as useMemo2 } from "react";
1018
+ import { useDefaultValue } from "@dxos/react-hooks";
1019
+ import { byDisposition as byDisposition2 } from "@dxos/util";
1020
+
1021
+ // packages/sdk/app-framework/src/common/layout.ts
1022
+ import { S as S4 } from "@dxos/echo-schema";
1023
+
1024
+ // packages/sdk/app-framework/src/plugin-intent/IntentContext.tsx
1025
+ import { createContext as createContext2, useContext as useContext2, useEffect } from "react";
1026
+ import { raise as raise2 } from "@dxos/debug";
1027
+ import { pick } from "@dxos/util";
1028
+ var IntentContext = /* @__PURE__ */ createContext2(void 0);
1029
+ var useIntentDispatcher = () => {
1030
+ const context = useContext2(IntentContext) ?? raise2(new Error("IntentContext not found"));
1031
+ return pick(context, [
1032
+ "dispatch",
1033
+ "dispatchPromise"
1034
+ ]);
1035
+ };
1036
+ var useIntentResolver = (module, resolver) => {
1037
+ const manager = usePluginManager();
1038
+ useEffect(() => {
1039
+ manager.context.contributeCapability({
1040
+ module,
1041
+ interface: Capabilities.IntentResolver,
1042
+ implementation: resolver
1043
+ });
1044
+ return () => manager.context.removeCapability(Capabilities.IntentResolver, resolver);
1045
+ }, [
1046
+ module,
1047
+ resolver
1048
+ ]);
1049
+ };
1050
+ var IntentProvider = IntentContext.Provider;
1051
+
1052
+ // packages/sdk/app-framework/src/plugin-intent/IntentPlugin.tsx
1053
+ import { Effect as Effect3 } from "effect";
1054
+ import React2 from "react";
1055
+ import { create as create3 } from "@dxos/live-object";
1056
+ var defaultEffect = () => Effect3.fail(new Error("Intent runtime not ready"));
1057
+ var defaultPromise = () => Effect3.runPromise(defaultEffect());
1058
+ var IntentPlugin = () => definePlugin({
1059
+ id: INTENT_PLUGIN
1060
+ }, [
1061
+ defineModule({
1062
+ id: `${INTENT_PLUGIN}/module/dispatcher`,
1063
+ // TODO(wittjosiah): This will mean that startup needs to be reset when intents are added or removed.
1064
+ // This is fine for now because it's how it worked prior to capabilities api anyways.
1065
+ // In the future, the intent dispatcher should be able to be reset without resetting the entire app.
1066
+ activatesOn: Events.Startup,
1067
+ activatesBefore: [
1068
+ Events.SetupIntents
1069
+ ],
1070
+ activatesAfter: [
1071
+ Events.DispatcherReady
1072
+ ],
1073
+ activate: (context) => {
1074
+ const state = create3({
1075
+ dispatch: defaultEffect,
1076
+ dispatchPromise: defaultPromise,
1077
+ undo: defaultEffect,
1078
+ undoPromise: defaultPromise
1079
+ });
1080
+ const { dispatch, dispatchPromise, undo, undoPromise } = createDispatcher((module) => context.requestCapabilities(Capabilities.IntentResolver, (c, moduleId) => {
1081
+ return module ? moduleId === module : true;
1082
+ }).flat());
1083
+ state.dispatch = dispatch;
1084
+ state.dispatchPromise = dispatchPromise;
1085
+ state.undo = undo;
1086
+ state.undoPromise = undoPromise;
1087
+ return [
1088
+ contributes(Capabilities.IntentDispatcher, state),
1089
+ contributes(Capabilities.ReactContext, {
1090
+ id: INTENT_PLUGIN,
1091
+ context: ({ children }) => /* @__PURE__ */ React2.createElement(IntentProvider, {
1092
+ value: state
1093
+ }, children)
1094
+ })
1095
+ ];
1096
+ }
1097
+ })
1098
+ ]);
1099
+
1100
+ // packages/sdk/app-framework/src/common/layout.ts
1101
+ var Toast = S4.Struct({
1102
+ id: S4.String,
1103
+ title: S4.optional(Label),
1104
+ description: S4.optional(Label),
1105
+ icon: S4.optional(S4.String),
1106
+ duration: S4.optional(S4.Number),
1107
+ closeLabel: S4.optional(Label),
1108
+ actionLabel: S4.optional(Label),
1109
+ actionAlt: S4.optional(Label),
1110
+ // TODO(wittjosiah): Make class with customizable method?
1111
+ onAction: S4.optional(S4.Any)
1112
+ });
1113
+ var LayoutMode = S4.Union(S4.Literal("deck"), S4.Literal("solo"), S4.Literal("fullscreen"));
1114
+ var isLayoutMode = (value) => S4.is(LayoutMode)(value);
1115
+ var Layout = S4.mutable(S4.Struct({
1116
+ layoutMode: LayoutMode,
1117
+ sidebarOpen: S4.Boolean,
1118
+ complementarySidebarOpen: S4.Boolean,
1119
+ /**
1120
+ * @deprecated Data to be passed to the complementary sidebar Surface.
1121
+ */
1122
+ complementarySidebarContent: S4.optional(S4.Any),
1123
+ dialogOpen: S4.Boolean,
1124
+ /**
1125
+ * Data to be passed to the dialog Surface.
1126
+ */
1127
+ dialogContent: S4.optional(S4.Any),
1128
+ // TODO(wittjosiah): Custom properties?
1129
+ dialogBlockAlign: S4.optional(S4.Literal("start", "center")),
1130
+ dialogType: S4.optional(S4.Literal("default", "alert")),
1131
+ popoverOpen: S4.Boolean,
1132
+ /**
1133
+ * Data to be passed to the popover Surface.
1134
+ */
1135
+ popoverContent: S4.optional(S4.Any),
1136
+ popoverAnchorId: S4.optional(S4.String),
1137
+ toasts: S4.mutable(S4.Array(Toast)),
1138
+ /**
1139
+ * The identifier of a component to scroll into view when it is mounted.
1140
+ */
1141
+ scrollIntoView: S4.optional(S4.String)
1142
+ }));
1143
+ var LAYOUT_PLUGIN = "dxos.org/plugin/layout";
1144
+ var LAYOUT_ACTION = `${LAYOUT_PLUGIN}/action`;
1145
+ var LayoutAction;
1146
+ (function(LayoutAction2) {
1147
+ class SetLayout extends S4.TaggedClass()(`${LAYOUT_ACTION}/set-layout`, {
1148
+ input: S4.Struct({
1149
+ /**
1150
+ * Element to set the state of.
1151
+ */
1152
+ element: S4.Literal("fullscreen", "sidebar", "complementary", "dialog", "popover", "toast"),
1153
+ /**
1154
+ * Whether the element is on or off.
1155
+ *
1156
+ * If omitted, the element's state will be toggled or set based on other provided data.
1157
+ * For example, if `component` is provided, the state will be set to `true`.
1158
+ */
1159
+ state: S4.optional(S4.Boolean),
1160
+ /**
1161
+ * Component to render in the dialog or popover.
1162
+ */
1163
+ component: S4.optional(S4.String),
1164
+ /**
1165
+ * Data to be passed to the dialog or popover Surface.
1166
+ */
1167
+ subject: S4.optional(S4.Any),
1168
+ /**
1169
+ * Anchor ID for the popover.
1170
+ */
1171
+ anchorId: S4.optional(S4.String),
1172
+ // TODO(wittjosiah): Custom properties?
1173
+ /**
1174
+ * Block alignment for the dialog.
1175
+ */
1176
+ dialogBlockAlign: S4.optional(S4.Literal("start", "center")),
1177
+ /**
1178
+ * Type of dialog.
1179
+ */
1180
+ dialogType: S4.optional(S4.Literal("default", "alert"))
1181
+ }),
1182
+ output: S4.Void
1183
+ }) {
1184
+ }
1185
+ LayoutAction2.SetLayout = SetLayout;
1186
+ class SetLayoutMode extends S4.TaggedClass()(`${LAYOUT_ACTION}/set-layout-mode`, {
1187
+ input: S4.Union(S4.Struct({
1188
+ layoutMode: LayoutMode
1189
+ }), S4.Struct({
1190
+ revert: S4.Literal(true)
1191
+ })),
1192
+ output: S4.Void
1193
+ }) {
1194
+ }
1195
+ LayoutAction2.SetLayoutMode = SetLayoutMode;
1196
+ class ScrollIntoView extends S4.TaggedClass()(`${LAYOUT_ACTION}/scroll-into-view`, {
1197
+ input: S4.Struct({
1198
+ id: S4.optional(S4.String),
1199
+ // TODO(wittjosiah): Factor out to thread scroll into view action?
1200
+ cursor: S4.optional(S4.String),
1201
+ ref: S4.optional(S4.String)
1202
+ }),
1203
+ output: S4.Void
1204
+ }) {
1205
+ }
1206
+ LayoutAction2.ScrollIntoView = ScrollIntoView;
1207
+ })(LayoutAction || (LayoutAction = {}));
1208
+
1209
+ // packages/sdk/app-framework/src/common/navigation.ts
1210
+ import { Schema as S5 } from "@effect/schema";
1211
+ import { pick as pick2 } from "@dxos/util";
1212
+ var SLUG_LIST_SEPARATOR = "+";
1213
+ var SLUG_ENTRY_SEPARATOR = "_";
1214
+ var SLUG_KEY_VALUE_SEPARATOR = "-";
1215
+ var SLUG_PATH_SEPARATOR = "~";
1216
+ var SLUG_COLLECTION_INDICATOR = "";
1217
+ var LayoutEntrySchema = S5.mutable(S5.Struct({
1218
+ id: S5.String,
1219
+ path: S5.optional(S5.String)
1220
+ }));
1221
+ var LayoutPartSchema = S5.Union(S5.Literal("sidebar"), S5.Literal("main"), S5.Literal("solo"), S5.Literal("complementary"), S5.Literal("fullScreen"));
1222
+ var LayoutPartsSchema = S5.partial(S5.mutable(S5.Record({
1223
+ key: LayoutPartSchema,
1224
+ value: S5.mutable(S5.Array(LayoutEntrySchema))
1225
+ })));
1226
+ var LayoutCoordinateSchema = S5.mutable(S5.Struct({
1227
+ part: LayoutPartSchema,
1228
+ entryId: S5.String
1229
+ }));
1230
+ var PartAdjustmentSchema = S5.Union(S5.Literal("increment-start"), S5.Literal("increment-end"), S5.Literal("pin-start"), S5.Literal("pin-end"), S5.Literal("close"), S5.Literal("solo"));
1231
+ var LayoutAdjustmentSchema = S5.mutable(S5.Struct({
1232
+ layoutCoordinate: LayoutCoordinateSchema,
1233
+ type: PartAdjustmentSchema
1234
+ }));
1235
+ var ActiveParts = S5.Record({
1236
+ key: S5.String,
1237
+ value: S5.Union(S5.String, S5.mutable(S5.Array(S5.String)))
1238
+ });
1239
+ var LocationProvidesSchema = S5.mutable(S5.Struct({
1240
+ location: S5.Struct({
1241
+ active: LayoutPartsSchema,
1242
+ closed: S5.Array(S5.String)
1243
+ })
1244
+ }));
1245
+ var isLayoutParts = (value) => {
1246
+ return S5.is(LayoutPartsSchema)(value);
1247
+ };
1248
+ var isLayoutAdjustment = (value) => {
1249
+ return S5.is(LayoutAdjustmentSchema)(value);
1250
+ };
1251
+ var openIds = (layout, parts) => {
1252
+ return Object.values(parts ? pick2(layout, parts) : layout).flatMap((part) => part?.map((entry) => entry.id) ?? []).filter((id) => id !== void 0);
1253
+ };
1254
+ var firstIdInPart = (layout, part) => {
1255
+ if (!layout) {
1256
+ return void 0;
1257
+ }
1258
+ return layout[part]?.at(0)?.id;
1259
+ };
1260
+ var indexInPart = (layout, layoutCoordinate) => {
1261
+ if (!layout || !layoutCoordinate) {
1262
+ return void 0;
1263
+ }
1264
+ const { part, entryId } = layoutCoordinate;
1265
+ return layout[part]?.findIndex((entry) => entry.id === entryId);
1266
+ };
1267
+ var partLength = (layout, part) => {
1268
+ if (!layout || !part) {
1269
+ return 0;
1270
+ }
1271
+ return layout[part]?.length ?? 0;
1272
+ };
1273
+ var NAVIGATION_PLUGIN = "dxos.org/plugin/navigation";
1274
+ var NAVIGATION_ACTION = `${NAVIGATION_PLUGIN}/action`;
1275
+ var NavigationAction;
1276
+ (function(NavigationAction2) {
1277
+ class Open extends S5.TaggedClass()(`${NAVIGATION_ACTION}/open`, {
1278
+ input: S5.Struct({
1279
+ activeParts: ActiveParts,
1280
+ noToggle: S5.optional(S5.Boolean)
1281
+ }),
1282
+ output: S5.Struct({
1283
+ open: S5.Array(S5.String)
1284
+ })
1285
+ }) {
1286
+ }
1287
+ NavigationAction2.Open = Open;
1288
+ class AddToActive extends S5.TaggedClass()(`${NAVIGATION_ACTION}/add-to-active`, {
1289
+ input: S5.Struct({
1290
+ id: S5.String,
1291
+ part: LayoutPartSchema,
1292
+ scrollIntoView: S5.optional(S5.Boolean),
1293
+ pivotId: S5.optional(S5.String),
1294
+ positioning: S5.optional(S5.Literal("start", "end"))
1295
+ }),
1296
+ output: S5.Void
1297
+ }) {
1298
+ }
1299
+ NavigationAction2.AddToActive = AddToActive;
1300
+ class Set2 extends S5.TaggedClass()(`${NAVIGATION_ACTION}/set`, {
1301
+ input: S5.Struct({
1302
+ activeParts: ActiveParts
1303
+ }),
1304
+ output: S5.Void
1305
+ }) {
1306
+ }
1307
+ NavigationAction2.Set = Set2;
1308
+ class Close extends S5.TaggedClass()(`${NAVIGATION_ACTION}/close`, {
1309
+ input: S5.Struct({
1310
+ activeParts: ActiveParts,
1311
+ noToggle: S5.optional(S5.Boolean)
1312
+ }),
1313
+ output: S5.Void
1314
+ }) {
1315
+ }
1316
+ NavigationAction2.Close = Close;
1317
+ class Adjust extends S5.TaggedClass()(`${NAVIGATION_ACTION}/adjust`, {
1318
+ input: LayoutAdjustmentSchema,
1319
+ output: S5.Void
1320
+ }) {
1321
+ }
1322
+ NavigationAction2.Adjust = Adjust;
1323
+ class Expose extends S5.TaggedClass()(`${NAVIGATION_ACTION}/expose`, {
1324
+ input: S5.Struct({
1325
+ id: S5.String
1326
+ }),
1327
+ output: S5.Void
1328
+ }) {
1329
+ }
1330
+ NavigationAction2.Expose = Expose;
1331
+ })(NavigationAction || (NavigationAction = {}));
1332
+
1333
+ // packages/sdk/app-framework/src/common/surface.ts
1334
+ var createSurface = (definition) => definition;
1335
+
1336
+ // packages/sdk/app-framework/src/common/translations.ts
1337
+ import { z } from "zod";
1338
+ var ResourceKey = z.union([
1339
+ z.string(),
1340
+ z.record(z.any())
1341
+ ]);
1342
+ var ResourceLanguage = z.record(ResourceKey);
1343
+ var Resource = z.record(ResourceLanguage);
1344
+
1345
+ // packages/sdk/app-framework/src/react/Surface.tsx
1346
+ var useSurfaces = () => {
1347
+ const surfaces = useCapabilities(Capabilities.ReactSurface);
1348
+ return useMemo2(() => surfaces.flat(), [
1349
+ surfaces
1350
+ ]);
1351
+ };
1352
+ var findCandidates = (surfaces, { role, data }) => {
1353
+ return Object.values(surfaces).filter((definition) => Array.isArray(definition.role) ? definition.role.includes(role) : definition.role === role).filter(({ filter }) => filter ? filter(data ?? {}) : true).toSorted(byDisposition2);
1354
+ };
1355
+ var isSurfaceAvailable = (context, { role, data }) => {
1356
+ const surfaces = context.requestCapabilities(Capabilities.ReactSurface);
1357
+ const candidates = findCandidates(surfaces.flat(), {
1358
+ role,
1359
+ data
1344
1360
  });
1345
- const { dispatch, dispatchPromise, undo, undoPromise } = createDispatcher((module) => context.requestCapabilities(Capabilities.IntentResolver, (c, moduleId) => {
1346
- return module ? moduleId === module : true;
1347
- }).flat());
1348
- const manager = context.requestCapability(Capabilities.PluginManager);
1349
- state.dispatch = (intentChain, depth) => {
1350
- return Effect2.gen(function* () {
1351
- yield* manager._activate(Events.SetupIntents);
1352
- return yield* dispatch(intentChain, depth);
1361
+ return candidates.length > 0;
1362
+ };
1363
+ var Surface = /* @__PURE__ */ memo(/* @__PURE__ */ forwardRef(({ id: _id, role, data: _data, limit, fallback, placeholder, ...rest }, forwardedRef) => {
1364
+ const surfaces = useSurfaces();
1365
+ const data = useDefaultValue(_data, () => ({}));
1366
+ const candidates = useMemo2(() => {
1367
+ const definitions = findCandidates(surfaces, {
1368
+ role,
1369
+ data
1353
1370
  });
1371
+ return limit ? definitions.slice(0, limit) : definitions;
1372
+ }, [
1373
+ surfaces,
1374
+ role,
1375
+ data,
1376
+ limit
1377
+ ]);
1378
+ const nodes = candidates.map(({ component: Component2, id }) => /* @__PURE__ */ React3.createElement(Component2, {
1379
+ ref: forwardedRef,
1380
+ key: id,
1381
+ id,
1382
+ role,
1383
+ data,
1384
+ limit,
1385
+ ...rest
1386
+ }));
1387
+ const suspense = placeholder ? /* @__PURE__ */ React3.createElement(Suspense, {
1388
+ fallback: placeholder
1389
+ }, nodes) : nodes;
1390
+ return fallback ? /* @__PURE__ */ React3.createElement(ErrorBoundary, {
1391
+ data,
1392
+ fallback
1393
+ }, suspense) : suspense;
1394
+ }));
1395
+
1396
+ // packages/sdk/app-framework/src/App.tsx
1397
+ import { effect as effect2 } from "@preact/signals-core";
1398
+ import React4 from "react";
1399
+ import { invariant as invariant2 } from "@dxos/invariant";
1400
+ import { create as create4 } from "@dxos/live-object";
1401
+
1402
+ // packages/sdk/app-framework/src/helpers.ts
1403
+ var topologicalSort = (nodes) => {
1404
+ const getDependencies = (nodeId, seen = /* @__PURE__ */ new Set(), path = /* @__PURE__ */ new Set()) => {
1405
+ if (path.has(nodeId)) {
1406
+ throw new Error(`Circular dependency detected involving ${nodeId}`);
1407
+ }
1408
+ if (seen.has(nodeId)) {
1409
+ return [];
1410
+ }
1411
+ const node = nodes.find((n) => n.id === nodeId);
1412
+ if (!node) {
1413
+ throw new Error(`Node ${nodeId} not found but is listed as a dependency`);
1414
+ }
1415
+ const newPath = /* @__PURE__ */ new Set([
1416
+ ...path,
1417
+ nodeId
1418
+ ]);
1419
+ const newSeen = /* @__PURE__ */ new Set([
1420
+ ...seen,
1421
+ nodeId
1422
+ ]);
1423
+ const dependsOn = node.dependsOn ?? [];
1424
+ return [
1425
+ ...dependsOn.flatMap((depId) => getDependencies(depId, newSeen, newPath)),
1426
+ nodeId
1427
+ ];
1354
1428
  };
1355
- state.dispatchPromise = async (intentChain) => {
1356
- await manager.activate(Events.SetupIntents);
1357
- return await dispatchPromise(intentChain);
1358
- };
1359
- state.undo = undo;
1360
- state.undoPromise = undoPromise;
1361
- return contributes(Capabilities.IntentDispatcher, state);
1429
+ const allDependencies = nodes.map((node) => node.id).flatMap((id) => getDependencies(id)).filter((id, index, self) => self.indexOf(id) === index);
1430
+ return allDependencies.map((id) => nodes.find((node) => node.id === id)).filter((node) => node !== void 0);
1431
+ };
1432
+
1433
+ // packages/sdk/app-framework/src/App.tsx
1434
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/sdk/app-framework/src/App.tsx";
1435
+ var ENABLED_KEY = "dxos.org/app-framework/enabled";
1436
+ var createApp = ({ pluginManager, pluginLoader: _pluginLoader, plugins = [], core = plugins.map(({ meta }) => meta.id), defaults = [], placeholder = null, fallback = DefaultFallback, cacheEnabled = false }) => {
1437
+ const pluginLoader = _pluginLoader ?? ((id) => {
1438
+ const plugin = plugins.find((plugin2) => plugin2.meta.id === id);
1439
+ invariant2(plugin, `Plugin not found: ${id}`, {
1440
+ F: __dxlog_file3,
1441
+ L: 68,
1442
+ S: void 0,
1443
+ A: [
1444
+ "plugin",
1445
+ "`Plugin not found: ${id}`"
1446
+ ]
1447
+ });
1448
+ return plugin;
1449
+ });
1450
+ const state = create4({
1451
+ ready: false,
1452
+ error: null
1453
+ });
1454
+ const cached = JSON.parse(localStorage.getItem(ENABLED_KEY) ?? "[]");
1455
+ const enabled = cacheEnabled && cached.length > 0 ? cached : defaults;
1456
+ const manager = pluginManager ?? new PluginManager({
1457
+ pluginLoader,
1458
+ plugins,
1459
+ core,
1460
+ enabled
1461
+ });
1462
+ manager.activation.on(({ event, state: _state, error }) => {
1463
+ if (event === Events.Startup.id) {
1464
+ state.ready = _state === "activated";
1465
+ }
1466
+ if (error && !state.ready && !state.error) {
1467
+ state.error = error;
1468
+ }
1469
+ });
1470
+ effect2(() => {
1471
+ cacheEnabled && localStorage.setItem(ENABLED_KEY, JSON.stringify(manager.enabled));
1472
+ });
1473
+ manager.context.contributeCapability({
1474
+ interface: Capabilities.PluginManager,
1475
+ implementation: manager,
1476
+ module: "dxos.org/app-framework/plugin-manager"
1477
+ });
1478
+ setupDevtools(manager);
1479
+ void manager.activate(Events.Startup);
1480
+ return () => /* @__PURE__ */ React4.createElement(ErrorBoundary, {
1481
+ fallback
1482
+ }, /* @__PURE__ */ React4.createElement(App, {
1483
+ placeholder,
1484
+ manager,
1485
+ state
1486
+ }));
1487
+ };
1488
+ var App = ({ placeholder, manager, state }) => {
1489
+ if (state.error) {
1490
+ throw state.error;
1491
+ }
1492
+ if (!state.ready) {
1493
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, placeholder);
1494
+ }
1495
+ const reactContexts = manager.context.requestCapabilities(Capabilities.ReactContext);
1496
+ const reactRoots = manager.context.requestCapabilities(Capabilities.ReactRoot);
1497
+ const ComposedContext = composeContexts(reactContexts);
1498
+ return /* @__PURE__ */ React4.createElement(PluginManagerProvider, {
1499
+ value: manager
1500
+ }, /* @__PURE__ */ React4.createElement(ComposedContext, null, reactRoots.map(({ id, root: Component2 }) => /* @__PURE__ */ React4.createElement(Component2, {
1501
+ key: id
1502
+ }))));
1503
+ };
1504
+ var DefaultFallback = ({ error }) => {
1505
+ return /* @__PURE__ */ React4.createElement("div", {
1506
+ style: {
1507
+ padding: "1rem"
1508
+ }
1509
+ }, /* @__PURE__ */ React4.createElement("h1", {
1510
+ style: {
1511
+ fontSize: "1.2rem",
1512
+ fontWeight: 700,
1513
+ margin: "0.5rem 0"
1514
+ }
1515
+ }, error.message), /* @__PURE__ */ React4.createElement("pre", null, error.stack));
1516
+ };
1517
+ var composeContexts = (contexts) => {
1518
+ if (contexts.length === 0) {
1519
+ return ({ children }) => /* @__PURE__ */ React4.createElement(React4.Fragment, null, children);
1520
+ }
1521
+ return topologicalSort(contexts).map(({ context }) => context).reduce((Acc, Next) => ({ children }) => /* @__PURE__ */ React4.createElement(Acc, null, /* @__PURE__ */ React4.createElement(Next, null, children)));
1522
+ };
1523
+ var setupDevtools = (manager) => {
1524
+ globalThis.composer ??= {};
1525
+ globalThis.composer.manager = manager;
1362
1526
  };
1363
1527
 
1364
1528
  export {
@@ -1390,14 +1554,42 @@ export {
1390
1554
  IntentAction,
1391
1555
  createResolver,
1392
1556
  createDispatcher,
1393
- intent_dispatcher_default,
1557
+ ErrorBoundary,
1558
+ usePluginManager,
1559
+ PluginManagerProvider,
1560
+ useCapabilities,
1561
+ useCapability,
1562
+ isSurfaceAvailable,
1563
+ Surface,
1564
+ useIntentDispatcher,
1565
+ useIntentResolver,
1566
+ IntentProvider,
1394
1567
  IntentPlugin,
1568
+ Toast,
1569
+ isLayoutMode,
1570
+ Layout,
1395
1571
  LAYOUT_PLUGIN,
1396
1572
  LAYOUT_ACTION,
1397
1573
  LayoutAction,
1574
+ SLUG_LIST_SEPARATOR,
1575
+ SLUG_ENTRY_SEPARATOR,
1576
+ SLUG_KEY_VALUE_SEPARATOR,
1577
+ SLUG_PATH_SEPARATOR,
1578
+ SLUG_COLLECTION_INDICATOR,
1579
+ ActiveParts,
1580
+ isLayoutParts,
1581
+ isLayoutAdjustment,
1582
+ openIds,
1583
+ firstIdInPart,
1584
+ indexInPart,
1585
+ partLength,
1586
+ NAVIGATION_PLUGIN,
1587
+ NAVIGATION_ACTION,
1588
+ NavigationAction,
1398
1589
  createSurface,
1399
1590
  ResourceKey,
1400
1591
  ResourceLanguage,
1401
- Resource
1592
+ Resource,
1593
+ createApp
1402
1594
  };
1403
- //# sourceMappingURL=chunk-G3HBVVT5.mjs.map
1595
+ //# sourceMappingURL=chunk-GNLU3GAU.mjs.map