@dxos/app-framework 0.10.0 → 0.11.0
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.
- package/.storybook/main.mts +1 -1
- package/.storybook/preview.mts +2 -2
- package/CHANGELOG.md +93 -0
- package/TASKS.md +11 -0
- package/dist/lib/chunk-SurfaceManager.mjs +960 -0
- package/dist/lib/chunk-SurfaceManager.mjs.map +1 -0
- package/dist/lib/chunk-capability.mjs +15 -0
- package/dist/lib/chunk-capability.mjs.map +1 -0
- package/dist/lib/{browser/chunk-FJ4765WW.mjs → chunk-context.mjs} +4 -5
- package/dist/lib/chunk-context.mjs.map +1 -0
- package/dist/lib/chunk-history-tracker.mjs +160 -0
- package/dist/lib/chunk-history-tracker.mjs.map +1 -0
- package/dist/lib/chunk-plugin-manager.mjs +1390 -0
- package/dist/lib/chunk-plugin-manager.mjs.map +1 -0
- package/dist/lib/chunk-plugin-manifest.mjs +125 -0
- package/dist/lib/chunk-plugin-manifest.mjs.map +1 -0
- package/dist/lib/chunk-process-manager-capability.mjs +126 -0
- package/dist/lib/chunk-process-manager-capability.mjs.map +1 -0
- package/dist/lib/chunk-rolldown-runtime.mjs +13 -0
- package/dist/lib/chunk-url-loader.mjs +347 -0
- package/dist/lib/chunk-url-loader.mjs.map +1 -0
- package/dist/lib/cli.mjs +78 -0
- package/dist/lib/cli.mjs.map +1 -0
- package/dist/lib/common/activation-events.mjs +35 -0
- package/dist/lib/common/activation-events.mjs.map +1 -0
- package/dist/lib/common/capabilities.mjs +184 -0
- package/dist/lib/common/capabilities.mjs.map +1 -0
- package/dist/lib/config.mjs +2 -0
- package/dist/lib/core/activation-event.mjs +55 -0
- package/dist/lib/core/activation-event.mjs.map +1 -0
- package/dist/lib/core/capability.mjs +189 -0
- package/dist/lib/core/capability.mjs.map +1 -0
- package/dist/lib/core/plugin-manager.mjs +2 -0
- package/dist/lib/core/plugin.mjs +340 -0
- package/dist/lib/core/plugin.mjs.map +1 -0
- package/dist/lib/core/url-loader.mjs +2 -0
- package/dist/lib/index.mjs +134 -0
- package/dist/lib/index.mjs.map +1 -0
- package/dist/lib/testing/react.mjs +70 -0
- package/dist/lib/testing/react.mjs.map +1 -0
- package/dist/lib/testing.mjs +399 -0
- package/dist/lib/testing.mjs.map +1 -0
- package/dist/lib/ui.mjs +636 -0
- package/dist/lib/ui.mjs.map +1 -0
- package/dist/lib/vite-plugin.mjs +986 -0
- package/dist/lib/vite-plugin.mjs.map +1 -0
- package/dist/plugin/node-esm/index.mjs +4 -3
- package/dist/plugin/node-esm/index.mjs.map +3 -3
- package/dist/plugin/node-esm/meta.json +1 -1
- package/dist/types/src/common/Role.d.ts +31 -0
- package/dist/types/src/common/Role.d.ts.map +1 -0
- package/dist/types/src/common/Role.test.d.ts +2 -0
- package/dist/types/src/common/Role.test.d.ts.map +1 -0
- package/dist/types/src/common/capabilities.d.ts +11 -2
- package/dist/types/src/common/capabilities.d.ts.map +1 -1
- package/dist/types/src/common/index.d.ts +1 -0
- package/dist/types/src/common/index.d.ts.map +1 -1
- package/dist/types/src/core/capability-manager.d.ts +1 -1
- package/dist/types/src/core/capability-manager.d.ts.map +1 -1
- package/dist/types/src/core/capability.d.ts +38 -5
- package/dist/types/src/core/capability.d.ts.map +1 -1
- package/dist/types/src/core/plugin-manager.d.ts +1 -1
- package/dist/types/src/core/plugin-manager.d.ts.map +1 -1
- package/dist/types/src/core/plugin.d.ts +14 -1
- package/dist/types/src/core/plugin.d.ts.map +1 -1
- package/dist/types/src/core/registry.d.ts +1 -1
- package/dist/types/src/core/registry.d.ts.map +1 -1
- package/dist/types/src/plugin-process-manager/history/capability.d.ts +1 -1
- package/dist/types/src/plugin-process-manager/process-manager-capability.d.ts +1 -1
- package/dist/types/src/plugin-process-manager/process-manager-capability.d.ts.map +1 -1
- package/dist/types/src/testing/StorybookErrorFallback.d.ts +15 -0
- package/dist/types/src/testing/StorybookErrorFallback.d.ts.map +1 -0
- package/dist/types/src/testing/harness.d.ts +1 -1
- package/dist/types/src/testing/harness.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +2 -0
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/testing/react.d.ts +4 -4
- package/dist/types/src/testing/react.d.ts.map +1 -1
- package/dist/types/src/testing/withPluginManager.d.ts.map +1 -1
- package/dist/types/src/testing/withPluginManager.stories.d.ts +6 -0
- package/dist/types/src/testing/withPluginManager.stories.d.ts.map +1 -1
- package/dist/types/src/testing/withSurfaceDebug.d.ts +10 -0
- package/dist/types/src/testing/withSurfaceDebug.d.ts.map +1 -0
- package/dist/types/src/ui/components/App/App.d.ts +0 -32
- package/dist/types/src/ui/components/App/App.d.ts.map +1 -1
- package/dist/types/src/ui/components/App/index.d.ts +1 -0
- package/dist/types/src/ui/components/App/index.d.ts.map +1 -1
- package/dist/types/src/ui/components/App/loader.d.ts +35 -0
- package/dist/types/src/ui/components/App/loader.d.ts.map +1 -0
- package/dist/types/src/ui/components/HomeSection/HomeSection.d.ts +26 -0
- package/dist/types/src/ui/components/HomeSection/HomeSection.d.ts.map +1 -0
- package/dist/types/src/ui/components/HomeSection/HomeSection.stories.d.ts +15 -0
- package/dist/types/src/ui/components/HomeSection/HomeSection.stories.d.ts.map +1 -0
- package/dist/types/src/ui/components/HomeSection/index.d.ts +2 -0
- package/dist/types/src/ui/components/HomeSection/index.d.ts.map +1 -0
- package/dist/types/src/ui/components/NamePopover/NamePopover.d.ts +14 -0
- package/dist/types/src/ui/components/NamePopover/NamePopover.d.ts.map +1 -0
- package/dist/types/src/ui/components/NamePopover/index.d.ts +2 -0
- package/dist/types/src/ui/components/NamePopover/index.d.ts.map +1 -0
- package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts +21 -9
- package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts +4 -1
- package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/SurfaceComponent.test.d.ts +2 -0
- package/dist/types/src/ui/components/Surface/SurfaceComponent.test.d.ts.map +1 -0
- package/dist/types/src/ui/components/Surface/SurfaceDebug.d.ts +40 -0
- package/dist/types/src/ui/components/Surface/SurfaceDebug.d.ts.map +1 -0
- package/dist/types/src/ui/components/Surface/SurfaceManager.d.ts +23 -0
- package/dist/types/src/ui/components/Surface/SurfaceManager.d.ts.map +1 -0
- package/dist/types/src/ui/components/Surface/SurfaceManagerContext.d.ts +11 -0
- package/dist/types/src/ui/components/Surface/SurfaceManagerContext.d.ts.map +1 -0
- package/dist/types/src/ui/components/Surface/SurfaceMetrics.d.ts +72 -0
- package/dist/types/src/ui/components/Surface/SurfaceMetrics.d.ts.map +1 -0
- package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/index.d.ts +20 -25
- package/dist/types/src/ui/components/Surface/index.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/types.d.ts +56 -52
- package/dist/types/src/ui/components/Surface/types.d.ts.map +1 -1
- package/dist/types/src/ui/components/index.d.ts +2 -0
- package/dist/types/src/ui/components/index.d.ts.map +1 -1
- package/dist/types/src/ui/hooks/useApp.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/moon.yml +25 -18
- package/package.json +58 -73
- package/src/common/Role.test.ts +41 -0
- package/src/common/Role.ts +54 -0
- package/src/common/capabilities.ts +17 -2
- package/src/common/index.ts +1 -0
- package/src/core/capability-manager.test.ts +1 -1
- package/src/core/capability-manager.ts +1 -1
- package/src/core/capability.ts +45 -6
- package/src/core/plugin-manager.test.ts +38 -3
- package/src/core/plugin-manager.ts +18 -1
- package/src/core/plugin.ts +16 -1
- package/src/core/registry.ts +1 -1
- package/src/plugin-process-manager/process-manager-capability.ts +25 -2
- package/src/testing/StorybookErrorFallback.tsx +40 -0
- package/src/testing/harness.ts +1 -1
- package/src/testing/index.ts +2 -0
- package/src/testing/react.test.tsx +2 -1
- package/src/testing/react.tsx +14 -8
- package/src/testing/withPluginManager.stories.tsx +16 -1
- package/src/testing/withPluginManager.tsx +13 -2
- package/src/testing/withSurfaceDebug.tsx +22 -0
- package/src/ui/components/App/App.tsx +7 -35
- package/src/ui/components/App/index.ts +1 -0
- package/src/ui/components/App/loader.ts +39 -0
- package/src/ui/components/HomeSection/HomeSection.stories.tsx +43 -0
- package/src/ui/components/HomeSection/HomeSection.tsx +69 -0
- package/src/ui/components/HomeSection/index.ts +5 -0
- package/src/ui/components/NamePopover/NamePopover.tsx +70 -0
- package/src/ui/components/NamePopover/index.ts +5 -0
- package/src/ui/components/Surface/DESIGN.md +136 -0
- package/src/ui/components/Surface/SurfaceComponent.stories.tsx +70 -41
- package/src/ui/components/Surface/SurfaceComponent.test.tsx +403 -0
- package/src/ui/components/Surface/SurfaceComponent.tsx +209 -189
- package/src/ui/components/Surface/SurfaceDebug.tsx +435 -0
- package/src/ui/components/Surface/SurfaceManager.ts +95 -0
- package/src/ui/components/Surface/SurfaceManagerContext.ts +23 -0
- package/src/ui/components/Surface/SurfaceMetrics.ts +202 -0
- package/src/ui/components/Surface/SurfaceProfilerContext.tsx +12 -2
- package/src/ui/components/Surface/index.ts +24 -22
- package/src/ui/components/Surface/types.test.ts +47 -54
- package/src/ui/components/Surface/types.ts +66 -91
- package/src/ui/components/index.ts +2 -0
- package/src/ui/hooks/useApp.tsx +7 -3
- package/src/vite-plugin/boot-loader/loader-app/boot-loader.css +1 -1
- package/tsconfig.json +3 -0
- package/vite.config.ts +26 -0
- package/dist/lib/browser/capability-S44TE2H7.mjs +0 -35
- package/dist/lib/browser/capability-S44TE2H7.mjs.map +0 -7
- package/dist/lib/browser/chunk-3NQLTQCP.mjs +0 -47
- package/dist/lib/browser/chunk-3NQLTQCP.mjs.map +0 -7
- package/dist/lib/browser/chunk-53HJHMS5.mjs +0 -7
- package/dist/lib/browser/chunk-53HJHMS5.mjs.map +0 -7
- package/dist/lib/browser/chunk-FJ4765WW.mjs.map +0 -7
- package/dist/lib/browser/chunk-J5LGTIGS.mjs +0 -10
- package/dist/lib/browser/chunk-J5LGTIGS.mjs.map +0 -7
- package/dist/lib/browser/chunk-KRJ4KK2W.mjs +0 -505
- package/dist/lib/browser/chunk-KRJ4KK2W.mjs.map +0 -7
- package/dist/lib/browser/chunk-LUH4Y5F2.mjs +0 -430
- package/dist/lib/browser/chunk-LUH4Y5F2.mjs.map +0 -7
- package/dist/lib/browser/chunk-NKVRSMFN.mjs +0 -95
- package/dist/lib/browser/chunk-NKVRSMFN.mjs.map +0 -7
- package/dist/lib/browser/chunk-OO53M5UK.mjs +0 -260
- package/dist/lib/browser/chunk-OO53M5UK.mjs.map +0 -7
- package/dist/lib/browser/chunk-OPTS3ZSN.mjs +0 -83
- package/dist/lib/browser/chunk-OPTS3ZSN.mjs.map +0 -7
- package/dist/lib/browser/chunk-Q2GLJTVV.mjs +0 -12
- package/dist/lib/browser/chunk-Q2GLJTVV.mjs.map +0 -7
- package/dist/lib/browser/chunk-SYXIYT6T.mjs +0 -143
- package/dist/lib/browser/chunk-SYXIYT6T.mjs.map +0 -7
- package/dist/lib/browser/chunk-U5MESPM5.mjs +0 -603
- package/dist/lib/browser/chunk-U5MESPM5.mjs.map +0 -7
- package/dist/lib/browser/chunk-UGYCLOXE.mjs +0 -1471
- package/dist/lib/browser/chunk-UGYCLOXE.mjs.map +0 -7
- package/dist/lib/browser/chunk-VF37YTXJ.mjs +0 -28
- package/dist/lib/browser/chunk-VF37YTXJ.mjs.map +0 -7
- package/dist/lib/browser/chunk-YUVQIOTB.mjs +0 -60
- package/dist/lib/browser/chunk-YUVQIOTB.mjs.map +0 -7
- package/dist/lib/browser/cli/index.mjs +0 -74
- package/dist/lib/browser/cli/index.mjs.map +0 -7
- package/dist/lib/browser/common/activation-events.mjs +0 -20
- package/dist/lib/browser/common/activation-events.mjs.map +0 -7
- package/dist/lib/browser/common/capabilities.mjs +0 -56
- package/dist/lib/browser/common/capabilities.mjs.map +0 -7
- package/dist/lib/browser/config/index.mjs +0 -8
- package/dist/lib/browser/config/index.mjs.map +0 -7
- package/dist/lib/browser/core/activation-event.mjs +0 -20
- package/dist/lib/browser/core/activation-event.mjs.map +0 -7
- package/dist/lib/browser/core/capability.mjs +0 -32
- package/dist/lib/browser/core/capability.mjs.map +0 -7
- package/dist/lib/browser/core/plugin-manager.mjs +0 -19
- package/dist/lib/browser/core/plugin-manager.mjs.map +0 -7
- package/dist/lib/browser/core/plugin.mjs +0 -51
- package/dist/lib/browser/core/plugin.mjs.map +0 -7
- package/dist/lib/browser/core/url-loader.mjs +0 -24
- package/dist/lib/browser/core/url-loader.mjs.map +0 -7
- package/dist/lib/browser/index.mjs +0 -98
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/browser/process-manager-capability-QK4BMKMN.mjs +0 -132
- package/dist/lib/browser/process-manager-capability-QK4BMKMN.mjs.map +0 -7
- package/dist/lib/browser/testing/index.mjs +0 -359
- package/dist/lib/browser/testing/index.mjs.map +0 -7
- package/dist/lib/browser/testing/react.mjs +0 -78
- package/dist/lib/browser/testing/react.mjs.map +0 -7
- package/dist/lib/browser/ui/index.mjs +0 -60
- package/dist/lib/browser/ui/index.mjs.map +0 -7
- package/dist/lib/node-esm/capability-3YRF77LV.mjs +0 -36
- package/dist/lib/node-esm/capability-3YRF77LV.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-2UPUZXGU.mjs +0 -9
- package/dist/lib/node-esm/chunk-2UPUZXGU.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-37Z53PXZ.mjs +0 -10
- package/dist/lib/node-esm/chunk-37Z53PXZ.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-4SE7SX7N.mjs +0 -261
- package/dist/lib/node-esm/chunk-4SE7SX7N.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-BMW6P6QA.mjs +0 -48
- package/dist/lib/node-esm/chunk-BMW6P6QA.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-COHOWGGJ.mjs +0 -144
- package/dist/lib/node-esm/chunk-COHOWGGJ.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-DRT75WGD.mjs +0 -604
- package/dist/lib/node-esm/chunk-DRT75WGD.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-FKMVORZN.mjs +0 -431
- package/dist/lib/node-esm/chunk-FKMVORZN.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-FPW45EZH.mjs +0 -14
- package/dist/lib/node-esm/chunk-FPW45EZH.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-GLH4LGHZ.mjs +0 -84
- package/dist/lib/node-esm/chunk-GLH4LGHZ.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +0 -11
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-IL7O7IRX.mjs +0 -1472
- package/dist/lib/node-esm/chunk-IL7O7IRX.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-ND2HETHD.mjs +0 -506
- package/dist/lib/node-esm/chunk-ND2HETHD.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-TLKYZKPW.mjs +0 -29
- package/dist/lib/node-esm/chunk-TLKYZKPW.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-VCPGX7WN.mjs +0 -62
- package/dist/lib/node-esm/chunk-VCPGX7WN.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-XSZMX53L.mjs +0 -96
- package/dist/lib/node-esm/chunk-XSZMX53L.mjs.map +0 -7
- package/dist/lib/node-esm/cli/index.mjs +0 -75
- package/dist/lib/node-esm/cli/index.mjs.map +0 -7
- package/dist/lib/node-esm/common/activation-events.mjs +0 -21
- package/dist/lib/node-esm/common/activation-events.mjs.map +0 -7
- package/dist/lib/node-esm/common/capabilities.mjs +0 -57
- package/dist/lib/node-esm/common/capabilities.mjs.map +0 -7
- package/dist/lib/node-esm/config/index.mjs +0 -9
- package/dist/lib/node-esm/config/index.mjs.map +0 -7
- package/dist/lib/node-esm/core/activation-event.mjs +0 -21
- package/dist/lib/node-esm/core/activation-event.mjs.map +0 -7
- package/dist/lib/node-esm/core/capability.mjs +0 -33
- package/dist/lib/node-esm/core/capability.mjs.map +0 -7
- package/dist/lib/node-esm/core/plugin-manager.mjs +0 -20
- package/dist/lib/node-esm/core/plugin-manager.mjs.map +0 -7
- package/dist/lib/node-esm/core/plugin.mjs +0 -52
- package/dist/lib/node-esm/core/plugin.mjs.map +0 -7
- package/dist/lib/node-esm/core/url-loader.mjs +0 -25
- package/dist/lib/node-esm/core/url-loader.mjs.map +0 -7
- package/dist/lib/node-esm/index.mjs +0 -99
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/process-manager-capability-5S7WZ2JR.mjs +0 -133
- package/dist/lib/node-esm/process-manager-capability-5S7WZ2JR.mjs.map +0 -7
- package/dist/lib/node-esm/testing/index.mjs +0 -360
- package/dist/lib/node-esm/testing/index.mjs.map +0 -7
- package/dist/lib/node-esm/testing/react.mjs +0 -79
- package/dist/lib/node-esm/testing/react.mjs.map +0 -7
- package/dist/lib/node-esm/ui/index.mjs +0 -61
- package/dist/lib/node-esm/ui/index.mjs.map +0 -7
- package/dist/types/src/ui/components/Surface/SurfaceInfo.d.ts +0 -11
- package/dist/types/src/ui/components/Surface/SurfaceInfo.d.ts.map +0 -1
- package/src/ui/components/Surface/SurfaceInfo.tsx +0 -106
- package/vitest.config.ts +0 -14
package/dist/lib/ui.mjs
ADDED
|
@@ -0,0 +1,636 @@
|
|
|
1
|
+
import { a as make } from "./chunk-plugin-manager.mjs";
|
|
2
|
+
import { AtomRegistry, OperationInvoker, PluginManager, ProcessManagerRuntime, ReactContext, ReactRoot } from "./common/capabilities.mjs";
|
|
3
|
+
import { SetupReactSurface, Startup } from "./common/activation-events.mjs";
|
|
4
|
+
import { t as PluginManagerContext } from "./chunk-context.mjs";
|
|
5
|
+
import { C as topologicalSort, S as usePluginManager, _ as surfaceMetrics, a as makeFilter, b as PluginManagerProvider, c as SurfaceProfilerProvider, d as useSurfaceProfilerEntries, f as useSurfaceProfilerStats, g as setSurfaceDebug, h as isSurfaceDebugEnabled, i as isFilter, l as useSurfaceProfilerCallback, m as useSurfaceManager, n as create, o as SurfaceComponent, p as SurfaceManagerProvider, r as createWeb, s as useIsSurfaceAvailable, t as SurfaceManager, u as useSurfaceProfilerClear, v as useSurfaceMetrics, x as useOptionalPluginManager, y as SurfaceContext } from "./chunk-SurfaceManager.mjs";
|
|
6
|
+
import * as Effect from "effect/Effect";
|
|
7
|
+
import * as Layer from "effect/Layer";
|
|
8
|
+
import { Atom } from "@effect-atom/atom";
|
|
9
|
+
import { invariant } from "@dxos/invariant";
|
|
10
|
+
import { log } from "@dxos/log";
|
|
11
|
+
import * as Fiber from "effect/Fiber";
|
|
12
|
+
import * as PubSub from "effect/PubSub";
|
|
13
|
+
import { EffectEx } from "@dxos/effect";
|
|
14
|
+
import * as Queue from "effect/Queue";
|
|
15
|
+
import { forwardRef, use, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
16
|
+
import { ErrorBoundary, ErrorFallback } from "@dxos/react-error-boundary";
|
|
17
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
18
|
+
import { raise } from "@dxos/debug";
|
|
19
|
+
import { useAsyncEffect, useDefaultValue } from "@dxos/react-hooks";
|
|
20
|
+
import { RegistryContext, useAtomValue } from "@effect-atom/atom-react";
|
|
21
|
+
import { ContextProtocolProvider } from "@dxos/web-context-react";
|
|
22
|
+
import { Operation, ServiceResolver } from "@dxos/compute";
|
|
23
|
+
import { Button, Input, Popover, SystemIconButton } from "@dxos/react-ui";
|
|
24
|
+
import { mx } from "@dxos/ui-theme";
|
|
25
|
+
//#region src/ui/hooks/useApp.tsx
|
|
26
|
+
var __dxlog_file$1 = "/__w/dxos/dxos/packages/sdk/app-framework/src/ui/hooks/useApp.tsx";
|
|
27
|
+
var ENABLED_KEY = "org.dxos.app-framework.enabled";
|
|
28
|
+
/**
|
|
29
|
+
* Expected usage is for this to be the entrypoint of the application.
|
|
30
|
+
* Initializes plugins and renders the root components.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* const plugins = [LayoutPlugin(), MyPlugin()];
|
|
34
|
+
* const defaults = [MyPluginId];
|
|
35
|
+
* const fallback = () => <div>Initializing Plugins...</div>;
|
|
36
|
+
* const App = useApp({ plugins, defaults, fallback });
|
|
37
|
+
* createRoot(document.getElementById('root')!).render(
|
|
38
|
+
* <StrictMode>
|
|
39
|
+
* <App />
|
|
40
|
+
* </StrictMode>,
|
|
41
|
+
* );
|
|
42
|
+
*
|
|
43
|
+
* @param params.pluginLoader A function which loads new plugins.
|
|
44
|
+
* @param params.plugins All plugins available to the application. Plugins whose `meta.profile.tags` includes `'system'` are treated as core (force-enabled, not user-toggleable).
|
|
45
|
+
* @param params.defaults Default plugins are enabled by default but can be disabled by the user.
|
|
46
|
+
* @param params.cacheEnabled Whether to cache enabled plugins in localStorage.
|
|
47
|
+
* @param params.safeMode Whether to enable safe mode, which disables optional plugins.
|
|
48
|
+
* @param params.fallback Fallback component to render if an error occurs during startup.
|
|
49
|
+
*/
|
|
50
|
+
var useApp = ({ pluginManager, pluginLoader: pluginLoaderProp, onPluginRemove, pluginRegistryProvider, plugins: pluginsProp, defaults: defaultsProp, setupEvents: setupEventsProp, fallback = ErrorFallback, cacheEnabled = false, safeMode = false, debounce = 0, timeout = 3e4 }) => {
|
|
51
|
+
const plugins = useDefaultValue(pluginsProp, () => []);
|
|
52
|
+
const defaults = useDefaultValue(defaultsProp, () => []);
|
|
53
|
+
const setupEvents = useDefaultValue(setupEventsProp, () => []);
|
|
54
|
+
const pluginLoader = useMemo(() => pluginLoaderProp ?? ((id) => Effect.sync(() => {
|
|
55
|
+
const plugin = plugins.find((plugin) => plugin.meta.profile.key === id);
|
|
56
|
+
invariant(plugin, `Plugin not found: ${id}`, {
|
|
57
|
+
"~LogMeta": "~LogMeta",
|
|
58
|
+
F: __dxlog_file$1,
|
|
59
|
+
L: 127,
|
|
60
|
+
S: void 0,
|
|
61
|
+
A: ["plugin", "`Plugin not found: ${id}`"]
|
|
62
|
+
});
|
|
63
|
+
return { plugin };
|
|
64
|
+
})), [pluginLoaderProp, plugins]);
|
|
65
|
+
const readyRef = useRef(false);
|
|
66
|
+
const [ready, setReady] = useState(false);
|
|
67
|
+
const errorRef = useRef(null);
|
|
68
|
+
const [error, setError] = useState(null);
|
|
69
|
+
const [startupProgress, setStartupProgress] = useState({
|
|
70
|
+
activated: 0,
|
|
71
|
+
total: 0,
|
|
72
|
+
progress: 0
|
|
73
|
+
});
|
|
74
|
+
const cached = useMemo(() => JSON.parse(localStorage.getItem(ENABLED_KEY) ?? "[]"), []);
|
|
75
|
+
const enabled = useMemo(() => safeMode ? [] : cacheEnabled && cached.length > 0 ? cached : defaults, [
|
|
76
|
+
safeMode,
|
|
77
|
+
cacheEnabled,
|
|
78
|
+
cached,
|
|
79
|
+
defaults
|
|
80
|
+
]);
|
|
81
|
+
const isExternalManager = !!pluginManager;
|
|
82
|
+
const manager = useMemo(() => {
|
|
83
|
+
const mgr = pluginManager ?? make({
|
|
84
|
+
pluginLoader,
|
|
85
|
+
plugins,
|
|
86
|
+
enabled,
|
|
87
|
+
onRemove: onPluginRemove,
|
|
88
|
+
pluginRegistryProvider
|
|
89
|
+
});
|
|
90
|
+
log("useApp: useMemo created/reused manager", { provided: !!pluginManager }, {
|
|
91
|
+
"~LogMeta": "~LogMeta",
|
|
92
|
+
F: __dxlog_file$1,
|
|
93
|
+
L: 159,
|
|
94
|
+
S: void 0
|
|
95
|
+
});
|
|
96
|
+
return mgr;
|
|
97
|
+
}, [
|
|
98
|
+
pluginManager,
|
|
99
|
+
pluginLoader,
|
|
100
|
+
plugins,
|
|
101
|
+
enabled,
|
|
102
|
+
onPluginRemove,
|
|
103
|
+
pluginRegistryProvider
|
|
104
|
+
]);
|
|
105
|
+
useEffect(() => {
|
|
106
|
+
if (!cacheEnabled) return;
|
|
107
|
+
return manager.registry.subscribe(manager.enabled, (value) => {
|
|
108
|
+
localStorage.setItem(ENABLED_KEY, JSON.stringify(value));
|
|
109
|
+
});
|
|
110
|
+
}, [cacheEnabled, manager]);
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
setupDevtools(manager);
|
|
113
|
+
}, [manager]);
|
|
114
|
+
useAsyncEffect(async () => {
|
|
115
|
+
log("useApp: effect mount", void 0, {
|
|
116
|
+
"~LogMeta": "~LogMeta",
|
|
117
|
+
F: __dxlog_file$1,
|
|
118
|
+
L: 177,
|
|
119
|
+
S: void 0
|
|
120
|
+
});
|
|
121
|
+
manager.capabilities.contribute({
|
|
122
|
+
interface: PluginManager,
|
|
123
|
+
implementation: manager,
|
|
124
|
+
module: "org.dxos.app-framework.plugin-manager"
|
|
125
|
+
});
|
|
126
|
+
manager.capabilities.contribute({
|
|
127
|
+
interface: AtomRegistry,
|
|
128
|
+
implementation: manager.registry,
|
|
129
|
+
module: "org.dxos.app-framework.atom-registry"
|
|
130
|
+
});
|
|
131
|
+
const fiber = Effect.gen(function* () {
|
|
132
|
+
const queue = yield* PubSub.subscribe(manager.activation);
|
|
133
|
+
const listener = yield* Effect.forkDaemon(Queue.take(queue).pipe(Effect.tap(({ event, state, module, error: error$ }) => Effect.sync(() => {
|
|
134
|
+
if (event === Startup.id && state === "activated" && !module) {
|
|
135
|
+
clearTimeout(timeoutId);
|
|
136
|
+
setReady(true);
|
|
137
|
+
readyRef.current = true;
|
|
138
|
+
globalThis.composer?.profiler?.dump();
|
|
139
|
+
if (typeof window !== "undefined") window.dispatchEvent(new CustomEvent("app-framework:startup-activated"));
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (module && state === "activating" && !readyRef.current) setStartupProgress((current) => ({
|
|
143
|
+
...current,
|
|
144
|
+
event: event || void 0,
|
|
145
|
+
module,
|
|
146
|
+
humanizedName: humanizeModuleId(module)
|
|
147
|
+
}));
|
|
148
|
+
if (module && state === "activated" && !readyRef.current) {
|
|
149
|
+
const active = manager.getActive();
|
|
150
|
+
const total = manager.getModules().length;
|
|
151
|
+
setStartupProgress((current) => ({
|
|
152
|
+
...current,
|
|
153
|
+
activated: active.length,
|
|
154
|
+
total,
|
|
155
|
+
progress: total > 0 ? active.length / total : 0
|
|
156
|
+
}));
|
|
157
|
+
}
|
|
158
|
+
if (event && !module && state === "activating" && !readyRef.current) setStartupProgress((current) => ({
|
|
159
|
+
...current,
|
|
160
|
+
event,
|
|
161
|
+
module: void 0,
|
|
162
|
+
humanizedName: humanizeEventKey(event)
|
|
163
|
+
}));
|
|
164
|
+
if (error$ && !readyRef.current) {
|
|
165
|
+
setError(error$);
|
|
166
|
+
errorRef.current = error$;
|
|
167
|
+
}
|
|
168
|
+
})), Effect.forever));
|
|
169
|
+
yield* Effect.all([
|
|
170
|
+
...setupEvents.map((event) => manager.activate(event)),
|
|
171
|
+
manager.activate(SetupReactSurface),
|
|
172
|
+
manager.activate(Startup)
|
|
173
|
+
]);
|
|
174
|
+
return yield* Fiber.join(listener);
|
|
175
|
+
}).pipe(Effect.scoped, Effect.runFork);
|
|
176
|
+
const timeoutId = setTimeout(() => {
|
|
177
|
+
if (!readyRef.current && !errorRef.current) {
|
|
178
|
+
log.warn("startup timeout diagnostic", {
|
|
179
|
+
eventsFired: manager.getEventsFired(),
|
|
180
|
+
activeModules: manager.getActive(),
|
|
181
|
+
pendingReset: manager.getPendingReset()
|
|
182
|
+
}, {
|
|
183
|
+
"~LogMeta": "~LogMeta",
|
|
184
|
+
F: __dxlog_file$1,
|
|
185
|
+
L: 297,
|
|
186
|
+
S: void 0
|
|
187
|
+
});
|
|
188
|
+
EffectEx.runAndForwardErrors(Fiber.interrupt(fiber));
|
|
189
|
+
setError(/* @__PURE__ */ new Error(`Startup timed out after ${timeout}ms`));
|
|
190
|
+
}
|
|
191
|
+
}, timeout);
|
|
192
|
+
return () => {
|
|
193
|
+
log("useApp: effect cleanup", void 0, {
|
|
194
|
+
"~LogMeta": "~LogMeta",
|
|
195
|
+
F: __dxlog_file$1,
|
|
196
|
+
L: 308,
|
|
197
|
+
S: void 0
|
|
198
|
+
});
|
|
199
|
+
clearTimeout(timeoutId);
|
|
200
|
+
EffectEx.runAndForwardErrors(Fiber.interrupt(fiber));
|
|
201
|
+
if (!isExternalManager) EffectEx.runAndForwardErrors(manager.shutdown());
|
|
202
|
+
};
|
|
203
|
+
}, [manager]);
|
|
204
|
+
const progressRef = useRef(startupProgress);
|
|
205
|
+
progressRef.current = startupProgress;
|
|
206
|
+
const surfaces = useMemo(() => new SurfaceManager(manager.capabilities), [manager]);
|
|
207
|
+
return useCallback(() => /* @__PURE__ */ jsx(ErrorBoundary, {
|
|
208
|
+
name: "app",
|
|
209
|
+
FallbackComponent: fallback,
|
|
210
|
+
children: /* @__PURE__ */ jsx(PluginManagerProvider, {
|
|
211
|
+
value: manager,
|
|
212
|
+
children: /* @__PURE__ */ jsx(ContextProtocolProvider, {
|
|
213
|
+
value: manager,
|
|
214
|
+
context: PluginManagerContext,
|
|
215
|
+
children: /* @__PURE__ */ jsx(RegistryContext.Provider, {
|
|
216
|
+
value: manager.registry,
|
|
217
|
+
children: /* @__PURE__ */ jsx(SurfaceManagerProvider, {
|
|
218
|
+
value: surfaces,
|
|
219
|
+
children: /* @__PURE__ */ jsx(App, {
|
|
220
|
+
ready,
|
|
221
|
+
error,
|
|
222
|
+
debounce,
|
|
223
|
+
progress: progressRef.current
|
|
224
|
+
})
|
|
225
|
+
})
|
|
226
|
+
})
|
|
227
|
+
})
|
|
228
|
+
})
|
|
229
|
+
}), [
|
|
230
|
+
fallback,
|
|
231
|
+
manager,
|
|
232
|
+
surfaces,
|
|
233
|
+
ready,
|
|
234
|
+
error
|
|
235
|
+
]);
|
|
236
|
+
};
|
|
237
|
+
var setupDevtools = (manager) => {
|
|
238
|
+
globalThis.composer ??= {};
|
|
239
|
+
globalThis.composer.manager = manager;
|
|
240
|
+
};
|
|
241
|
+
/**
|
|
242
|
+
* Extracts a human-readable label from a module ID.
|
|
243
|
+
*
|
|
244
|
+
* Module IDs follow `org.dxos.plugin.<plugin-slug>.module.<module-name>`,
|
|
245
|
+
* where `<plugin-slug>` is kebab-case and `<module-name>` is either an
|
|
246
|
+
* explicit string (often kebab-case, e.g. `'observability'`, `'namespace'`)
|
|
247
|
+
* or a capability tag in PascalCase from `Capability.getModuleTag(...)`
|
|
248
|
+
* (e.g. `'ReactSurface'`, `'AppGraphBuilder'`). The output is
|
|
249
|
+
* `"Title Case Plugin: kebab-module"` so the visible status names both the
|
|
250
|
+
* plugin and the aspect being activated, helping disambiguate the multiple
|
|
251
|
+
* modules a plugin contributes.
|
|
252
|
+
*
|
|
253
|
+
* Examples:
|
|
254
|
+
* - "org.dxos.plugin.markdown.module.ReactSurface" → "Markdown: react-surface"
|
|
255
|
+
* - "org.dxos.plugin.observability.module.AppGraphBuilder" → "Observability: app-graph-builder"
|
|
256
|
+
* - "org.dxos.plugin.observability.module.observability" → "Observability"
|
|
257
|
+
* (the module name matches the plugin slug — collapsed to avoid
|
|
258
|
+
* "Observability: observability" noise.)
|
|
259
|
+
*/
|
|
260
|
+
var humanizeModuleId = (moduleId) => {
|
|
261
|
+
const match = moduleId.match(/\.plugin\.([^.]+)\.module\.(.+)$/);
|
|
262
|
+
if (!match) {
|
|
263
|
+
const parts = moduleId.split(".");
|
|
264
|
+
return parts[parts.length - 1];
|
|
265
|
+
}
|
|
266
|
+
const [, pluginSlug, moduleName] = match;
|
|
267
|
+
const pluginLabel = pluginSlug.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
268
|
+
const moduleLabel = moduleName.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2").toLowerCase();
|
|
269
|
+
if (moduleLabel === pluginSlug) return pluginLabel;
|
|
270
|
+
return `${pluginLabel}: ${moduleLabel}`;
|
|
271
|
+
};
|
|
272
|
+
/**
|
|
273
|
+
* Extracts a human-readable label from an activation event key.
|
|
274
|
+
* E.g., "org.dxos.app-framework.event.setup-react-surface" → "Setup React Surface".
|
|
275
|
+
*/
|
|
276
|
+
var humanizeEventKey = (eventKey) => {
|
|
277
|
+
const id = eventKey.split(":")[0];
|
|
278
|
+
const match = id.match(/\.event\.(.+)$/);
|
|
279
|
+
return (match ? match[1] : id.split(".").pop() ?? id).split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
280
|
+
};
|
|
281
|
+
//#endregion
|
|
282
|
+
//#region src/ui/hooks/useCapabilities.ts
|
|
283
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/sdk/app-framework/src/ui/hooks/useCapabilities.ts";
|
|
284
|
+
/** Stable empty result for capability lookups made outside a plugin manager. */
|
|
285
|
+
var emptyCapabilities = Atom.make(() => []);
|
|
286
|
+
/** Stable atom yielding `undefined`, used as the fallback for optional atom-capability lookups. */
|
|
287
|
+
var emptyAtomValue = Atom.make(() => void 0);
|
|
288
|
+
/**
|
|
289
|
+
* Hook to request capabilities from the plugin context.
|
|
290
|
+
* @returns An array of capabilities.
|
|
291
|
+
*/
|
|
292
|
+
var useCapabilities = (interfaceDef) => {
|
|
293
|
+
return useAtomValue(usePluginManager().capabilities.atom(interfaceDef));
|
|
294
|
+
};
|
|
295
|
+
/**
|
|
296
|
+
* Hook to request a capability from the plugin context.
|
|
297
|
+
* @returns The capability.
|
|
298
|
+
* @throws If no capability is found.
|
|
299
|
+
*/
|
|
300
|
+
var useCapability = (interfaceDef) => {
|
|
301
|
+
const capabilities = useCapabilities(interfaceDef);
|
|
302
|
+
invariant(capabilities.length > 0, `No capability found for ${interfaceDef.identifier}`, {
|
|
303
|
+
"~LogMeta": "~LogMeta",
|
|
304
|
+
F: __dxlog_file,
|
|
305
|
+
L: 38,
|
|
306
|
+
S: void 0,
|
|
307
|
+
A: ["capabilities.length > 0", "`No capability found for ${interfaceDef.identifier}`"]
|
|
308
|
+
});
|
|
309
|
+
return capabilities[0];
|
|
310
|
+
};
|
|
311
|
+
/**
|
|
312
|
+
* Hook to request capabilities without requiring a plugin manager.
|
|
313
|
+
* @returns An array of capabilities, or an empty array when rendered outside a {@link PluginManagerProvider}.
|
|
314
|
+
*/
|
|
315
|
+
var useOptionalCapabilities = (interfaceDef) => {
|
|
316
|
+
const manager = useOptionalPluginManager();
|
|
317
|
+
return useAtomValue(manager ? manager.capabilities.atom(interfaceDef) : emptyCapabilities);
|
|
318
|
+
};
|
|
319
|
+
/**
|
|
320
|
+
* Hook to request a single capability without requiring a plugin manager.
|
|
321
|
+
* @returns The first matching capability, or `undefined` when none is registered (or there is no plugin manager).
|
|
322
|
+
*/
|
|
323
|
+
var useOptionalCapability = (interfaceDef) => useOptionalCapabilities(interfaceDef)[0];
|
|
324
|
+
/**
|
|
325
|
+
* Hook to get the current value of an atom capability.
|
|
326
|
+
* Automatically subscribes to changes.
|
|
327
|
+
* @example const settings = useAtomCapability(CommentCapabilities.Settings);
|
|
328
|
+
*/
|
|
329
|
+
var useAtomCapability = (atomCapability) => {
|
|
330
|
+
return useAtomValue(useCapability(atomCapability));
|
|
331
|
+
};
|
|
332
|
+
/**
|
|
333
|
+
* Hook to get value and updater for an atom capability.
|
|
334
|
+
* Returns [currentValue, updateFn] similar to useState.
|
|
335
|
+
* @example const [settings, updateSettings] = useAtomCapabilityState(CommentCapabilities.Settings);
|
|
336
|
+
*/
|
|
337
|
+
var useAtomCapabilityState = (atomCapability) => {
|
|
338
|
+
const registry = useCapability(AtomRegistry);
|
|
339
|
+
const atom = useCapability(atomCapability);
|
|
340
|
+
return [useAtomValue(atom), useCallback((fn) => {
|
|
341
|
+
registry.set(atom, fn(registry.get(atom)));
|
|
342
|
+
}, [registry, atom])];
|
|
343
|
+
};
|
|
344
|
+
/**
|
|
345
|
+
* Tolerant variant of {@link useAtomCapabilityState}: returns `[undefined, noop]` when the atom
|
|
346
|
+
* capability is not registered (e.g. the contributing plugin is not installed) rather than
|
|
347
|
+
* throwing. The updater is a no-op while the capability is absent.
|
|
348
|
+
*/
|
|
349
|
+
var useOptionalAtomCapabilityState = (atomCapability) => {
|
|
350
|
+
const registry = useOptionalCapability(AtomRegistry);
|
|
351
|
+
const atom = useOptionalCapability(atomCapability);
|
|
352
|
+
return [useAtomValue(atom ?? emptyAtomValue), useCallback((fn) => {
|
|
353
|
+
if (registry && atom) registry.set(atom, fn(registry.get(atom)));
|
|
354
|
+
}, [registry, atom])];
|
|
355
|
+
};
|
|
356
|
+
/**
|
|
357
|
+
* Hook to get the operation invoker capability.
|
|
358
|
+
*/
|
|
359
|
+
var useOperationInvoker = () => useCapability(OperationInvoker);
|
|
360
|
+
//#endregion
|
|
361
|
+
//#region src/ui/hooks/useLoading.tsx
|
|
362
|
+
var LoadingState = /* @__PURE__ */ function(LoadingState) {
|
|
363
|
+
LoadingState[LoadingState["Loading"] = 0] = "Loading";
|
|
364
|
+
LoadingState[LoadingState["FadeIn"] = 1] = "FadeIn";
|
|
365
|
+
LoadingState[LoadingState["FadeOut"] = 2] = "FadeOut";
|
|
366
|
+
LoadingState[LoadingState["Done"] = 3] = "Done";
|
|
367
|
+
return LoadingState;
|
|
368
|
+
}({});
|
|
369
|
+
/**
|
|
370
|
+
* To avoid "flashing" the placeholder, we wait a period of time before starting the loading animation.
|
|
371
|
+
* If loading completes during this time the placehoder is not shown, otherwise is it displayed for a minimum period of time.
|
|
372
|
+
*
|
|
373
|
+
* States:
|
|
374
|
+
* 0: Loading - Wait for a period of time before starting the loading animation.
|
|
375
|
+
* 1: Fade-in - Display a loading animation.
|
|
376
|
+
* 2: Fade-out - Fade out the loading animation.
|
|
377
|
+
* 3: Done - Remove the placeholder.
|
|
378
|
+
*/
|
|
379
|
+
var useLoading = (ready, debounce = 0) => {
|
|
380
|
+
const [stage, setStage] = useState(0);
|
|
381
|
+
const readyRef = useRef(ready);
|
|
382
|
+
readyRef.current = ready;
|
|
383
|
+
useEffect(() => {
|
|
384
|
+
if (!debounce) return;
|
|
385
|
+
const i = setInterval(() => {
|
|
386
|
+
setStage((stage) => {
|
|
387
|
+
const isReady = readyRef.current;
|
|
388
|
+
switch (stage) {
|
|
389
|
+
case 0:
|
|
390
|
+
if (!isReady) return 1;
|
|
391
|
+
clearInterval(i);
|
|
392
|
+
return 3;
|
|
393
|
+
case 1:
|
|
394
|
+
if (isReady) return 2;
|
|
395
|
+
break;
|
|
396
|
+
case 2:
|
|
397
|
+
clearInterval(i);
|
|
398
|
+
return 3;
|
|
399
|
+
}
|
|
400
|
+
return stage;
|
|
401
|
+
});
|
|
402
|
+
}, debounce);
|
|
403
|
+
return () => clearInterval(i);
|
|
404
|
+
}, [debounce]);
|
|
405
|
+
if (!debounce) return ready ? 3 : 0;
|
|
406
|
+
return stage;
|
|
407
|
+
};
|
|
408
|
+
//#endregion
|
|
409
|
+
//#region src/ui/hooks/useProcessManagerRuntime.ts
|
|
410
|
+
/**
|
|
411
|
+
* Resolve the shared {@link Capabilities.ProcessManagerRuntime} from the plugin context.
|
|
412
|
+
*/
|
|
413
|
+
var useProcessManagerRuntime = () => useCapability(ProcessManagerRuntime);
|
|
414
|
+
/**
|
|
415
|
+
* Build a callback that runs an effect on the {@link Capabilities.ProcessManagerRuntime}
|
|
416
|
+
* with space-scoped services resolved via {@link ServiceResolver.provide}.
|
|
417
|
+
*
|
|
418
|
+
* The `tags` tuple must list every service the effect requires (beyond the
|
|
419
|
+
* fixed {@link Capabilities.ProcessManagerRuntimeServices}); these services are
|
|
420
|
+
* resolved for the given `spaceId` through the runtime's service resolver.
|
|
421
|
+
*
|
|
422
|
+
* Nested `Operation.invoke` / `Operation.schedule` calls within the effect
|
|
423
|
+
* inherit `spaceId` as a default {@link Operation.InvokeOptions} so that
|
|
424
|
+
* spawned operation processes have a space context (and therefore can resolve
|
|
425
|
+
* space-scoped services like `Database.Service`) without each call site having
|
|
426
|
+
* to thread the id through manually.
|
|
427
|
+
*/
|
|
428
|
+
var useSpaceCallback = (spaceId, tags, fn, deps) => {
|
|
429
|
+
const runtime = useProcessManagerRuntime();
|
|
430
|
+
return useCallback(() => {
|
|
431
|
+
if (spaceId === void 0) throw new TypeError("Space not provided to useSpaceCallback");
|
|
432
|
+
const layer = Layer.merge(ServiceResolver.provide({ space: spaceId }, ...tags), Operation.withInvocationOptions({ spaceId }));
|
|
433
|
+
return runtime.runPromise(fn().pipe(Effect.provide(layer)));
|
|
434
|
+
}, [
|
|
435
|
+
runtime,
|
|
436
|
+
spaceId,
|
|
437
|
+
...deps ?? []
|
|
438
|
+
]);
|
|
439
|
+
};
|
|
440
|
+
/**
|
|
441
|
+
* Suspensefully resolve a single space-scoped service via the
|
|
442
|
+
* {@link Capabilities.ProcessManagerRuntime}'s service resolver.
|
|
443
|
+
*/
|
|
444
|
+
var useSpaceService = (tag, spaceId) => {
|
|
445
|
+
const runtime = useProcessManagerRuntime();
|
|
446
|
+
const promise = useMemo(() => {
|
|
447
|
+
if (spaceId === void 0) return;
|
|
448
|
+
const layer = ServiceResolver.provide({ space: spaceId }, tag);
|
|
449
|
+
const effect = Effect.flatMap(tag, (service) => Effect.succeed(service)).pipe(Effect.provide(layer));
|
|
450
|
+
return runtime.runPromiseExit(effect);
|
|
451
|
+
}, [
|
|
452
|
+
runtime,
|
|
453
|
+
spaceId,
|
|
454
|
+
tag
|
|
455
|
+
]);
|
|
456
|
+
if (!promise) return;
|
|
457
|
+
return EffectEx.unwrapExit(use(promise));
|
|
458
|
+
};
|
|
459
|
+
//#endregion
|
|
460
|
+
//#region src/ui/hooks/useSettingsState.ts
|
|
461
|
+
/**
|
|
462
|
+
* Hook to read and update a settings atom.
|
|
463
|
+
* Returns the current value and an update function.
|
|
464
|
+
*/
|
|
465
|
+
var useSettingsState = (atom) => {
|
|
466
|
+
const registry = useContext(RegistryContext);
|
|
467
|
+
return {
|
|
468
|
+
settings: useAtomValue(atom),
|
|
469
|
+
updateSettings: useCallback((fn) => {
|
|
470
|
+
registry.set(atom, fn(registry.get(atom)));
|
|
471
|
+
}, [registry, atom])
|
|
472
|
+
};
|
|
473
|
+
};
|
|
474
|
+
//#endregion
|
|
475
|
+
//#region src/ui/hooks/useSurface.ts
|
|
476
|
+
var useSurface = () => {
|
|
477
|
+
return useContext(Surface.Context) ?? raise(/* @__PURE__ */ new Error("Missing SurfaceContext"));
|
|
478
|
+
};
|
|
479
|
+
//#endregion
|
|
480
|
+
//#region src/ui/components/App/loader.ts
|
|
481
|
+
var bootLoader = typeof window !== "undefined" ? window.__bootLoader : void 0;
|
|
482
|
+
//#endregion
|
|
483
|
+
//#region src/ui/components/App/App.tsx
|
|
484
|
+
var FIRST_INTERACTIVE_MARK = "app-framework:first-interactive";
|
|
485
|
+
var App = ({ ready, error, debounce, progress }) => {
|
|
486
|
+
const reactContexts = useCapabilities(ReactContext);
|
|
487
|
+
const reactRoots = useCapabilities(ReactRoot);
|
|
488
|
+
const stage = useLoading(ready, debounce);
|
|
489
|
+
const placeholderDismissed = stage >= LoadingState.Done;
|
|
490
|
+
useEffect(() => {
|
|
491
|
+
if (stage >= LoadingState.FadeOut) return;
|
|
492
|
+
const fraction = progress?.progress ?? 0;
|
|
493
|
+
bootLoader?.progress(.5 + fraction * .5);
|
|
494
|
+
if (progress?.humanizedName) bootLoader?.status({
|
|
495
|
+
event: progress.event,
|
|
496
|
+
module: progress.module,
|
|
497
|
+
humanized: `Activating ${progress.humanizedName}`
|
|
498
|
+
});
|
|
499
|
+
}, [
|
|
500
|
+
stage,
|
|
501
|
+
progress?.progress,
|
|
502
|
+
progress?.event,
|
|
503
|
+
progress?.module,
|
|
504
|
+
progress?.humanizedName
|
|
505
|
+
]);
|
|
506
|
+
useLayoutEffect(() => {
|
|
507
|
+
if (stage >= LoadingState.FadeOut) bootLoader?.ready();
|
|
508
|
+
}, [stage]);
|
|
509
|
+
useEffect(() => {
|
|
510
|
+
if (!placeholderDismissed) return;
|
|
511
|
+
if (performance.getEntriesByName(FIRST_INTERACTIVE_MARK).length === 0) performance.mark(FIRST_INTERACTIVE_MARK);
|
|
512
|
+
bootLoader?.dismiss();
|
|
513
|
+
}, [placeholderDismissed]);
|
|
514
|
+
if (location.search === "?throw") throw new Error("Test error");
|
|
515
|
+
if (error) throw error;
|
|
516
|
+
if (!placeholderDismissed) return null;
|
|
517
|
+
return /* @__PURE__ */ jsx(composeContexts(reactContexts), { children: reactRoots.map(({ id, root: Component }) => /* @__PURE__ */ jsx(Component, {}, id)) });
|
|
518
|
+
};
|
|
519
|
+
var composeContexts = (contexts) => {
|
|
520
|
+
if (contexts.length === 0) return ({ children }) => /* @__PURE__ */ jsx(Fragment$1, { children });
|
|
521
|
+
return topologicalSort(contexts).map(({ context }) => context).reduce((Acc, Next) => ({ children }) => /* @__PURE__ */ jsx(Acc, { children: /* @__PURE__ */ jsx(Next, { children }) }));
|
|
522
|
+
};
|
|
523
|
+
//#endregion
|
|
524
|
+
//#region src/ui/components/HomeSection/HomeSection.tsx
|
|
525
|
+
/**
|
|
526
|
+
* Shared container for a Home content section: a centered, max-width column. Home surface
|
|
527
|
+
* contributors (welcome, recent, dashboard, suggestions) render inside one so they share a
|
|
528
|
+
* consistent width and rhythm regardless of which plugin owns them.
|
|
529
|
+
*/
|
|
530
|
+
var HomeSectionRoot = forwardRef(({ classNames, children }, forwardedRef) => /* @__PURE__ */ jsx("div", {
|
|
531
|
+
ref: forwardedRef,
|
|
532
|
+
className: mx("flex flex-col w-full mx-auto max-w-[40rem]", classNames),
|
|
533
|
+
children
|
|
534
|
+
}));
|
|
535
|
+
HomeSectionRoot.displayName = "HomeSection.Root";
|
|
536
|
+
/**
|
|
537
|
+
* Header row for a Home section: a muted title, an optional trailing actions slot (`children`),
|
|
538
|
+
* and an optional close affordance. `children` render before the close button so section-specific
|
|
539
|
+
* controls (e.g. a range selector) sit inline with it.
|
|
540
|
+
*/
|
|
541
|
+
var HomeSectionHeader = forwardRef(({ title, onClose, classNames, children }, forwardedRef) => /* @__PURE__ */ jsxs("div", {
|
|
542
|
+
ref: forwardedRef,
|
|
543
|
+
className: mx("flex items-center gap-2", classNames),
|
|
544
|
+
children: [
|
|
545
|
+
title && /* @__PURE__ */ jsx("h2", {
|
|
546
|
+
className: "grow truncate text-sm font-medium text-description",
|
|
547
|
+
children: title
|
|
548
|
+
}),
|
|
549
|
+
!title && /* @__PURE__ */ jsx("span", { className: "grow" }),
|
|
550
|
+
children,
|
|
551
|
+
onClose && /* @__PURE__ */ jsx(SystemIconButton.Close, {
|
|
552
|
+
variant: "ghost",
|
|
553
|
+
iconOnly: true,
|
|
554
|
+
onClick: onClose
|
|
555
|
+
})
|
|
556
|
+
]
|
|
557
|
+
}));
|
|
558
|
+
HomeSectionHeader.displayName = "HomeSection.Header";
|
|
559
|
+
var HomeSection = {
|
|
560
|
+
Root: HomeSectionRoot,
|
|
561
|
+
Header: HomeSectionHeader
|
|
562
|
+
};
|
|
563
|
+
//#endregion
|
|
564
|
+
//#region src/ui/components/NamePopover/NamePopover.tsx
|
|
565
|
+
/**
|
|
566
|
+
* Name-entry popover anchored to its trigger (mirrors the object rename popover UX).
|
|
567
|
+
* Enter or the submit button commits — an empty name is allowed; Escape or dismissal cancels.
|
|
568
|
+
*/
|
|
569
|
+
var NamePopover = ({ children, open, placeholder, submitLabel, onSubmit, onCancel }) => {
|
|
570
|
+
const [value, setValue] = useState("");
|
|
571
|
+
const submit = () => {
|
|
572
|
+
onSubmit(value);
|
|
573
|
+
setValue("");
|
|
574
|
+
};
|
|
575
|
+
const cancel = () => {
|
|
576
|
+
onCancel();
|
|
577
|
+
setValue("");
|
|
578
|
+
};
|
|
579
|
+
return /* @__PURE__ */ jsxs(Popover.Root, {
|
|
580
|
+
open,
|
|
581
|
+
onOpenChange: (next) => !next && cancel(),
|
|
582
|
+
children: [/* @__PURE__ */ jsx(Popover.Trigger, {
|
|
583
|
+
asChild: true,
|
|
584
|
+
children
|
|
585
|
+
}), /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsxs(Popover.Content, { children: [/* @__PURE__ */ jsxs("div", {
|
|
586
|
+
className: "flex items-center gap-1 p-2",
|
|
587
|
+
children: [/* @__PURE__ */ jsxs(Input.Root, { children: [/* @__PURE__ */ jsx(Input.Label, {
|
|
588
|
+
srOnly: true,
|
|
589
|
+
children: placeholder
|
|
590
|
+
}), /* @__PURE__ */ jsx(Input.TextInput, {
|
|
591
|
+
autoFocus: true,
|
|
592
|
+
placeholder,
|
|
593
|
+
value,
|
|
594
|
+
onChange: (event) => setValue(event.target.value),
|
|
595
|
+
onKeyDown: (event) => {
|
|
596
|
+
if (event.key === "Enter") submit();
|
|
597
|
+
else if (event.key === "Escape") {
|
|
598
|
+
event.preventDefault();
|
|
599
|
+
event.stopPropagation();
|
|
600
|
+
cancel();
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
})] }), /* @__PURE__ */ jsx(Button, {
|
|
604
|
+
variant: "primary",
|
|
605
|
+
onClick: submit,
|
|
606
|
+
children: submitLabel
|
|
607
|
+
})]
|
|
608
|
+
}), /* @__PURE__ */ jsx(Popover.Arrow, {})] }) })]
|
|
609
|
+
});
|
|
610
|
+
};
|
|
611
|
+
NamePopover.displayName = "NamePopover";
|
|
612
|
+
//#endregion
|
|
613
|
+
//#region src/ui/components/Surface/index.ts
|
|
614
|
+
var Surface;
|
|
615
|
+
(function(_Surface) {
|
|
616
|
+
_Surface.create = create;
|
|
617
|
+
_Surface.createWeb = createWeb;
|
|
618
|
+
_Surface.Context = SurfaceContext;
|
|
619
|
+
_Surface.Surface = SurfaceComponent;
|
|
620
|
+
_Surface.useIsAvailable = useIsSurfaceAvailable;
|
|
621
|
+
_Surface.makeFilter = makeFilter;
|
|
622
|
+
_Surface.isFilter = isFilter;
|
|
623
|
+
_Surface.isDebugEnabled = isSurfaceDebugEnabled;
|
|
624
|
+
_Surface.setDebug = setSurfaceDebug;
|
|
625
|
+
_Surface.ProfilerProvider = SurfaceProfilerProvider;
|
|
626
|
+
_Surface.useProfilerCallback = useSurfaceProfilerCallback;
|
|
627
|
+
_Surface.useProfilerEntries = useSurfaceProfilerEntries;
|
|
628
|
+
_Surface.useProfilerStats = useSurfaceProfilerStats;
|
|
629
|
+
_Surface.useProfilerClear = useSurfaceProfilerClear;
|
|
630
|
+
_Surface.useMetrics = useSurfaceMetrics;
|
|
631
|
+
_Surface.clearMetrics = () => surfaceMetrics.clear();
|
|
632
|
+
})(Surface || (Surface = {}));
|
|
633
|
+
//#endregion
|
|
634
|
+
export { App, HomeSection, LoadingState, NamePopover, PluginManagerProvider, Surface, SurfaceManager, SurfaceManagerProvider, bootLoader, useApp, useAtomCapability, useAtomCapabilityState, useCapabilities, useCapability, useLoading, useOperationInvoker, useOptionalAtomCapabilityState, useOptionalCapabilities, useOptionalCapability, useOptionalPluginManager, usePluginManager, useProcessManagerRuntime, useSettingsState, useSpaceCallback, useSpaceService, useSurface, useSurfaceManager };
|
|
635
|
+
|
|
636
|
+
//# sourceMappingURL=ui.mjs.map
|