@dxos/app-framework 0.8.4-main.d05539e30a → 0.8.4-main.d9fc60f731
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/dist/lib/browser/{capability-K5XIVCQU.mjs → capability-JCUNWZ66.mjs} +7 -7
- package/dist/lib/browser/{chunk-5AHASNDW.mjs → chunk-2ZIYRDAF.mjs} +1 -1
- package/dist/lib/browser/{chunk-5AHASNDW.mjs.map → chunk-2ZIYRDAF.mjs.map} +1 -1
- package/dist/lib/browser/{chunk-QLML5QFJ.mjs → chunk-7MBI66M7.mjs} +12 -6
- package/dist/lib/browser/chunk-7MBI66M7.mjs.map +7 -0
- package/dist/lib/browser/{chunk-VJ5PFAWC.mjs → chunk-BMLCIFZW.mjs} +37 -16
- package/dist/lib/browser/chunk-BMLCIFZW.mjs.map +7 -0
- package/dist/lib/browser/{chunk-SLX73WRZ.mjs → chunk-DC3WRPBV.mjs} +14 -5
- package/dist/lib/browser/chunk-DC3WRPBV.mjs.map +7 -0
- package/dist/lib/browser/{chunk-BRK6GYNB.mjs → chunk-E5DTDNDY.mjs} +20 -19
- package/dist/lib/browser/chunk-E5DTDNDY.mjs.map +7 -0
- package/dist/lib/browser/{chunk-KLHQNYJ2.mjs → chunk-KZUDO43J.mjs} +2 -2
- package/dist/lib/browser/chunk-Q2GLJTVV.mjs +12 -0
- package/dist/lib/browser/chunk-Q2GLJTVV.mjs.map +7 -0
- package/dist/lib/browser/{chunk-UVTGHZQF.mjs → chunk-VBG5F5UF.mjs} +51 -88
- package/dist/lib/browser/chunk-VBG5F5UF.mjs.map +7 -0
- package/dist/lib/browser/cli/index.mjs +5 -5
- package/dist/lib/browser/common/activation-events.mjs +3 -3
- package/dist/lib/browser/common/capabilities.mjs +4 -4
- package/dist/lib/browser/core/plugin-manager.mjs +2 -2
- package/dist/lib/browser/core/plugin.mjs +3 -1
- package/dist/lib/browser/core/url-loader.mjs +2 -2
- package/dist/lib/browser/index.mjs +13 -14
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{process-manager-capability-JIWLN7SU.mjs → process-manager-capability-4FUA4TRP.mjs} +6 -6
- package/dist/lib/browser/testing/index.mjs +11 -10
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/browser/testing/react.mjs +6 -6
- package/dist/lib/browser/ui/index.mjs +7 -9
- package/dist/lib/node-esm/{capability-RLKFFLTB.mjs → capability-7TCQK7ZP.mjs} +7 -7
- package/dist/lib/node-esm/{chunk-SFYCO3PT.mjs → chunk-4BX2AE47.mjs} +37 -16
- package/dist/lib/node-esm/chunk-4BX2AE47.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-FPW45EZH.mjs +14 -0
- package/dist/lib/node-esm/chunk-FPW45EZH.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-LJNUFNDO.mjs → chunk-GEWHMHM7.mjs} +12 -6
- package/dist/lib/node-esm/chunk-GEWHMHM7.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-BYHYYJZH.mjs → chunk-KSH4OVMY.mjs} +20 -19
- package/dist/lib/node-esm/chunk-KSH4OVMY.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-PW2VYGOS.mjs → chunk-QBUGLR4H.mjs} +1 -1
- package/dist/lib/node-esm/{chunk-PW2VYGOS.mjs.map → chunk-QBUGLR4H.mjs.map} +1 -1
- package/dist/lib/node-esm/{chunk-42UNAKYO.mjs → chunk-XGBUKRCK.mjs} +2 -2
- package/dist/lib/node-esm/{chunk-6S45OMUP.mjs → chunk-XIGPWXCQ.mjs} +14 -5
- package/dist/lib/node-esm/chunk-XIGPWXCQ.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-JNT72ZCN.mjs → chunk-Y7JKXNDU.mjs} +51 -88
- package/dist/lib/node-esm/chunk-Y7JKXNDU.mjs.map +7 -0
- package/dist/lib/node-esm/cli/index.mjs +5 -5
- package/dist/lib/node-esm/common/activation-events.mjs +3 -3
- package/dist/lib/node-esm/common/capabilities.mjs +4 -4
- package/dist/lib/node-esm/core/plugin-manager.mjs +2 -2
- package/dist/lib/node-esm/core/plugin.mjs +3 -1
- package/dist/lib/node-esm/core/url-loader.mjs +2 -2
- package/dist/lib/node-esm/index.mjs +13 -14
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{process-manager-capability-PHKLO2BL.mjs → process-manager-capability-F23D62RN.mjs} +6 -6
- package/dist/lib/node-esm/testing/index.mjs +11 -10
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/testing/react.mjs +6 -6
- package/dist/lib/node-esm/ui/index.mjs +7 -9
- package/dist/plugin/node-esm/index.mjs +155 -77
- package/dist/plugin/node-esm/index.mjs.map +4 -4
- package/dist/plugin/node-esm/meta.json +1 -1
- package/dist/types/src/common/capabilities.d.ts +1 -1
- package/dist/types/src/common/index.d.ts +0 -1
- package/dist/types/src/common/index.d.ts.map +1 -1
- package/dist/types/src/common/translations.d.ts +1 -1
- package/dist/types/src/core/capability-manager.d.ts +4 -0
- package/dist/types/src/core/capability-manager.d.ts.map +1 -1
- package/dist/types/src/core/plugin-manager.d.ts.map +1 -1
- package/dist/types/src/core/plugin.d.ts +33 -6
- package/dist/types/src/core/plugin.d.ts.map +1 -1
- package/dist/types/src/plugin-process-manager/history/history-tracker.d.ts +15 -1
- package/dist/types/src/plugin-process-manager/history/history-tracker.d.ts.map +1 -1
- package/dist/types/src/plugin-process-manager/history/undo-mapping.d.ts +1 -1
- package/dist/types/src/plugin-process-manager/history/undo-mapping.d.ts.map +1 -1
- package/dist/types/src/plugin-process-manager/meta.d.ts +1 -1
- package/dist/types/src/plugin-process-manager/meta.d.ts.map +1 -1
- package/dist/types/src/plugin-process-manager/testing.d.ts.map +1 -1
- package/dist/types/src/testing/withPluginManager.d.ts.map +1 -1
- package/dist/types/src/ui/components/App/App.d.ts +34 -2
- package/dist/types/src/ui/components/App/App.d.ts.map +1 -1
- package/dist/types/src/ui/components/App/App.stories.d.ts.map +1 -1
- package/dist/types/src/ui/components/PluginManager/PluginManagerContext.stories.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/types.d.ts.map +1 -1
- package/dist/types/src/ui/components/index.d.ts +0 -1
- package/dist/types/src/ui/components/index.d.ts.map +1 -1
- package/dist/types/src/ui/hooks/useApp.d.ts +1 -7
- package/dist/types/src/ui/hooks/useApp.d.ts.map +1 -1
- package/dist/types/src/ui/hooks/useCapabilities.d.ts.map +1 -1
- package/dist/types/src/ui/hooks/useProcessManagerRuntime.d.ts +6 -0
- package/dist/types/src/ui/hooks/useProcessManagerRuntime.d.ts.map +1 -1
- package/dist/types/src/vite-plugin/boot-loader/loader.d.ts +26 -23
- package/dist/types/src/vite-plugin/boot-loader/loader.d.ts.map +1 -1
- package/dist/types/src/vite-plugin/manifest.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +40 -35
- package/src/common/capabilities.ts +1 -1
- package/src/common/index.ts +0 -1
- package/src/common/translations.ts +1 -1
- package/src/core/capability-manager.test.ts +3 -0
- package/src/core/capability-manager.ts +22 -1
- package/src/core/plugin-manager.test.ts +51 -21
- package/src/core/plugin-manager.ts +10 -5
- package/src/core/plugin.ts +44 -8
- package/src/core/url-loader.test.ts +2 -1
- package/src/plugin-process-manager/history/history-tracker.test.ts +39 -60
- package/src/plugin-process-manager/history/history-tracker.ts +32 -16
- package/src/plugin-process-manager/history/undo-mapping.ts +1 -1
- package/src/plugin-process-manager/history/undo-registry.test.ts +3 -1
- package/src/plugin-process-manager/meta.ts +6 -4
- package/src/plugin-process-manager/testing.ts +6 -5
- package/src/testing/react.test.tsx +3 -1
- package/src/testing/withPluginManager.tsx +4 -3
- package/src/ui/components/App/App.stories.tsx +9 -11
- package/src/ui/components/App/App.tsx +80 -17
- package/src/ui/components/PluginManager/PluginManagerContext.stories.tsx +9 -14
- package/src/ui/components/Surface/SurfaceComponent.stories.tsx +1 -1
- package/src/ui/components/Surface/SurfaceComponent.tsx +1 -1
- package/src/ui/components/Surface/types.test.ts +2 -2
- package/src/ui/components/Surface/types.ts +21 -0
- package/src/ui/components/index.ts +0 -1
- package/src/ui/hooks/useApp.test.tsx +3 -1
- package/src/ui/hooks/useApp.tsx +4 -18
- package/src/ui/hooks/useCapabilities.ts +1 -0
- package/src/ui/hooks/useProcessManagerRuntime.ts +12 -2
- package/src/vite-plugin/boot-loader/BootLoader.solid-stories.tsx +198 -0
- package/src/vite-plugin/boot-loader/loader-app/Loader.tsx +166 -0
- package/src/vite-plugin/boot-loader/loader-app/boot-loader.css +311 -0
- package/src/vite-plugin/boot-loader/loader-app/bridge.ts +25 -0
- package/src/vite-plugin/boot-loader/loader-app/entry.tsx +21 -0
- package/src/vite-plugin/boot-loader/loader-app/mount.tsx +70 -0
- package/src/vite-plugin/boot-loader/loader-app/store.test.ts +137 -0
- package/src/vite-plugin/boot-loader/loader-app/store.ts +149 -0
- package/src/vite-plugin/boot-loader/loader-app/tsconfig.json +11 -0
- package/src/vite-plugin/boot-loader/loader-app/types.ts +78 -0
- package/src/vite-plugin/boot-loader/loader.ts +133 -63
- package/src/vite-plugin/manifest.test.ts +19 -10
- package/src/vite-plugin/manifest.ts +9 -3
- package/tsconfig.json +6 -7
- package/dist/lib/browser/chunk-BRK6GYNB.mjs.map +0 -7
- package/dist/lib/browser/chunk-KFDF7KR3.mjs +0 -42
- package/dist/lib/browser/chunk-KFDF7KR3.mjs.map +0 -7
- package/dist/lib/browser/chunk-QLML5QFJ.mjs.map +0 -7
- package/dist/lib/browser/chunk-SLX73WRZ.mjs.map +0 -7
- package/dist/lib/browser/chunk-UVTGHZQF.mjs.map +0 -7
- package/dist/lib/browser/chunk-VJ5PFAWC.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-6S45OMUP.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-BYHYYJZH.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-JNT72ZCN.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-LJNUFNDO.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-OUEMWPIW.mjs +0 -43
- package/dist/lib/node-esm/chunk-OUEMWPIW.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-SFYCO3PT.mjs.map +0 -7
- package/dist/types/src/common/operations.d.ts +0 -19
- package/dist/types/src/common/operations.d.ts.map +0 -1
- package/dist/types/src/ui/components/Placeholder/Placeholder.d.ts +0 -64
- package/dist/types/src/ui/components/Placeholder/Placeholder.d.ts.map +0 -1
- package/dist/types/src/ui/components/Placeholder/Placeholder.stories.d.ts +0 -19
- package/dist/types/src/ui/components/Placeholder/Placeholder.stories.d.ts.map +0 -1
- package/dist/types/src/ui/components/Placeholder/index.d.ts +0 -2
- package/dist/types/src/ui/components/Placeholder/index.d.ts.map +0 -1
- package/dist/types/src/vite-plugin/boot-loader/BootLoader.stories.d.ts +0 -34
- package/dist/types/src/vite-plugin/boot-loader/BootLoader.stories.d.ts.map +0 -1
- package/src/common/operations.ts +0 -35
- package/src/ui/components/Placeholder/Placeholder.stories.tsx +0 -77
- package/src/ui/components/Placeholder/Placeholder.tsx +0 -155
- package/src/ui/components/Placeholder/index.ts +0 -5
- package/src/vite-plugin/boot-loader/BootLoader.stories.tsx +0 -270
- package/src/vite-plugin/boot-loader/boot-loader.css +0 -320
- package/src/vite-plugin/boot-loader/boot-loader.js +0 -325
- /package/dist/lib/browser/{capability-K5XIVCQU.mjs.map → capability-JCUNWZ66.mjs.map} +0 -0
- /package/dist/lib/browser/{chunk-KLHQNYJ2.mjs.map → chunk-KZUDO43J.mjs.map} +0 -0
- /package/dist/lib/browser/{process-manager-capability-JIWLN7SU.mjs.map → process-manager-capability-4FUA4TRP.mjs.map} +0 -0
- /package/dist/lib/node-esm/{capability-RLKFFLTB.mjs.map → capability-7TCQK7ZP.mjs.map} +0 -0
- /package/dist/lib/node-esm/{chunk-42UNAKYO.mjs.map → chunk-XGBUKRCK.mjs.map} +0 -0
- /package/dist/lib/node-esm/{process-manager-capability-PHKLO2BL.mjs.map → process-manager-capability-F23D62RN.mjs.map} +0 -0
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
/**
|
|
4
|
-
* Storybook host that runs the **real** inline driver script (`boot-loader.js`)
|
|
5
|
-
* against the same DOM structure {@link bootLoaderPlugin} injects in production
|
|
6
|
-
* via `transformIndexHtml`. The component injects `<style>` + the loader DOM,
|
|
7
|
-
* evaluates the driver, and exposes `window.__bootLoader` for the stories to
|
|
8
|
-
* call — no React reimplementation of the state machine.
|
|
9
|
-
*
|
|
10
|
-
* On unmount, the host calls `__bootLoader.dismiss()` (which clears the creep
|
|
11
|
-
* timer and removes the `#boot-loader` node) and clears the global so a fresh
|
|
12
|
-
* mount re-runs the driver from scratch.
|
|
13
|
-
*/
|
|
14
|
-
type BootLoaderHostProps = {
|
|
15
|
-
initialStatus?: string;
|
|
16
|
-
markSvg?: string;
|
|
17
|
-
};
|
|
18
|
-
declare const BootLoaderHost: ({ initialStatus, markSvg }: BootLoaderHostProps) => React.JSX.Element;
|
|
19
|
-
declare const meta: Meta<typeof BootLoaderHost>;
|
|
20
|
-
export default meta;
|
|
21
|
-
type Story = StoryObj<typeof BootLoaderHost>;
|
|
22
|
-
export declare const Default: Story;
|
|
23
|
-
/**
|
|
24
|
-
* Renders the React `Placeholder` from `@dxos/app-framework/ui` on its own —
|
|
25
|
-
* useful for eyeballing the handoff target the boot loader dismisses to.
|
|
26
|
-
*/
|
|
27
|
-
export declare const PlaceholderHandoff: Story;
|
|
28
|
-
/**
|
|
29
|
-
* End-to-end handoff sim: the driver ticks 0 → 100% then the host calls
|
|
30
|
-
* `dismiss()` and the underlying `Placeholder` fades the mark in / out,
|
|
31
|
-
* mirroring the production sequence.
|
|
32
|
-
*/
|
|
33
|
-
export declare const Handoff: Story;
|
|
34
|
-
//# sourceMappingURL=BootLoader.stories.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BootLoader.stories.d.ts","sourceRoot":"","sources":["../../../../../src/vite-plugin/boot-loader/BootLoader.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,KAAsC,MAAM,OAAO,CAAC;AAU3D;;;;;;;;;;GAUG;AACH,KAAK,mBAAmB,GAAG;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAMF,QAAA,MAAM,cAAc,+BAA6C,mBAAmB,sBAmDnF,CAAC;AA0IF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,cAAc,CAYrC,CAAC;eAEa,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,cAAc,CAAC,CAAC;AAE7C,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,KAGhC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,OAAO,EAAE,KAWrB,CAAC"}
|
package/src/common/operations.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import * as Schema from 'effect/Schema';
|
|
6
|
-
|
|
7
|
-
import { Operation } from '@dxos/compute';
|
|
8
|
-
|
|
9
|
-
import { Capability } from '../core';
|
|
10
|
-
import { Label } from './translations';
|
|
11
|
-
|
|
12
|
-
const UNDO_NAMESPACE = 'org.dxos.app-framework.undo';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Operations related to undo/history functionality.
|
|
16
|
-
*/
|
|
17
|
-
export namespace UndoOperation {
|
|
18
|
-
/**
|
|
19
|
-
* Show an undo toast notification.
|
|
20
|
-
* Fired by HistoryTracker when an undoable operation is tracked.
|
|
21
|
-
*/
|
|
22
|
-
export const ShowUndo = Operation.make({
|
|
23
|
-
meta: {
|
|
24
|
-
key: `${UNDO_NAMESPACE}.operation.show-undo`,
|
|
25
|
-
name: 'Show Undo',
|
|
26
|
-
description: 'Show an undo toast notification.',
|
|
27
|
-
},
|
|
28
|
-
executionMode: 'sync',
|
|
29
|
-
services: [Capability.Service],
|
|
30
|
-
input: Schema.Struct({
|
|
31
|
-
message: Schema.optional(Label.annotations({ description: 'The message to display in the undo toast.' })),
|
|
32
|
-
}),
|
|
33
|
-
output: Schema.Void,
|
|
34
|
-
});
|
|
35
|
-
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
-
import React, { useEffect, useState } from 'react';
|
|
7
|
-
import { expect, within } from 'storybook/test';
|
|
8
|
-
|
|
9
|
-
import { Composer } from '@dxos/brand';
|
|
10
|
-
import { Input, Panel, Toolbar } from '@dxos/react-ui';
|
|
11
|
-
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
12
|
-
|
|
13
|
-
import { Placeholder } from './Placeholder';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* The story renders the brand-agnostic `Placeholder` from `@dxos/app-framework/ui`
|
|
17
|
-
* with the Composer brand icon as its `logo`, so the storybook mirrors what
|
|
18
|
-
* composer-app actually mounts in production. The render function form lets
|
|
19
|
-
* the SVG accept the placeholder's animation `className` directly.
|
|
20
|
-
*/
|
|
21
|
-
const meta = {
|
|
22
|
-
title: 'sdk/app-framework/components/Placeholder',
|
|
23
|
-
component: Placeholder,
|
|
24
|
-
render: () => {
|
|
25
|
-
const [stage, setStage] = useState(0);
|
|
26
|
-
const [auto, setAuto] = useState(false);
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
if (!auto) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const interval = setInterval(() => {
|
|
33
|
-
setStage((prev) => {
|
|
34
|
-
return prev >= 2 ? 0 : prev + 1;
|
|
35
|
-
});
|
|
36
|
-
}, 3_000);
|
|
37
|
-
|
|
38
|
-
return () => clearInterval(interval);
|
|
39
|
-
}, [auto]);
|
|
40
|
-
|
|
41
|
-
return (
|
|
42
|
-
<Panel.Root>
|
|
43
|
-
<Panel.Toolbar asChild>
|
|
44
|
-
<Toolbar.Root classNames='gap-2'>
|
|
45
|
-
<Input.Root>
|
|
46
|
-
<Input.Checkbox checked={auto} onCheckedChange={(checked) => setAuto(checked === true)} />
|
|
47
|
-
<Input.Label>Auto</Input.Label>
|
|
48
|
-
</Input.Root>
|
|
49
|
-
<Toolbar.Button onClick={() => setStage((prev) => (prev < 2 ? prev + 1 : 0))}>Next</Toolbar.Button>
|
|
50
|
-
<Toolbar.Text>{stage}</Toolbar.Text>
|
|
51
|
-
</Toolbar.Root>
|
|
52
|
-
</Panel.Toolbar>
|
|
53
|
-
<Panel.Content>
|
|
54
|
-
<Placeholder stage={stage} logo={(logoProps) => <Composer {...logoProps} />} />
|
|
55
|
-
</Panel.Content>
|
|
56
|
-
</Panel.Root>
|
|
57
|
-
);
|
|
58
|
-
},
|
|
59
|
-
decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
|
|
60
|
-
tags: ['test'],
|
|
61
|
-
} satisfies Meta<typeof Placeholder>;
|
|
62
|
-
|
|
63
|
-
export default meta;
|
|
64
|
-
|
|
65
|
-
type Story = StoryObj<typeof meta>;
|
|
66
|
-
|
|
67
|
-
export const Default: Story = {
|
|
68
|
-
args: {
|
|
69
|
-
stage: 0,
|
|
70
|
-
},
|
|
71
|
-
play: async ({ canvasElement }) => {
|
|
72
|
-
const canvas = within(canvasElement);
|
|
73
|
-
// Smoke test: the toolbar's `Next` button is rendered alongside the
|
|
74
|
-
// placeholder, so the story mounted without throwing.
|
|
75
|
-
await expect(canvas.getByRole('button', { name: 'Next' })).toBeInTheDocument();
|
|
76
|
-
},
|
|
77
|
-
};
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import React, { type ReactNode, useEffect, useLayoutEffect, useRef } from 'react';
|
|
6
|
-
|
|
7
|
-
import { ThemeProvider } from '@dxos/react-ui';
|
|
8
|
-
import { defaultTx, mx } from '@dxos/ui-theme';
|
|
9
|
-
|
|
10
|
-
import { type PlaceholderProps as PlaceholderSlotProps } from '../../hooks';
|
|
11
|
-
|
|
12
|
-
declare global {
|
|
13
|
-
interface Window {
|
|
14
|
-
/**
|
|
15
|
-
* Driver injected by `@dxos/app-framework/vite-plugin`'s `bootLoaderPlugin`.
|
|
16
|
-
* Declared here so the {@link Placeholder} can dismiss the native-DOM
|
|
17
|
-
* loader once the React placeholder commits without each host having to
|
|
18
|
-
* re-declare the type.
|
|
19
|
-
*/
|
|
20
|
-
__bootLoader?: {
|
|
21
|
-
status: (payload: {
|
|
22
|
-
event?: string;
|
|
23
|
-
module?: string;
|
|
24
|
-
humanized: string;
|
|
25
|
-
/**
|
|
26
|
-
* Optional `(index/total)` tick. When present, the loader replaces the
|
|
27
|
-
* current line in place ("Loading plugins (12/80)") instead of
|
|
28
|
-
* appending a new entry — keeps the visible log compact during long
|
|
29
|
-
* counted phases like plugin chunk-loading or module activation.
|
|
30
|
-
*/
|
|
31
|
-
range?: { index: number; total: number };
|
|
32
|
-
}) => void;
|
|
33
|
-
progress: (fraction?: number) => void;
|
|
34
|
-
dismiss: () => void;
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export type PlaceholderComponentProps = PlaceholderSlotProps & {
|
|
40
|
-
/**
|
|
41
|
-
* Brand mark rendered while the React tree settles. Pass either a static
|
|
42
|
-
* `ReactNode` (the framework wraps it in a sizing/animation div) or a
|
|
43
|
-
* render function that receives the precomputed `className` so the host
|
|
44
|
-
* can apply it directly to its logo (e.g. an SVG that accepts `className`
|
|
45
|
-
* — `composer-app` passes `(p) => <Composer {...p} />` from `@dxos/brand`).
|
|
46
|
-
*/
|
|
47
|
-
logo?: ReactNode | ((props: { className: string }) => ReactNode);
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* React placeholder. The native-DOM boot loader is the visible UI through
|
|
52
|
-
* stages 0 (Loading) and 1 (FadeIn): we render `null` until `stage >= 2`
|
|
53
|
-
* (FadeOut) and instead feed activation progress + status into the still-
|
|
54
|
-
* alive boot loader. At stage 2 the loader dismisses and the React mark
|
|
55
|
-
* appears for the cross-fade to the real shell:
|
|
56
|
-
*
|
|
57
|
-
* - composer-app fills `0 → 50%` from `getPlugins`'s per-chunk counter.
|
|
58
|
-
* - this component fills `50 → 100%` from `useApp`'s
|
|
59
|
-
* `startupProgress.progress` (`activated / total` modules) and pushes
|
|
60
|
-
* the per-module status text to the loader's status line.
|
|
61
|
-
* - at `stage >= 2` the boot loader is dismissed and the React mark
|
|
62
|
-
* starts its `FadeOut → Done` shrink-and-fade.
|
|
63
|
-
*
|
|
64
|
-
* Stage progression (driven by `useApp`):
|
|
65
|
-
* - `0` — Loading: native-DOM boot loader visible. Placeholder renders nothing.
|
|
66
|
-
* - `1` — FadeIn: same — boot loader still owns the screen.
|
|
67
|
-
* - `2` — FadeOut: boot loader dismissed, React mark visible at full opacity then shrinks.
|
|
68
|
-
*/
|
|
69
|
-
export const Placeholder = ({ stage = 1, progress, logo }: PlaceholderComponentProps) => {
|
|
70
|
-
// Used in tests to exercise the error boundary & reset dialog.
|
|
71
|
-
if (location.search === '?throw') {
|
|
72
|
-
throw new Error('Test error');
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Phase B: feed activation progress + status to the still-visible boot
|
|
76
|
-
// loader. Maps `[0, 1]` activation → `[0.5, 1]` of the ring; forwards
|
|
77
|
-
// the raw activation source (`event` / `module`) plus the pre-humanised
|
|
78
|
-
// label to `__bootLoader.status` so the loader gets to decide how to
|
|
79
|
-
// render and trace each transition (current default policy: "Activating
|
|
80
|
-
// <humanizedName>"; trace mode and timings track the structured fields).
|
|
81
|
-
// No-op once the loader has been dismissed (its `status()` early-returns
|
|
82
|
-
// when the boot DOM is gone). Skipping `stage >= 2` lets the dismissal
|
|
83
|
-
// run uncontended.
|
|
84
|
-
useEffect(() => {
|
|
85
|
-
if (stage >= 2) {
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
const fraction = progress?.progress ?? 0;
|
|
89
|
-
window.__bootLoader?.progress(0.5 + fraction * 0.5);
|
|
90
|
-
if (progress?.humanizedName) {
|
|
91
|
-
window.__bootLoader?.status({
|
|
92
|
-
event: progress.event,
|
|
93
|
-
module: progress.module,
|
|
94
|
-
humanized: `Activating ${progress.humanizedName}`,
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
}, [stage, progress?.progress, progress?.event, progress?.module, progress?.humanizedName]);
|
|
98
|
-
|
|
99
|
-
// Hand off from the native-DOM boot loader once the placeholder starts
|
|
100
|
-
// fading out — keeping the loader visible through `stage 0` and `stage 1`
|
|
101
|
-
// means the ring stays the visible source of truth for activation
|
|
102
|
-
// progress. `useLayoutEffect` runs before the next paint so the loader
|
|
103
|
-
// DOM is removed in the same frame the cross-fade begins.
|
|
104
|
-
useLayoutEffect(() => {
|
|
105
|
-
if (stage >= 2) {
|
|
106
|
-
window.__bootLoader?.dismiss();
|
|
107
|
-
}
|
|
108
|
-
}, [stage]);
|
|
109
|
-
|
|
110
|
-
// Backstop for the fast-load path where `useLoading` can skip straight
|
|
111
|
-
// from stage 0 to `Done` (ready=true at the first debounce tick) — the
|
|
112
|
-
// stage-driven effect above never sees `stage >= 2`, so dismiss on
|
|
113
|
-
// unmount instead. The `stageRef` guard is what keeps StrictMode's
|
|
114
|
-
// synthetic mount → cleanup → remount cycle from prematurely dismissing
|
|
115
|
-
// the loader: the synthetic cleanup runs while `stageRef.current === 0`,
|
|
116
|
-
// skips the dismiss, and the real unmount (later, at stage `Done`)
|
|
117
|
-
// performs it.
|
|
118
|
-
const stageRef = useRef(stage);
|
|
119
|
-
stageRef.current = stage;
|
|
120
|
-
useEffect(() => {
|
|
121
|
-
return () => {
|
|
122
|
-
if (stageRef.current >= 3 /* Done */) {
|
|
123
|
-
window.__bootLoader?.dismiss();
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
|
-
}, []);
|
|
127
|
-
|
|
128
|
-
// Defer rendering anything until the FadeOut stage. The boot loader owns
|
|
129
|
-
// the screen during stages 0 and 1, so any DOM we render here would just
|
|
130
|
-
// sit invisibly behind it — and rendering null avoids paint cost during
|
|
131
|
-
// the longest part of the loading sequence (plugin activation).
|
|
132
|
-
if (stage < 2) {
|
|
133
|
-
return null;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const logoClassName = mx(
|
|
137
|
-
'h-[300px] w-[300px] scale-600 transition-all duration-500 ease-in-out filter grayscale opacity-0',
|
|
138
|
-
stage >= 1 && 'scale-100 grayscale-0 opacity-70',
|
|
139
|
-
stage >= 2 && 'scale-50 opacity-0',
|
|
140
|
-
);
|
|
141
|
-
|
|
142
|
-
return (
|
|
143
|
-
<ThemeProvider tx={defaultTx}>
|
|
144
|
-
<div className='relative dx-container h-dvh flex flex-col'>
|
|
145
|
-
<div className='flex flex-col grow justify-center items-center'>
|
|
146
|
-
{typeof logo === 'function' ? (
|
|
147
|
-
logo({ className: logoClassName })
|
|
148
|
-
) : logo ? (
|
|
149
|
-
<div className={logoClassName}>{logo}</div>
|
|
150
|
-
) : null}
|
|
151
|
-
</div>
|
|
152
|
-
</div>
|
|
153
|
-
</ThemeProvider>
|
|
154
|
-
);
|
|
155
|
-
};
|
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2026 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
-
import React, { useEffect, useRef, useState } from 'react';
|
|
7
|
-
|
|
8
|
-
import { Composer } from '@dxos/brand';
|
|
9
|
-
import { Toolbar } from '@dxos/react-ui';
|
|
10
|
-
import { withTheme } from '@dxos/react-ui/testing';
|
|
11
|
-
|
|
12
|
-
import { Placeholder } from '../../ui';
|
|
13
|
-
import bootLoaderCss from './boot-loader.css?raw';
|
|
14
|
-
import bootLoaderScript from './boot-loader.js?raw';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Storybook host that runs the **real** inline driver script (`boot-loader.js`)
|
|
18
|
-
* against the same DOM structure {@link bootLoaderPlugin} injects in production
|
|
19
|
-
* via `transformIndexHtml`. The component injects `<style>` + the loader DOM,
|
|
20
|
-
* evaluates the driver, and exposes `window.__bootLoader` for the stories to
|
|
21
|
-
* call — no React reimplementation of the state machine.
|
|
22
|
-
*
|
|
23
|
-
* On unmount, the host calls `__bootLoader.dismiss()` (which clears the creep
|
|
24
|
-
* timer and removes the `#boot-loader` node) and clears the global so a fresh
|
|
25
|
-
* mount re-runs the driver from scratch.
|
|
26
|
-
*/
|
|
27
|
-
type BootLoaderHostProps = {
|
|
28
|
-
initialStatus?: string;
|
|
29
|
-
markSvg?: string;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
// `__bootLoader` is declared globally by `../../ui/components/Placeholder/Placeholder.tsx`
|
|
33
|
-
// so consumers don't have to redeclare it. The story imports `Placeholder` for the
|
|
34
|
-
// handoff scenarios, which pulls the declaration into scope.
|
|
35
|
-
|
|
36
|
-
const BootLoaderHost = ({ initialStatus = 'Loading…', markSvg }: BootLoaderHostProps) => {
|
|
37
|
-
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
38
|
-
|
|
39
|
-
useEffect(() => {
|
|
40
|
-
const container = containerRef.current;
|
|
41
|
-
if (!container) {
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Mirror the HTML structure produced by `bootLoaderPlugin.transformIndexHtml`.
|
|
46
|
-
const initialLine = initialStatus ? `<div class="boot-loader-status-line">${escapeHtml(initialStatus)}</div>` : '';
|
|
47
|
-
const markHtml = markSvg ? `<div id="boot-loader-mark">${markSvg}</div>` : '';
|
|
48
|
-
container.innerHTML = `
|
|
49
|
-
<div id="boot-loader" role="status" aria-live="polite" aria-label="Initializing">
|
|
50
|
-
<div id="boot-loader-disc">
|
|
51
|
-
<div id="boot-loader-bar"></div>
|
|
52
|
-
<div id="boot-loader-dot"></div>
|
|
53
|
-
${markHtml}
|
|
54
|
-
</div>
|
|
55
|
-
<div id="boot-loader-status">
|
|
56
|
-
<div id="boot-loader-status-fade"></div>
|
|
57
|
-
<div id="boot-loader-status-track">
|
|
58
|
-
${initialLine}
|
|
59
|
-
</div>
|
|
60
|
-
</div>
|
|
61
|
-
</div>
|
|
62
|
-
`;
|
|
63
|
-
|
|
64
|
-
// Evaluate the driver IIFE — it auto-promotes idle → state 1 (slow creep)
|
|
65
|
-
// and exposes `window.__bootLoader.{status, progress, dismiss}` globally.
|
|
66
|
-
const driverEl = document.createElement('script');
|
|
67
|
-
driverEl.textContent = bootLoaderScript;
|
|
68
|
-
container.appendChild(driverEl);
|
|
69
|
-
|
|
70
|
-
return () => {
|
|
71
|
-
try {
|
|
72
|
-
window.__bootLoader?.dismiss();
|
|
73
|
-
} catch {
|
|
74
|
-
// Driver removes its own DOM — swallow errors from idempotent retries.
|
|
75
|
-
}
|
|
76
|
-
delete window.__bootLoader;
|
|
77
|
-
container.innerHTML = '';
|
|
78
|
-
};
|
|
79
|
-
}, [initialStatus, markSvg]);
|
|
80
|
-
|
|
81
|
-
return (
|
|
82
|
-
<>
|
|
83
|
-
<style>{bootLoaderCss}</style>
|
|
84
|
-
<div ref={containerRef} />
|
|
85
|
-
</>
|
|
86
|
-
);
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
const escapeHtml = (text: string): string =>
|
|
90
|
-
text.replace(/[&<>"']/g, (ch) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[ch]!);
|
|
91
|
-
|
|
92
|
-
// Inlined snapshot of `packages/ui/brand/assets/icons/composer-icon.svg` —
|
|
93
|
-
// keeps storybook self-contained (production pipes the same file in from
|
|
94
|
-
// vite.config.ts via the plugin's `markSvg` option) while previewing the
|
|
95
|
-
// real brand palette the loader will render in production.
|
|
96
|
-
const PLACEHOLDER_MARK = `
|
|
97
|
-
<svg viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
|
98
|
-
<g transform="matrix(0.969697,0,0,1,-570.182,0)">
|
|
99
|
-
<rect x="588" y="0" width="264" height="256" style="fill:none;"/>
|
|
100
|
-
<g transform="matrix(0.917198,0,0,1,-223.93,-876)">
|
|
101
|
-
<path d="M1065.83,1064L1029.14,1064C991.913,1064 961.684,1037.12 961.684,1004C961.684,971.197 991.282,944.542 1028.02,944.008L1028.02,944L1047.85,944L1039.21,968L1029.14,968C1006.79,968 988.669,984.118 988.669,1004C988.669,1023.87 1006.81,1040 1029.14,1040C1029.38,1040 1029.62,1040 1029.85,1040L1029.85,1040L1074.47,1040L1065.83,1064ZM1083.11,1040L1083.11,1040L1083.11,1064L1083.11,1064L1083.11,1040Z" style="fill:rgb(1,122,183);"/>
|
|
102
|
-
</g>
|
|
103
|
-
<path d="M761.579,164L720,164C699.51,164 682.875,147.869 682.875,128C682.875,108.452 698.942,92.543 718.969,92.014L718.969,92L729.238,92L721.317,116L720,116C713.165,116 707.625,121.373 707.625,128C707.625,134.623 713.17,140 720,140C720.072,140 720.144,139.999 720.216,139.998L720.216,140L769.5,140L761.579,164Z" style="fill:rgb(6,197,253);"/>
|
|
104
|
-
<path d="M745.738,212L720.025,212L720,212C672.202,212 633.389,174.377 633.375,128.024C633.361,81.958 671.591,44.542 718.969,44.006L718.969,44L719.975,44L745.079,44L737.159,68L719.982,68C685.809,68.01 658.115,94.88 658.125,128.017C658.135,161.126 685.858,188 720,188L720.018,188C720.378,188 720.738,187.997 721.098,187.991L721.098,188L753.659,188L745.738,212Z" style="fill:rgb(10,75,105);"/>
|
|
105
|
-
<g transform="matrix(1.03125,0,0,1,588,0)">
|
|
106
|
-
<path d="M128,236C68.393,236 20,187.607 20,128C20,68.353 68.353,20 128,20L160,20L152.319,44L128,44C81.608,44 44,81.608 44,128C44,174.361 81.639,212 128,212C127.756,212.004 127.878,212.004 128,212.003C128.122,212.002 128.244,212 128,212L152.958,212L145.277,236L128,236ZM128,236C128.628,236 127.372,236.011 128,236Z" style="fill:rgb(5,40,61);"/>
|
|
107
|
-
</g>
|
|
108
|
-
</g>
|
|
109
|
-
</svg>
|
|
110
|
-
`;
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Approximate plugin count used by the simulation. Hardcoded here to keep the
|
|
114
|
-
* storybook self-contained — the production count comes from
|
|
115
|
-
* `composer-app/src/plugin-defs.tsx`'s dynamic-import list.
|
|
116
|
-
*/
|
|
117
|
-
const STORY_PLUGIN_COUNT = 80;
|
|
118
|
-
|
|
119
|
-
/** Tick interval for the determinate-progress simulation, in ms. */
|
|
120
|
-
const STORY_TICK_MS = 50;
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Story controls — emits real `__bootLoader.status(...)` and `progress(...)`
|
|
124
|
-
* calls into the running driver script, which then drives the visible DOM.
|
|
125
|
-
* No React state shadow of the loader's progress; the driver is the source
|
|
126
|
-
* of truth.
|
|
127
|
-
*/
|
|
128
|
-
type SimRunningState = 'idle' | 'creep' | 'progress' | 'done';
|
|
129
|
-
|
|
130
|
-
const useBootLoaderDriver = ({ withHandoff = false }: { withHandoff?: boolean } = {}) => {
|
|
131
|
-
const [running, setRunning] = useState<SimRunningState>('creep');
|
|
132
|
-
const [stage, setStage] = useState(0);
|
|
133
|
-
|
|
134
|
-
// `creep` state — driver auto-creeps; the story emits a sequence of
|
|
135
|
-
// status messages so the appended-log behaviour is observable.
|
|
136
|
-
useEffect(() => {
|
|
137
|
-
if (running !== 'creep') {
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
const phases = ['Loading framework…', 'Reading configuration…', 'Starting services…'];
|
|
141
|
-
let index = 0;
|
|
142
|
-
const handle = setInterval(() => {
|
|
143
|
-
window.__bootLoader?.status({ humanized: phases[index] });
|
|
144
|
-
index += 1;
|
|
145
|
-
if (index >= phases.length) {
|
|
146
|
-
clearInterval(handle);
|
|
147
|
-
}
|
|
148
|
-
}, 600);
|
|
149
|
-
return () => clearInterval(handle);
|
|
150
|
-
}, [running]);
|
|
151
|
-
|
|
152
|
-
// `progress` state — random-walk through the plugin count, calling the
|
|
153
|
-
// real `__bootLoader.progress(...)` so the driver's no-regress + creep
|
|
154
|
-
// logic runs as it does in production.
|
|
155
|
-
useEffect(() => {
|
|
156
|
-
if (running !== 'progress') {
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
let loaded = 0;
|
|
160
|
-
const handle = setInterval(() => {
|
|
161
|
-
loaded += Math.abs(Math.random()) * 1.5;
|
|
162
|
-
const fraction = Math.min(1, loaded / STORY_PLUGIN_COUNT);
|
|
163
|
-
window.__bootLoader?.progress(fraction);
|
|
164
|
-
// Range-bearing payload — replaces the current line in place
|
|
165
|
-
// instead of appending one entry per plugin tick.
|
|
166
|
-
window.__bootLoader?.status({
|
|
167
|
-
humanized: 'Loading plugins',
|
|
168
|
-
range: { index: Math.round(loaded), total: STORY_PLUGIN_COUNT },
|
|
169
|
-
});
|
|
170
|
-
if (loaded >= STORY_PLUGIN_COUNT) {
|
|
171
|
-
clearInterval(handle);
|
|
172
|
-
window.__bootLoader?.status({ humanized: 'Starting Composer…' });
|
|
173
|
-
setRunning('done');
|
|
174
|
-
}
|
|
175
|
-
}, STORY_TICK_MS);
|
|
176
|
-
return () => clearInterval(handle);
|
|
177
|
-
}, [running]);
|
|
178
|
-
|
|
179
|
-
// Handoff phase — fade the placeholder in/out once the driver hits 100%.
|
|
180
|
-
useEffect(() => {
|
|
181
|
-
if (!withHandoff || running !== 'done') {
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
const handles: ReturnType<typeof setTimeout>[] = [];
|
|
185
|
-
handles.push(setTimeout(() => setStage(1), 200));
|
|
186
|
-
handles.push(setTimeout(() => setStage(2), 2_000));
|
|
187
|
-
return () => handles.forEach(clearTimeout);
|
|
188
|
-
}, [running, withHandoff]);
|
|
189
|
-
|
|
190
|
-
const advance = () => {
|
|
191
|
-
if (running === 'creep') {
|
|
192
|
-
setRunning('progress');
|
|
193
|
-
} else {
|
|
194
|
-
setRunning('creep');
|
|
195
|
-
setStage(0);
|
|
196
|
-
}
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
return { running, stage, advance };
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
const SimToolbar = ({ running, advance }: { running: SimRunningState; advance: () => void }) => {
|
|
203
|
-
const button =
|
|
204
|
-
running === 'creep'
|
|
205
|
-
? { icon: 'ph--play--regular', label: 'Start progress' }
|
|
206
|
-
: { icon: 'ph--arrow-counter-clockwise--regular', label: 'Reset' };
|
|
207
|
-
return (
|
|
208
|
-
<Toolbar.Root classNames='relative z-20'>
|
|
209
|
-
<Toolbar.IconButton icon={button.icon} label={button.label} iconOnly onClick={advance} />
|
|
210
|
-
<Toolbar.Text>{running}</Toolbar.Text>
|
|
211
|
-
</Toolbar.Root>
|
|
212
|
-
);
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
const DefaultStory = () => {
|
|
216
|
-
const { running, advance } = useBootLoaderDriver();
|
|
217
|
-
return (
|
|
218
|
-
<>
|
|
219
|
-
<SimToolbar running={running} advance={advance} />
|
|
220
|
-
<BootLoaderHost markSvg={PLACEHOLDER_MARK} />
|
|
221
|
-
</>
|
|
222
|
-
);
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
const meta: Meta<typeof BootLoaderHost> = {
|
|
226
|
-
title: 'sdk/app-framework/vite-plugin/BootLoader',
|
|
227
|
-
component: BootLoaderHost,
|
|
228
|
-
render: DefaultStory,
|
|
229
|
-
decorators: [withTheme({})],
|
|
230
|
-
parameters: {
|
|
231
|
-
layout: 'fullscreen',
|
|
232
|
-
},
|
|
233
|
-
argTypes: {
|
|
234
|
-
initialStatus: { control: 'text' },
|
|
235
|
-
markSvg: { control: 'text' },
|
|
236
|
-
},
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
export default meta;
|
|
240
|
-
|
|
241
|
-
type Story = StoryObj<typeof BootLoaderHost>;
|
|
242
|
-
|
|
243
|
-
export const Default: Story = {};
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Renders the React `Placeholder` from `@dxos/app-framework/ui` on its own —
|
|
247
|
-
* useful for eyeballing the handoff target the boot loader dismisses to.
|
|
248
|
-
*/
|
|
249
|
-
export const PlaceholderHandoff: Story = {
|
|
250
|
-
name: 'Placeholder',
|
|
251
|
-
render: () => <Placeholder stage={1} logo={(logoProps) => <Composer {...logoProps} />} />,
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* End-to-end handoff sim: the driver ticks 0 → 100% then the host calls
|
|
256
|
-
* `dismiss()` and the underlying `Placeholder` fades the mark in / out,
|
|
257
|
-
* mirroring the production sequence.
|
|
258
|
-
*/
|
|
259
|
-
export const Handoff: Story = {
|
|
260
|
-
render: () => {
|
|
261
|
-
const { running, stage, advance } = useBootLoaderDriver({ withHandoff: true });
|
|
262
|
-
return (
|
|
263
|
-
<>
|
|
264
|
-
<SimToolbar running={running} advance={advance} />
|
|
265
|
-
<Placeholder stage={stage} logo={(logoProps) => <Composer {...logoProps} />} />
|
|
266
|
-
{stage < 1 && <BootLoaderHost markSvg={PLACEHOLDER_MARK} />}
|
|
267
|
-
</>
|
|
268
|
-
);
|
|
269
|
-
},
|
|
270
|
-
};
|