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