@graview/embed 0.1.37 → 0.1.39

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/README.md CHANGED
@@ -108,6 +108,32 @@ draws them first. Until a face's chunk arrives its box stands empty
108
108
  (`aria-busy`), and `handle.drawn()` resolves once the face asked for is on
109
109
  the page — after `mount`, and after every change of face.
110
110
 
111
+ A face on the page is not yet a place a person can read: its parts, the
112
+ fonts, a worker view's drawing and its pictures may still be on their way.
113
+ Once the place the reader is on has drawn and settled — every part drawn
114
+ on it arrived, the fonts and images loaded, each worker view drawn (or
115
+ stopped, what stands in its place drawn), each frame guest drawn (or
116
+ silent past its `limits.readyMs`, eight seconds by default) and nothing
117
+ moving for 200 ms —
118
+ the embed's root wears `data-graview-drawn`, its value the place's path,
119
+ and `onDrawn(place)` is told where it is as `where()` says it. A move to
120
+ another place takes the attribute off in the same commit, and the next
121
+ place puts it back as it settles. A place that never stops moving is said
122
+ drawn after ten seconds all the same. A host picturing a place headless
123
+ waits for the attribute rather than a timer:
124
+
125
+ ```ts
126
+ await page.waitForSelector("[data-graview-drawn]");
127
+ ```
128
+
129
+ A frame guest (`guestView({ url })`) has drawn once it has said it is
130
+ ready, been handed what it shows and asked for its height — or stayed
131
+ quiet for a moment after, if it never asks — and its frame says
132
+ `data-guest-view-drawn`; one that never says it is ready says
133
+ `data-guest-view-failed="silent"`. Until one or the other, the frame is
134
+ `aria-busy`, and so is its holder until the frame's host has drawn the
135
+ frame in it.
136
+
111
137
  A host that knows its face before it mounts starts that chunk at once,
112
138
  beside its own requests, and an embed mounted once it is here draws it in
113
139
  the first commit:
@@ -219,6 +245,51 @@ handle.unmount();
219
245
  handle = mount(root, { app, store, at });
220
246
  ```
221
247
 
248
+ ## A view proposed and not kept
249
+
250
+ A chat that proposes a worker view can try it headless and be told what it
251
+ drew in words; to see it at a phone's width in dark it had to keep it
252
+ first. `draftView` draws one for the seat at the keyboard without keeping
253
+ it: its manifest and its `source` (or `worker`, and anything else a
254
+ `WorkerViewDefinition` takes but `draft`):
255
+
256
+ ```ts
257
+ mount(root, { app, remote, routing: "address", draftView: { manifest, source, author: "Proposed by Claude" } });
258
+ ```
259
+
260
+ It is drawn where its manifest attaches — the home, a kind's list at the
261
+ place its title names (`/places/<title>`), each record's page — under one
262
+ line, "Draft — <title> · Not kept", in a group named "Draft: <title>"
263
+ (`[data-graview-draft-view="<name>"]`), as the seat's drawn panel is marked
264
+ on `/~draft`. A kept view of the same name is the one it stands in for: the
265
+ host's `views` may register it as ever, and it is drawn nowhere beside the
266
+ draft. A draft that is stopped says why in its place rather than standing
267
+ the kind's own face there. Nothing of it is kept: it is registered under no
268
+ name, so the place menu offers no Hide or Delete and `keptViews` is asked
269
+ nothing; the store is not written; the next page, handed no draft, has
270
+ none. The worker's host is fetched before the embed draws, and only when a
271
+ draft is handed. With `data-graview-drawn`, a host pictures the proposal
272
+ once it has drawn. `graview preview` and `graview shots` take one as
273
+ `--view <view.js> --manifest <manifest.json>`.
274
+
275
+ A host picturing several proposals in turn swaps them in place rather than
276
+ mounting again: `handle.setDraftView(draft)` draws another, and
277
+ `handle.setDraftView(null)` the app's own views again. The store, the place
278
+ and the seat stay; `data-graview-drawn` comes off in the call and comes
279
+ back, with `onDrawn` told again, once the new draft has drawn and settled:
280
+
281
+ ```ts
282
+ for (const proposal of proposals) {
283
+ handle.setDraftView(proposal);
284
+ await page.waitForSelector("[data-graview-drawn]");
285
+ // picture it
286
+ }
287
+ ```
288
+
289
+ Under a base path — the page the app, served at `/a/<app>` — a draft of a
290
+ kind's view is drawn at `/a/<app>/places/<title>`, and the attribute's
291
+ value is the place's path within the app (`/places/<title>`).
292
+
222
293
  ## What stands over what
223
294
 
224
295
  Every popover, menu and list of suggestions the embed draws — the profile,
@@ -376,6 +447,12 @@ that and does not bundle the scene, the Graview or the studio:
376
447
  import { mount } from "@graview/embed/pages";
377
448
  ```
378
449
 
450
+ It says when a page has drawn as the whole embed does — `onDrawn(place)`,
451
+ and `data-graview-drawn` (`DRAWN_ATTRIBUTE`) on its root — and takes a
452
+ `draftView`, swapped in place with `handle.setDraftView`, drawn and marked
453
+ as the whole embed draws one, the worker's host fetched only when a draft
454
+ is handed.
455
+
379
456
  Bundled for the browser without React, the pages face alone is about 500 KB
380
457
  minified (165 KB gzipped); the whole embed loads about 750 KB (190 KB) before a
381
458
  face is fetched, and every face about 1.28 MB (370 KB);
@@ -0,0 +1,29 @@
1
+ import type { WorkerViewDefinition } from "@graview/guest/host/views";
2
+ import type { DraftOver } from "./frame.js";
3
+ /** A view proposed and not kept (FR-187): a worker view's definition, its code as `source` — a plain script against the `graview` global — or `worker`. */
4
+ export type EmbedDraftView = Omit<WorkerViewDefinition, "worker" | "draft"> & ({
5
+ readonly source: string;
6
+ readonly worker?: undefined;
7
+ } | {
8
+ readonly worker: WorkerViewDefinition["worker"];
9
+ readonly source?: undefined;
10
+ });
11
+ export declare const fetchDraftHost: () => Promise<void>;
12
+ /** Whether a draft handed now must wait for the worker's host before the embed first draws. */
13
+ export declare const draftWaits: (draft: EmbedDraftView | null | undefined) => boolean;
14
+ /** Stands in for the embed while what it draws with arrives — the worker's host for a draft, the rules for a place handed back — then draws it. */
15
+ export declare function Settling({ onReady, fetch }: {
16
+ readonly onReady: () => void;
17
+ readonly fetch: () => Promise<void>;
18
+ }): null;
19
+ /**
20
+ * How the frame registers the draft over the app's views, kept while the
21
+ * same draft is handed, and which draft it is. A draft handed after the
22
+ * embed first drew, before the worker's host is here, is registered once
23
+ * the host arrives; the embed is not drawn again from nothing for it.
24
+ */
25
+ export declare function useDraft(draft: EmbedDraftView | null | undefined): {
26
+ readonly over: DraftOver | undefined;
27
+ readonly n: number;
28
+ };
29
+ //# sourceMappingURL=draft.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"draft.d.ts","sourceRoot":"","sources":["../src/draft.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAGtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAQ5C,2JAA2J;AAC3J,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,oBAAoB,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAA;CAAE,CAAC,CAAC;AAW5N,eAAO,MAAM,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAsB,CAAC;AAEtE,+FAA+F;AAC/F,eAAO,MAAM,UAAU,GAAI,OAAO,cAAc,GAAG,IAAI,GAAG,SAAS,KAAG,OAAoD,CAAC;AAE3H,mJAAmJ;AACnJ,wBAAgB,QAAQ,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,QAGjH;AAKD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;IAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAqB/H"}
package/dist/draft.js ADDED
@@ -0,0 +1,54 @@
1
+ import { retryingImport } from "@graview/core/retry";
2
+ import { partArriving } from "@graview/react/provider";
3
+ import { useEffect, useLayoutEffect, useMemo, useState } from "react";
4
+ /*
5
+ * THE WORKER'S HOST FOR A DRAFT, fetched only when one is handed: a page
6
+ * that is handed none never loads it for this. Counted while it is on its
7
+ * way (`partArriving`), so a place a draft is handed to after it first drew
8
+ * is not said drawn before the draft is in it (FR-188).
9
+ */
10
+ let draftHost;
11
+ const draftChunk = retryingImport(() => import("@graview/guest/host/views"));
12
+ const load = () => draftChunk().then((module) => void (draftHost = module), () => new Promise((resolve) => setTimeout(resolve, 2_000)).then(load));
13
+ export const fetchDraftHost = partArriving(load);
14
+ /** Whether a draft handed now must wait for the worker's host before the embed first draws. */
15
+ export const draftWaits = (draft) => Boolean(draft) && draftHost === undefined;
16
+ /** Stands in for the embed while what it draws with arrives — the worker's host for a draft, the rules for a place handed back — then draws it. */
17
+ export function Settling({ onReady, fetch }) {
18
+ useLayoutEffect(() => void fetch().then(onReady), [onReady, fetch]);
19
+ return null;
20
+ }
21
+ /** Each draft handed, counted: what the drawn signal is watched again for when a draft is swapped (`setDraftView`). */
22
+ let handed = 0;
23
+ /**
24
+ * How the frame registers the draft over the app's views, kept while the
25
+ * same draft is handed, and which draft it is. A draft handed after the
26
+ * embed first drew, before the worker's host is here, is registered once
27
+ * the host arrives; the embed is not drawn again from nothing for it.
28
+ */
29
+ export function useDraft(draft) {
30
+ const [host, setHost] = useState(() => draftHost);
31
+ useEffect(() => {
32
+ if (!draft || host)
33
+ return;
34
+ let gone = false;
35
+ void fetchDraftHost().then(() => {
36
+ if (!gone)
37
+ setHost(draftHost);
38
+ });
39
+ return () => {
40
+ gone = true;
41
+ };
42
+ }, [draft, host]);
43
+ const n = useMemo(() => (handed += 1), [draft]);
44
+ const over = useMemo(() => {
45
+ const views = host ?? draftHost;
46
+ if (!draft || !views)
47
+ return undefined;
48
+ const { source, worker, ...rest } = draft;
49
+ const definition = { ...rest, worker: worker ?? { source: source }, draft: true };
50
+ return { name: draft.manifest.name, home: draft.manifest.attach === "home", register: (registry) => views.registerWorkerView(registry, definition) };
51
+ }, [draft, host]);
52
+ return { over, n };
53
+ }
54
+ //# sourceMappingURL=draft.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"draft.js","sourceRoot":"","sources":["../src/draft.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { EmbedWhere } from "./where.js";
2
+ /** The attribute the embed's root wears while the place it is on has drawn and settled. */
3
+ export declare const DRAWN_ATTRIBUTE = "data-graview-drawn";
4
+ /**
5
+ * Watch a place settle: takes `data-graview-drawn` off the root at once,
6
+ * and puts it back — `path` its value — once the place has drawn and
7
+ * nothing has moved for a moment, then calls `settled`. The answer stops
8
+ * watching; a place left before it settled is never said drawn.
9
+ */
10
+ export declare function watchDrawn(root: HTMLElement, path: string, settled: () => void): () => void;
11
+ /**
12
+ * SAYS WHEN THE PLACE HAS DRAWN AND SETTLED, on the root and to the host:
13
+ * watched again from nothing each time `key` moves — another page, another
14
+ * stop on the scene, another face, another draft — so the attribute comes
15
+ * off in the commit that moved and goes back on once the new place
16
+ * settles. The whole embed and the pages alone say it alike.
17
+ */
18
+ export declare function useDrawnSignal(rootRef: {
19
+ readonly current: HTMLElement | null;
20
+ }, key: string, place: EmbedWhere, onDrawn: ((place: EmbedWhere) => void) | undefined): void;
21
+ //# sourceMappingURL=drawn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drawn.d.ts","sourceRoot":"","sources":["../src/drawn.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAgB7C,2FAA2F;AAC3F,eAAO,MAAM,eAAe,uBAAuB,CAAC;AAyCpD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAmD3F;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,CAiB1K"}
package/dist/drawn.js ADDED
@@ -0,0 +1,151 @@
1
+ import { partsArriving } from "@graview/react/provider";
2
+ import { useLayoutEffect, useRef } from "react";
3
+ /*
4
+ * THE PAGE SAYS WHEN A PLACE HAS DRAWN AND SETTLED (FR-188).
5
+ *
6
+ * A host picturing a place — Graview Cloud's describe_place, headless —
7
+ * waited on a guess: the opening frame gone, the network quiet, then 600
8
+ * ms. The embed knows better. Once the place it is on has drawn — the face
9
+ * here, every part drawn on it arrived (or said it did not), the fonts and
10
+ * images loaded, every worker view drawn (or failed, its plain face drawn
11
+ * in its place), every frame guest drawn (or silent past its time) — and nothing in it has moved for a moment, its root says
12
+ * `data-graview-drawn`, its value the place's path, and the host is told
13
+ * `onDrawn(place)`. A move to another place takes it off in the same
14
+ * commit, and the new place says it again once it settles.
15
+ */
16
+ /** The attribute the embed's root wears while the place it is on has drawn and settled. */
17
+ export const DRAWN_ATTRIBUTE = "data-graview-drawn";
18
+ /** How long nothing may move before a place is said to have settled. */
19
+ const QUIET_MS = 200;
20
+ /** How often a place still settling is looked at. */
21
+ const EVERY_MS = 50;
22
+ /** A place that never stops moving — a clock, a view that draws forever — is said drawn after this long all the same. */
23
+ const MOST_MS = 10_000;
24
+ const now = () => (typeof performance !== "undefined" ? performance.now() : Date.now());
25
+ /** Every image the place draws, the worker views' own among them (their shadow roots are open). */
26
+ function images(root) {
27
+ const all = [...root.querySelectorAll("img")];
28
+ for (const view of root.querySelectorAll("[data-worker-view]"))
29
+ if (view.shadowRoot)
30
+ all.push(...view.shadowRoot.querySelectorAll("img"));
31
+ return all;
32
+ }
33
+ /** Whether what the place draws is all here: the face, its parts, its fonts, its images and its views. */
34
+ function here(root) {
35
+ const fonts = root.ownerDocument.fonts;
36
+ if (fonts?.status === "loading")
37
+ return false;
38
+ if (partsArriving() > 0)
39
+ return false;
40
+ // The face on its way, or a part of it saying it is busy: a frame guest among them, until it has drawn or its time is up.
41
+ if (root.querySelector('[aria-busy="true"]'))
42
+ return false;
43
+ // An image off screen and lazy is not waited for: it never loads until it is scrolled to.
44
+ if (images(root).some((image) => !image.complete && image.loading !== "lazy"))
45
+ return false;
46
+ // Each worker view drawn, or failed with its plain face: the region inside its place says which.
47
+ for (const place of root.querySelectorAll("[data-worker-view-place]")) {
48
+ if (!place.querySelector("[data-worker-view][data-worker-view-drawn], [data-worker-view][data-worker-view-failed]"))
49
+ return false;
50
+ }
51
+ return true;
52
+ }
53
+ /** What a move would change: the sizes of the root, the face and each worker view, whose own drawing the observer cannot see. */
54
+ function measure(root) {
55
+ const content = root.querySelector("[data-embed-content]");
56
+ const views = [...root.querySelectorAll("[data-worker-view]")].map((view) => `${view.offsetWidth}x${view.offsetHeight}`);
57
+ return `${root.scrollWidth}x${root.scrollHeight}|${content ? `${content.scrollWidth}x${content.scrollHeight}` : ""}|${views.join(",")}`;
58
+ }
59
+ /**
60
+ * Watch a place settle: takes `data-graview-drawn` off the root at once,
61
+ * and puts it back — `path` its value — once the place has drawn and
62
+ * nothing has moved for a moment, then calls `settled`. The answer stops
63
+ * watching; a place left before it settled is never said drawn.
64
+ */
65
+ export function watchDrawn(root, path, settled) {
66
+ root.removeAttribute(DRAWN_ATTRIBUTE);
67
+ const window = root.ownerDocument.defaultView;
68
+ if (!window)
69
+ return () => undefined;
70
+ const started = now();
71
+ let moved = started;
72
+ let last = measure(root);
73
+ let stopped = false;
74
+ let timer;
75
+ const observer = typeof MutationObserver === "undefined" ? undefined : new MutationObserver((records) => {
76
+ if (records.some((record) => !(record.target === root && record.attributeName === DRAWN_ATTRIBUTE)))
77
+ moved = now();
78
+ });
79
+ observer?.observe(root, { childList: true, subtree: true, characterData: true, attributes: true });
80
+ const stop = () => {
81
+ stopped = true;
82
+ observer?.disconnect();
83
+ if (timer !== undefined)
84
+ clearTimeout(timer);
85
+ };
86
+ // Said after the browser has painted what settled, where it paints at all.
87
+ // A tab out of sight paints nothing, so a frame that never comes is not waited for past a tenth of a second.
88
+ const afterPaint = (then) => {
89
+ let once = false;
90
+ const go = () => {
91
+ if (once)
92
+ return;
93
+ once = true;
94
+ then();
95
+ };
96
+ if (typeof window.requestAnimationFrame === "function")
97
+ window.requestAnimationFrame(() => setTimeout(go, 0));
98
+ setTimeout(go, 100);
99
+ };
100
+ const look = () => {
101
+ if (stopped)
102
+ return;
103
+ const size = measure(root);
104
+ if (size !== last) {
105
+ last = size;
106
+ moved = now();
107
+ }
108
+ const at = now();
109
+ if ((here(root) && at - moved >= QUIET_MS) || at - started >= MOST_MS) {
110
+ afterPaint(() => {
111
+ if (stopped)
112
+ return;
113
+ stop();
114
+ root.setAttribute(DRAWN_ATTRIBUTE, path);
115
+ settled();
116
+ });
117
+ return;
118
+ }
119
+ timer = setTimeout(look, EVERY_MS);
120
+ };
121
+ timer = setTimeout(look, EVERY_MS);
122
+ return stop;
123
+ }
124
+ /**
125
+ * SAYS WHEN THE PLACE HAS DRAWN AND SETTLED, on the root and to the host:
126
+ * watched again from nothing each time `key` moves — another page, another
127
+ * stop on the scene, another face, another draft — so the attribute comes
128
+ * off in the commit that moved and goes back on once the new place
129
+ * settles. The whole embed and the pages alone say it alike.
130
+ */
131
+ export function useDrawnSignal(rootRef, key, place, onDrawn) {
132
+ const latest = useRef({ place, onDrawn });
133
+ latest.current = { place, onDrawn };
134
+ useLayoutEffect(() => {
135
+ const watch = (root) => watchDrawn(root, latest.current.place.path, () => latest.current.onDrawn?.(latest.current.place));
136
+ if (rootRef.current)
137
+ return watch(rootRef.current);
138
+ // First drawn below the root, its ref is set after this effect runs: watched once the commit is done (there is nothing to take off yet).
139
+ let stop;
140
+ let gone = false;
141
+ queueMicrotask(() => {
142
+ if (!gone && rootRef.current)
143
+ stop = watch(rootRef.current);
144
+ });
145
+ return () => {
146
+ gone = true;
147
+ stop?.();
148
+ };
149
+ }, [key, rootRef]);
150
+ }
151
+ //# sourceMappingURL=drawn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drawn.js","sourceRoot":"","sources":["../src/drawn.ts"],"names":[],"mappings":"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"}
package/dist/embed.d.ts CHANGED
@@ -3,6 +3,7 @@ import type { StudioOffered, StudioOnApply, StudioPlace as StudioPlaceType } fro
3
3
  import { type Notice, type NoticeHandle } from "@graview/primitives/frame";
4
4
  import { type Scheme } from "@graview/react/provider";
5
5
  import type { EmbedWhere } from "./where.js";
6
+ import { type EmbedDraftView } from "./draft.js";
6
7
  import { AUTO_SCENE_HEIGHT, type EmbedFace, type EmbedHostContext, type EmbedRemote, type FrameOptions } from "./frame.js";
7
8
  /**
8
9
  * FETCH A FACE BEFORE IT IS DRAWN (FR-57). A host that knows which face it
@@ -58,12 +59,16 @@ export interface EmbedOptions<S extends AnySchema = AnySchema> extends FrameOpti
58
59
  */
59
60
  readonly studio?: false | EmbedStudio;
60
61
  /**
61
- * TOLD WHEN A FACE IS ON THE PAGE (FR-57). Each face is fetched as it is
62
- * first drawn, so the frame stands before the face does; this is called
63
- * with the face asked for once it has drawn (below `pagesBelow`, drawn
64
- * as the pages that stand in for it), each time the face changes.
62
+ * TOLD WHEN A PLACE HAS DRAWN AND SETTLED (FR-188): once the place the
63
+ * reader is on — its face here, every part drawn on it arrived, the fonts
64
+ * and images loaded, each worker view drawn (or failed, its plain face
65
+ * drawn instead) — has not moved for a moment. It is handed the place as
66
+ * `where()` says it. The embed's root wears `data-graview-drawn` (the
67
+ * place's path) from then until the reader moves: a move takes it off in
68
+ * the same commit, and the next place puts it back as it settles. A host
69
+ * picturing a place waits for the attribute rather than a guess.
65
70
  */
66
- readonly onDrawn?: (face: EmbedFace) => void;
71
+ readonly onDrawn?: (place: EmbedWhere) => void;
67
72
  /**
68
73
  * THE QUICK ASK on both faces (Roadmap f-quick-ask-framework): ⌘K's
69
74
  * command bar beside what is selected, and the answer cards it leaves.
@@ -79,7 +84,20 @@ export interface EmbedOptions<S extends AnySchema = AnySchema> extends FrameOpti
79
84
  * host that must remount on a new declaration hands the old place back here.
80
85
  */
81
86
  readonly at?: EmbedWhere;
87
+ /**
88
+ * A VIEW PROPOSED AND NOT KEPT (FR-187): a worker view's manifest and its
89
+ * `source` (or `worker`), drawn for the seat at the keyboard where its
90
+ * manifest attaches — the home, a kind's list, a record — over the app's
91
+ * own views, and marked "Draft — <title> · Not kept". A kept view of the
92
+ * same name is the one it stands in for. Nothing of it is kept: it is in
93
+ * no store and no `keptViews`, the place menu offers it nothing, and it
94
+ * is gone when the page closes. The worker's host is fetched before the
95
+ * embed draws, only when a draft is handed. `handle.setDraftView` swaps
96
+ * it for another, or none, without a remount.
97
+ */
98
+ readonly draftView?: EmbedDraftView | null;
82
99
  }
100
+ export type { EmbedDraftView } from "./draft.js";
83
101
  /** The studio an embed offers, for a host that keeps the declaration itself. */
84
102
  export interface EmbedStudio {
85
103
  /**
@@ -121,6 +139,14 @@ export interface EmbedProps<S extends AnySchema = AnySchema> extends EmbedOption
121
139
  readonly onOpening?: (face: EmbedFace) => void;
122
140
  /** Called when a seat is taken in the person's menu; the host decides who sits. */
123
141
  readonly onSeat?: (principal: Principal) => void;
142
+ /**
143
+ * TOLD WHEN A FACE IS ON THE PAGE (FR-57). Each face is fetched as it is
144
+ * first drawn, so the frame stands before the face does; this is called
145
+ * with the face asked for once it has drawn (below `pagesBelow`, drawn
146
+ * as the pages that stand in for it), each time the face changes. What
147
+ * `handle.drawn()` waits for; `onDrawn` waits for the place to settle.
148
+ */
149
+ readonly onFaceDrawn?: (face: EmbedFace) => void;
124
150
  }
125
151
  /** The face a stop implies: a stop at altitude opens the Graview, anything else the scene (FR-132). */
126
152
  export declare function faceOf(stop: string | undefined): EmbedFace;
@@ -182,6 +208,14 @@ export interface EmbedHandle {
182
208
  setHostContext(context: EmbedHostContext): void;
183
209
  /** Re-dress the embed: another brand, or the same brand with a different kit. */
184
210
  setBrand(brand: Brand | undefined): void;
211
+ /**
212
+ * ANOTHER VIEW PROPOSED AND NOT KEPT, OR NONE (FR-187): the draft drawn
213
+ * where it attaches swapped in place, without a remount — the store, the
214
+ * place and the seat stay. `data-graview-drawn` comes off in the call and
215
+ * returns once the new draft has drawn and settled; `null` draws the
216
+ * app's own views again.
217
+ */
218
+ setDraftView(draft: EmbedDraftView | null): void;
185
219
  /**
186
220
  * Resolves once the face now asked for is drawn (FR-57). The frame is on
187
221
  * the page when `mount` returns; each face is fetched as it is first
@@ -1 +1 @@
1
- {"version":3,"file":"embed.d.ts","sourceRoot":"","sources":["../src/embed.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"embed.d.ts","sourceRoot":"","sources":["../src/embed.tsx"],"names":[],"mappings":"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"}
package/dist/embed.js CHANGED
@@ -7,6 +7,8 @@ import { createNoticeBoard, quickAskOf } from "@graview/primitives/frame";
7
7
  import { ErrorReportContext, GraviewProvider, lazyModule, markLanded, openingView, useNavigation } from "@graview/react/provider";
8
8
  import { AddressBar, atTheBareHome, faceAtAddress, holdsNothing, landing, placed, stopAtAddress, whereTheSceneOpens } from "./address.js";
9
9
  import { createContext, createElement, Suspense, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
10
+ import { useDrawnSignal } from "./drawn.js";
11
+ import { draftWaits, fetchDraftHost, Settling, useDraft } from "./draft.js";
10
12
  import { createRoot } from "react-dom/client";
11
13
  import { flushSync } from "react-dom";
12
14
  import { AUTO_SCENE_HEIGHT, FaceBoundary, FrameBar, FrameFirstLook, FrameNotices, providerProps, storeOf, useErrorReport, useFrame, useIntrinsicHeight, useReady, titleBelow, useSteering, useViews, } from "./frame.js";
@@ -181,13 +183,22 @@ export function opensOnTheHome(app, views) {
181
183
  export function Embed(props) {
182
184
  const [, ready] = useState(false);
183
185
  const arrived = useCallback(() => ready(true), []);
186
+ const drew = useRef(false);
184
187
  // A place handed back is settled before the embed draws: until the rules for it are here, nothing stands in the element.
185
- return props.at && !settling ? _jsx(Settling, { onReady: arrived }) : _jsx(Drawing, { ...props });
188
+ if (props.at && !settling)
189
+ return _jsx(Settling, { onReady: arrived, fetch: fetchSettling });
190
+ // A draft is drawn with the app's own views from the first frame (FR-187): until the worker's host is here, nothing stands in the element.
191
+ // One handed later (`setDraftView`) is drawn in once the host arrives, never by drawing the embed again from nothing.
192
+ if (!drew.current && draftWaits(props.draftView))
193
+ return _jsx(Settling, { onReady: arrived, fetch: fetchDraftHost });
194
+ drew.current = true;
195
+ return _jsx(Drawing, { ...props });
186
196
  }
187
197
  function Drawing(props) {
188
198
  const { app, stop, bar = true, standing = "Everything is in order", principal, heading = 2 } = props;
189
199
  const { rootRef, scope, css, scheme, store, presence, brand, auto, height } = useFrame(props);
190
- const views = useViews(props, frameworkViewDoors);
200
+ const draft = useDraft(props.draftView);
201
+ const views = useViews(props, frameworkViewDoors, draft.over);
191
202
  /*
192
203
  * THE FACE IT OPENS ON (FR-136). When the host names none: the home, when
193
204
  * the app has a home view and the declaration names no other first place
@@ -302,8 +313,8 @@ function Drawing(props) {
302
313
  useOtherFaceWhenIdle(shown, width);
303
314
  const report = useErrorReport(props.onError, shown);
304
315
  const ready = useReady(props.onReady, shown);
305
- const drawnTold = useRef(props.onDrawn);
306
- drawnTold.current = props.onDrawn;
316
+ const drawnTold = useRef(props.onFaceDrawn);
317
+ drawnTold.current = props.onFaceDrawn;
307
318
  const drawn = useCallback((asked, drew) => {
308
319
  ready(drew);
309
320
  drawnTold.current?.(asked);
@@ -400,7 +411,7 @@ function Drawing(props) {
400
411
  */
401
412
  return (_jsxs("section", { ref: rootRef, className: scope, "aria-label": props.label ?? app.name, "data-graview-embed": shown, "data-graview-scheme": scheme, ...(narrow ? { "data-graview-embed-narrow": "" } : {}),
402
413
  // Its own stacking context: every layer inside it (the scene's corner control, a panel) is ordered inside it, never over the host's page.
403
- style: { position: "relative", isolation: "isolate", height, minHeight: auto ? 0 : 320, display: "flex", flexDirection: "column", overflow: "hidden", borderRadius: "var(--graview-radius, 12px)" }, children: [_jsx("style", { children: css }), _jsxs(ErrorReportContext.Provider, { value: report, children: [_jsx(FrameNotices, { rootRef: rootRef, board: notices }), _jsx(FrameFirstLook, { rootRef: rootRef, firstLook: props.firstLook, app: appKeyOf(brand ?? { name: app.name }, app.schema) }), _jsx(FaceBoundary, { module: "@graview/react", report: report, content: true, children: _jsx(GraviewProvider, { store: store, views: views, initialView: initialView, scheme: scheme, ...providerProps(props, presence, brand), ...(props.onSeat ? { onSeat: props.onSeat } : {}), children: _jsxs(NoticeBoardContext.Provider, { value: notices, children: [_jsx(Faces, { face: shown, stop: overviewStop ?? stop, kinds: kinds, places: places, opens: opens }), whereabouts ? _jsx(Watch, { into: whereabouts }) : null, address ? _jsx(AddressBar, { pagesWere: at?.path, basePath: props.basePath, shown: shown, onFace: props.onFace, toggle: toggled, kinds: kinds, places: places, opens: opens, landed: landed }) : null, bar && shown !== "picture" ? (_jsx(FaceBoundary, { module: "@graview/embed", report: report, children: _jsx(FrameBar, { name: brand?.name ?? app.name, heading: heading, faces: {
414
+ style: { position: "relative", isolation: "isolate", height, minHeight: auto ? 0 : 320, display: "flex", flexDirection: "column", overflow: "hidden", borderRadius: "var(--graview-radius, 12px)" }, children: [_jsx("style", { children: css }), _jsxs(ErrorReportContext.Provider, { value: report, children: [_jsx(FrameNotices, { rootRef: rootRef, board: notices }), _jsx(FrameFirstLook, { rootRef: rootRef, firstLook: props.firstLook, app: appKeyOf(brand ?? { name: app.name }, app.schema) }), _jsx(FaceBoundary, { module: "@graview/react", report: report, content: true, children: _jsx(GraviewProvider, { store: store, views: views, initialView: initialView, scheme: scheme, ...providerProps(props, presence, brand), ...(props.onSeat ? { onSeat: props.onSeat } : {}), children: _jsxs(NoticeBoardContext.Provider, { value: notices, children: [_jsx(Faces, { face: shown, stop: overviewStop ?? stop, kinds: kinds, places: places, opens: opens }), whereabouts ? _jsx(Watch, { into: whereabouts }) : null, _jsx(DrawnSignal, { rootRef: rootRef, face: face, shown: shown, path: pageAt, stop: stop, draft: draft.n, onDrawn: props.onDrawn }), address ? _jsx(AddressBar, { pagesWere: at?.path, basePath: props.basePath, shown: shown, onFace: props.onFace, toggle: toggled, kinds: kinds, places: places, opens: opens, landed: landed }) : null, bar && shown !== "picture" ? (_jsx(FaceBoundary, { module: "@graview/embed", report: report, children: _jsx(FrameBar, { name: brand?.name ?? app.name, heading: heading, faces: {
404
415
  scene: { label: sceneTitle(arrangement), current: !onPages, go: () => toOverview(), reach: () => void preload(sceneFace.current) },
405
416
  // The pages, back at the page the reader was on.
406
417
  pages: { label: pagesTitle(arrangement), current: onPages, go: () => toPage(pagesAt.current.path), reach: () => void preload("pages") },
@@ -414,6 +425,22 @@ function Watch({ into }) {
414
425
  into.view = useNavigation().view;
415
426
  return null;
416
427
  }
428
+ /**
429
+ * SAYS WHEN THE PLACE HAS DRAWN AND SETTLED (FR-188), on the root, and to
430
+ * the host: watched again from nothing each time the reader moves — another
431
+ * page, another stop on the scene, another face — or another draft is
432
+ * handed (`setDraftView`), so the attribute comes off in the commit that
433
+ * moved and goes back on once the new place settles.
434
+ */
435
+ function DrawnSignal({ rootRef, face, shown, path, stop, draft, onDrawn }) {
436
+ const { view } = useNavigation();
437
+ const onScene = shown === "scene" || shown === "graview";
438
+ const sceneStop = toUrl(view);
439
+ // Where the reader is, as `where()` says it: the overview's path on the scene, with its stop.
440
+ const place = { face, path: onScene ? OVERVIEW_PATH : shown === "picture" ? (stop ?? "#") : path, stop: sceneStop };
441
+ useDrawnSignal(rootRef, `${shown} ${onScene ? sceneStop : place.path} ${draft}`, place, onDrawn);
442
+ return null;
443
+ }
417
444
  /*
418
445
  * SETTLING A PLACE IN A NEW APP, fetched when one is handed over (FR-116):
419
446
  * a declaration changes rarely, and a page that never swaps one never loads
@@ -431,11 +458,6 @@ const fetchSettling = () => whereChunk().then((module) => void (settling = modul
431
458
  const timer = setTimeout(again, 10_000);
432
459
  window.addEventListener("online", again);
433
460
  }).then(fetchSettling));
434
- /** Stands in for the embed while the rules for a handed-back place arrive, then draws it. */
435
- function Settling({ onReady }) {
436
- useLayoutEffect(() => void fetchSettling().then(onReady), [onReady]);
437
- return null;
438
- }
439
461
  /** Keeps the scene's view in step with the face and stop props. */
440
462
  function Faces({ face, stop, kinds, places, opens }) {
441
463
  const { view, go } = useNavigation();
@@ -521,9 +543,8 @@ export function mount(element, options) {
521
543
  let asked = opening ?? faceOf(options.stop);
522
544
  let drawnFace = null;
523
545
  let waiting = [];
524
- const onDrawn = (face) => {
546
+ const onFaceDrawn = (face) => {
525
547
  drawnFace = face;
526
- options.onDrawn?.(face);
527
548
  if (face !== asked)
528
549
  return;
529
550
  const done = waiting;
@@ -545,20 +566,21 @@ export function mount(element, options) {
545
566
  const [called, setCalled] = useState(options.label);
546
567
  const [hostActions, setHostActions] = useState(options.hostActions);
547
568
  const [swap, setSwap] = useState(undefined);
569
+ const [draft, setDraft] = useState(options.draftView);
548
570
  setters = {
549
571
  app: (next) => {
550
572
  setSwap(next);
551
573
  setPath(undefined);
552
574
  setStop(undefined);
553
575
  },
554
- face: setFace, stop: setStop, path: setPath, scheme: setScheme, seat: setSeat, seats: setSeats, quickAsk: setQuickAsk, people: setPeople, hostContext: setHostContext, brand: setBrand, label: setCalled, hostActions: setHostActions
576
+ face: setFace, stop: setStop, path: setPath, scheme: setScheme, seat: setSeat, seats: setSeats, quickAsk: setQuickAsk, people: setPeople, hostContext: setHostContext, brand: setBrand, label: setCalled, hostActions: setHostActions, draft: setDraft
555
577
  };
556
578
  return (_jsx(Whereabouts.Provider, { value: here, children: _jsx(Embed, { ...(swap ? swapped(options, swap) : options), store: store, notices: board, ...(face !== undefined ? { face } : {}), onOpening: (opened) => {
557
579
  asked = opened;
558
- }, ...(stop !== undefined ? { stop } : {}), ...(path !== undefined ? { path } : {}), ...(principal ? { principal } : {}), ...(seats ? { seats } : {}), ...(quickAsk !== undefined ? { quickAsk } : {}), ...(people ? { people } : {}), ...(hostContext ? { hostContext } : {}), ...(brand ? { brand } : {}), label: called, hostActions: hostActions, scheme: scheme, onFace: (next) => {
580
+ }, ...(stop !== undefined ? { stop } : {}), ...(path !== undefined ? { path } : {}), ...(principal ? { principal } : {}), ...(seats ? { seats } : {}), ...(quickAsk !== undefined ? { quickAsk } : {}), ...(people ? { people } : {}), ...(hostContext ? { hostContext } : {}), ...(brand ? { brand } : {}), label: called, hostActions: hostActions, draftView: draft, scheme: scheme, onFace: (next) => {
559
581
  asked = next;
560
582
  setFace(next);
561
- }, onSeat: setSeat, onDrawn: onDrawn }, swap?.n ?? 0) }));
583
+ }, onSeat: setSeat, onFaceDrawn: onFaceDrawn }, swap?.n ?? 0) }));
562
584
  }
563
585
  const where = () => {
564
586
  const focus = here.view?.focusId;
@@ -620,6 +642,7 @@ export function mount(element, options) {
620
642
  setPeople: (people) => flushSync(() => setters?.people(people)),
621
643
  setHostContext: (context) => flushSync(() => setters?.hostContext(context)),
622
644
  setBrand: (brand) => flushSync(() => setters?.brand(brand)),
645
+ setDraftView: (draft) => flushSync(() => setters?.draft(draft)),
623
646
  setLabel: (given) => {
624
647
  label = given;
625
648
  flushSync(() => setters?.label(given));