@graview/studio 0.0.0-stage → 0.1.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/LICENSE +96 -0
- package/README.md +31 -2
- package/dist/agent-panel.d.ts +11 -0
- package/dist/agent-panel.d.ts.map +1 -0
- package/dist/agent-panel.js +334 -0
- package/dist/agent-panel.js.map +1 -0
- package/dist/agent.d.ts +24 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +371 -0
- package/dist/agent.js.map +1 -0
- package/dist/changes.d.ts +49 -0
- package/dist/changes.d.ts.map +1 -0
- package/dist/changes.js +217 -0
- package/dist/changes.js.map +1 -0
- package/dist/from-declaration.d.ts +13 -0
- package/dist/from-declaration.d.ts.map +1 -0
- package/dist/from-declaration.js +204 -0
- package/dist/from-declaration.js.map +1 -0
- package/dist/in-place.d.ts +27 -0
- package/dist/in-place.d.ts.map +1 -0
- package/dist/in-place.js +151 -0
- package/dist/in-place.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/lens.d.ts +9 -0
- package/dist/lens.d.ts.map +1 -0
- package/dist/lens.js +40 -0
- package/dist/lens.js.map +1 -0
- package/dist/meta.d.ts +2648 -0
- package/dist/meta.d.ts.map +1 -0
- package/dist/meta.js +553 -0
- package/dist/meta.js.map +1 -0
- package/dist/migration.d.ts +15 -0
- package/dist/migration.d.ts.map +1 -0
- package/dist/migration.js +82 -0
- package/dist/migration.js.map +1 -0
- package/dist/place.d.ts +61 -0
- package/dist/place.d.ts.map +1 -0
- package/dist/place.js +328 -0
- package/dist/place.js.map +1 -0
- package/dist/rewrite.d.ts +28 -0
- package/dist/rewrite.d.ts.map +1 -0
- package/dist/rewrite.js +52 -0
- package/dist/rewrite.js.map +1 -0
- package/dist/source.d.ts +69 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +465 -0
- package/dist/source.js.map +1 -0
- package/dist/studio.d.ts +64 -0
- package/dist/studio.d.ts.map +1 -0
- package/dist/studio.js +96 -0
- package/dist/studio.js.map +1 -0
- package/dist/to-declaration.d.ts +24 -0
- package/dist/to-declaration.d.ts.map +1 -0
- package/dist/to-declaration.js +439 -0
- package/dist/to-declaration.js.map +1 -0
- package/dist/write-in-place.d.ts +27 -0
- package/dist/write-in-place.d.ts.map +1 -0
- package/dist/write-in-place.js +61 -0
- package/dist/write-in-place.js.map +1 -0
- package/dist/zod-source.d.ts +7 -0
- package/dist/zod-source.d.ts.map +1 -0
- package/dist/zod-source.js +124 -0
- package/dist/zod-source.js.map +1 -0
- package/package.json +58 -3
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { stepsMigration } from "@graview/ship/browser";
|
|
2
|
+
import { declarationToGraph } from "./from-declaration.js";
|
|
3
|
+
import { defaultFor } from "./to-declaration.js";
|
|
4
|
+
const ofKind = (reading, kind) => reading.nodes.filter((node) => node.kind === kind);
|
|
5
|
+
const label = (node) => String(node["label"] ?? node.id);
|
|
6
|
+
const targetsOf = (reading, from, kind) => reading.edges.filter((edge) => edge.from === from && edge.kind === kind).map((edge) => edge.to);
|
|
7
|
+
/** The steps between two declarations' graphs; empty when the stored graph needs nothing. */
|
|
8
|
+
export function migrationSteps(before, after) {
|
|
9
|
+
const steps = [];
|
|
10
|
+
const beforeKinds = new Map(ofKind(before, "kind").map((node) => [node.id, node]));
|
|
11
|
+
const afterKinds = new Map(ofKind(after, "kind").map((node) => [node.id, node]));
|
|
12
|
+
for (const [id, node] of beforeKinds) {
|
|
13
|
+
const after = afterKinds.get(id);
|
|
14
|
+
if (!after)
|
|
15
|
+
steps.push({ what: "remove-kind", kind: label(node) });
|
|
16
|
+
// The same declaration, called something else: its records carry the new name.
|
|
17
|
+
else if (label(after) !== label(node))
|
|
18
|
+
steps.push({ what: "rename-kind", kind: label(node), to: label(after) });
|
|
19
|
+
}
|
|
20
|
+
const fieldKey = (reading, field) => {
|
|
21
|
+
const kindId = targetsOf(reading, field.id, "of")[0];
|
|
22
|
+
return kindId ? `${kindId}::${label(field)}` : null;
|
|
23
|
+
};
|
|
24
|
+
const beforeFields = new Map(ofKind(before, "field").map((node) => [fieldKey(before, node), node]));
|
|
25
|
+
const afterFields = new Map(ofKind(after, "field").map((node) => [fieldKey(after, node), node]));
|
|
26
|
+
for (const [key, node] of beforeFields) {
|
|
27
|
+
if (!key || afterFields.has(key))
|
|
28
|
+
continue;
|
|
29
|
+
const kindId = key.split("::")[0];
|
|
30
|
+
const kindNode = afterKinds.get(kindId);
|
|
31
|
+
if (!kindNode)
|
|
32
|
+
continue; // the whole kind goes; its fields go with it
|
|
33
|
+
steps.push({ what: "remove-field", kind: label(kindNode), field: label(node) });
|
|
34
|
+
}
|
|
35
|
+
for (const [key, node] of afterFields) {
|
|
36
|
+
if (!key || beforeFields.has(key) || node["required"] !== true)
|
|
37
|
+
continue;
|
|
38
|
+
const kindId = key.split("::")[0];
|
|
39
|
+
if (!beforeKinds.has(kindId))
|
|
40
|
+
continue; // a new kind has no stored records
|
|
41
|
+
const kindNode = afterKinds.get(kindId);
|
|
42
|
+
const options = Array.isArray(node["options"]) ? node["options"].map(String) : undefined;
|
|
43
|
+
steps.push({ what: "start-field", kind: label(kindNode), field: label(node), value: defaultFor(node["type"] ?? "string", options) });
|
|
44
|
+
}
|
|
45
|
+
const edgeKey = (reading, edge) => {
|
|
46
|
+
const kindId = targetsOf(reading, edge.id, "from-kind")[0];
|
|
47
|
+
return kindId ? `${kindId}::${label(edge)}` : null;
|
|
48
|
+
};
|
|
49
|
+
const beforeEdges = new Map(ofKind(before, "edge").map((node) => [edgeKey(before, node), node]));
|
|
50
|
+
const afterEdges = new Map(ofKind(after, "edge").map((node) => [edgeKey(after, node), node]));
|
|
51
|
+
// By name as well, so the same relation declared on another kind is seen as MOVED.
|
|
52
|
+
const afterByName = new Map([...afterEdges].flatMap(([key, node]) => (key ? [[label(node), key.split("::")[0]]] : [])));
|
|
53
|
+
for (const [key, node] of beforeEdges) {
|
|
54
|
+
if (!key || afterEdges.has(key))
|
|
55
|
+
continue;
|
|
56
|
+
const kindId = key.split("::")[0];
|
|
57
|
+
const kindNode = afterKinds.get(kindId);
|
|
58
|
+
if (!kindNode)
|
|
59
|
+
continue;
|
|
60
|
+
const movedTo = afterByName.get(label(node));
|
|
61
|
+
const heir = movedTo ? afterKinds.get(movedTo) : undefined;
|
|
62
|
+
steps.push(heir
|
|
63
|
+
? { what: "move-edge", kind: label(kindNode), edge: label(node), to: label(heir) }
|
|
64
|
+
: { what: "remove-edge", kind: label(kindNode), edge: label(node) });
|
|
65
|
+
}
|
|
66
|
+
return steps;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The migration from one declaration to the next, or null when a stored
|
|
70
|
+
* graph shaped like the old one is already a graph shaped like the new.
|
|
71
|
+
* Given the studio's own graph as `after`, a renamed kind is seen as a
|
|
72
|
+
* rename — its node kept its id — where two declarations read separately
|
|
73
|
+
* would show one kind gone and another arrived.
|
|
74
|
+
*/
|
|
75
|
+
export function migrationBetween(before, after) {
|
|
76
|
+
const steps = migrationSteps(declarationToGraph(before), "nodes" in after ? after : declarationToGraph(after));
|
|
77
|
+
if (steps.length === 0)
|
|
78
|
+
return null;
|
|
79
|
+
const from = before.version ?? 1;
|
|
80
|
+
return stepsMigration({ from, to: from + 1, steps });
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration.js","sourceRoot":"","sources":["../src/migration.ts"],"names":[],"mappings":"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"}
|
package/dist/place.d.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { INSTALLATION_MODULE, type AnySchema, type GraviewApp, type Store } from "@graview/core";
|
|
2
|
+
import { type Studio } from "./studio.js";
|
|
3
|
+
/**
|
|
4
|
+
* THE STUDIO IS A PLACE ON THE BAR, not a package you mount by hand.
|
|
5
|
+
*
|
|
6
|
+
* `@graview/studio` shipped as a package and as a chapter of the seedbed,
|
|
7
|
+
* and there was no way into it from the app you were looking at: to open a
|
|
8
|
+
* studio over your own declaration you wrote code. So the thing the whole
|
|
9
|
+
* platform story rests on — that the declaration is a graph you can change
|
|
10
|
+
* with the same gestures you change data with — was true and unreachable.
|
|
11
|
+
*
|
|
12
|
+
* One press, in place. The running app's declaration is read into a studio
|
|
13
|
+
* store; the scene draws its kinds, fields, edges, acts, rules, roles and
|
|
14
|
+
* grants as ordinary districts; the actions strip offers the acts that
|
|
15
|
+
* change them; "What the checker says" is a place beside them; every change
|
|
16
|
+
* has an author and an inverse. Applying runs `graview check` first and
|
|
17
|
+
* refuses on errors, naming them. What comes back is the files
|
|
18
|
+
* `graview create` writes and the migration a stored graph needs — offered
|
|
19
|
+
* as downloads, because a browser cannot write your checkout and pretending
|
|
20
|
+
* otherwise would be the one dishonest thing in the whole flow.
|
|
21
|
+
*
|
|
22
|
+
* AND OPENING IT IS A STOP. It was component state — so the one door in
|
|
23
|
+
* this interface that Back did not know about was the door into the app's
|
|
24
|
+
* own declaration: you pressed Escape or Back and left the whole app
|
|
25
|
+
* instead of the studio. It is `in.studio=open` in the address now, which
|
|
26
|
+
* means the browser's arrows and the bar's own carry you in and out of it,
|
|
27
|
+
* a link can open it, and closing puts you back exactly where you were —
|
|
28
|
+
* which is what the stop you came from IS.
|
|
29
|
+
*/
|
|
30
|
+
export declare function StudioPlace<S extends AnySchema>({ app, label, within, }: {
|
|
31
|
+
/** The declaration to open. The running app's own, in every case that matters. */
|
|
32
|
+
readonly app: GraviewApp<S>;
|
|
33
|
+
readonly label?: string;
|
|
34
|
+
/**
|
|
35
|
+
* How much of the screen the studio takes.
|
|
36
|
+
*
|
|
37
|
+
* "page" fills the window, which is what a whole app wants. "box" fills
|
|
38
|
+
* the nearest positioned ancestor, which is what an EMBED wants: a studio
|
|
39
|
+
* that escaped its box would cover somebody else's page.
|
|
40
|
+
*
|
|
41
|
+
* Said rather than inferred, because the control lives on a bar whose own
|
|
42
|
+
* `position: relative` would otherwise become the containing block — the
|
|
43
|
+
* first cut drew the whole studio inside a 57-pixel-tall header, where its
|
|
44
|
+
* scene was laid out under the bar it was drawn in.
|
|
45
|
+
*/
|
|
46
|
+
readonly within?: "page" | "box";
|
|
47
|
+
}): import("react").JSX.Element | null;
|
|
48
|
+
/**
|
|
49
|
+
* Who is offered it.
|
|
50
|
+
*
|
|
51
|
+
* The same shape as "Show the installation": where the app declares
|
|
52
|
+
* something administered, the studio belongs to the seat that administers
|
|
53
|
+
* it and to nobody else. Where it declares nothing administered — a
|
|
54
|
+
* scaffolded project on its first day, which has no installation yet — it
|
|
55
|
+
* belongs to whoever is here, because there is no one else and a project
|
|
56
|
+
* you cannot open the studio on is a project you cannot grow.
|
|
57
|
+
*/
|
|
58
|
+
export declare function maySeeTheStudio<S extends AnySchema>(store: Store<S>, principal: Parameters<Store<S>["mayAdminister"]>[1]): boolean;
|
|
59
|
+
export { INSTALLATION_MODULE };
|
|
60
|
+
export type { Studio };
|
|
61
|
+
//# sourceMappingURL=place.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"place.d.ts","sourceRoot":"","sources":["../src/place.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,KAAK,SAAS,EAAoB,KAAK,UAAU,EAAE,KAAK,KAAK,EAAE,MAAM,eAAe,CAAC;AAWnH,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAKxD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,SAAS,EAAE,EAC/C,GAAG,EACH,KAAgB,EAChB,MAAe,GAChB,EAAE;IACD,kFAAkF;IAClF,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CAClC,sCAkDA;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,SAAS,EACjD,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EACf,SAAS,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,GAClD,OAAO,CAIT;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAC;AA2Z/B,YAAY,EAAE,MAAM,EAAE,CAAC"}
|
package/dist/place.js
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { INSTALLATION_MODULE } from "@graview/core";
|
|
3
|
+
import { EMPTY_VIEW, withWithin } from "@graview/layout";
|
|
4
|
+
import { GraviewProvider, Scene, createViews, useGraview, useNavigation, useTheKeyboardLandsSomewhere } from "@graview/react";
|
|
5
|
+
import { ActivityRail, AgentSeat, Inspector, Places, registerDefaultViews } from "@graview/primitives";
|
|
6
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
7
|
+
import { createPortal } from "react-dom";
|
|
8
|
+
import { useStoreTick } from "@graview/pages";
|
|
9
|
+
import { StudioAgentPanel } from "./agent-panel.js";
|
|
10
|
+
import { createStudioLens } from "./lens.js";
|
|
11
|
+
import { studioApp } from "./meta.js";
|
|
12
|
+
import { createStudio } from "./studio.js";
|
|
13
|
+
import { Downloads, InPlaceWriter } from "./in-place.js";
|
|
14
|
+
import { useStudioDoor } from "./write-in-place.js";
|
|
15
|
+
/**
|
|
16
|
+
* THE STUDIO IS A PLACE ON THE BAR, not a package you mount by hand.
|
|
17
|
+
*
|
|
18
|
+
* `@graview/studio` shipped as a package and as a chapter of the seedbed,
|
|
19
|
+
* and there was no way into it from the app you were looking at: to open a
|
|
20
|
+
* studio over your own declaration you wrote code. So the thing the whole
|
|
21
|
+
* platform story rests on — that the declaration is a graph you can change
|
|
22
|
+
* with the same gestures you change data with — was true and unreachable.
|
|
23
|
+
*
|
|
24
|
+
* One press, in place. The running app's declaration is read into a studio
|
|
25
|
+
* store; the scene draws its kinds, fields, edges, acts, rules, roles and
|
|
26
|
+
* grants as ordinary districts; the actions strip offers the acts that
|
|
27
|
+
* change them; "What the checker says" is a place beside them; every change
|
|
28
|
+
* has an author and an inverse. Applying runs `graview check` first and
|
|
29
|
+
* refuses on errors, naming them. What comes back is the files
|
|
30
|
+
* `graview create` writes and the migration a stored graph needs — offered
|
|
31
|
+
* as downloads, because a browser cannot write your checkout and pretending
|
|
32
|
+
* otherwise would be the one dishonest thing in the whole flow.
|
|
33
|
+
*
|
|
34
|
+
* AND OPENING IT IS A STOP. It was component state — so the one door in
|
|
35
|
+
* this interface that Back did not know about was the door into the app's
|
|
36
|
+
* own declaration: you pressed Escape or Back and left the whole app
|
|
37
|
+
* instead of the studio. It is `in.studio=open` in the address now, which
|
|
38
|
+
* means the browser's arrows and the bar's own carry you in and out of it,
|
|
39
|
+
* a link can open it, and closing puts you back exactly where you were —
|
|
40
|
+
* which is what the stop you came from IS.
|
|
41
|
+
*/
|
|
42
|
+
export function StudioPlace({ app, label = "Studio", within = "page", }) {
|
|
43
|
+
const { store, principal } = useGraview();
|
|
44
|
+
const { view, go } = useNavigation();
|
|
45
|
+
const open = view.within?.["studio"] === "open";
|
|
46
|
+
const setOpen = (next) => go(withWithin(view, "studio", next ? "open" : null));
|
|
47
|
+
if (!maySeeTheStudio(store, principal))
|
|
48
|
+
return null;
|
|
49
|
+
return (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", "data-testid": "studio-place", "aria-expanded": open, onClick: () => setOpen(!open), title: "Open this app's own declaration \u2014 its kinds, fields, acts and rules \u2014 and change it", style: {
|
|
50
|
+
padding: "3px 11px",
|
|
51
|
+
borderRadius: 999,
|
|
52
|
+
fontSize: "0.875rem",
|
|
53
|
+
whiteSpace: "nowrap",
|
|
54
|
+
borderWidth: 1,
|
|
55
|
+
borderStyle: "solid",
|
|
56
|
+
borderColor: open ? "var(--graview-accent)" : "var(--graview-edge)",
|
|
57
|
+
color: open ? "var(--graview-accent)" : "var(--graview-ink-muted)",
|
|
58
|
+
background: open ? "var(--graview-panel)" : "transparent",
|
|
59
|
+
}, children: label }), open ? (
|
|
60
|
+
/*
|
|
61
|
+
* OUT OF THE BAR ENTIRELY, for the page-filling case.
|
|
62
|
+
*
|
|
63
|
+
* The control lives on a bar that carries `backdrop-filter`, and a
|
|
64
|
+
* filtered element is a containing block for its fixed descendants
|
|
65
|
+
* as well as its absolute ones — so neither `absolute` nor `fixed`
|
|
66
|
+
* escaped it, and the whole studio was drawn inside a 57-pixel-tall
|
|
67
|
+
* header with its scene laid out under the bar it was drawn in. A
|
|
68
|
+
* portal is the only thing no ancestor's filter can capture.
|
|
69
|
+
*
|
|
70
|
+
* The boxed case stays where it is on purpose: an embed's studio
|
|
71
|
+
* must not escape the embed.
|
|
72
|
+
*/
|
|
73
|
+
within === "page" ? (createPortal(_jsx(StudioOverlay, { app: app, within: within, onClose: () => setOpen(false) }), document.body)) : (_jsx(StudioOverlay, { app: app, within: within, onClose: () => setOpen(false) }))) : null] }));
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Who is offered it.
|
|
77
|
+
*
|
|
78
|
+
* The same shape as "Show the installation": where the app declares
|
|
79
|
+
* something administered, the studio belongs to the seat that administers
|
|
80
|
+
* it and to nobody else. Where it declares nothing administered — a
|
|
81
|
+
* scaffolded project on its first day, which has no installation yet — it
|
|
82
|
+
* belongs to whoever is here, because there is no one else and a project
|
|
83
|
+
* you cannot open the studio on is a project you cannot grow.
|
|
84
|
+
*/
|
|
85
|
+
export function maySeeTheStudio(store, principal) {
|
|
86
|
+
const administered = [...store.modules.administered.keys()];
|
|
87
|
+
if (administered.length === 0)
|
|
88
|
+
return true;
|
|
89
|
+
return administered.some((name) => store.mayAdminister(name, principal));
|
|
90
|
+
}
|
|
91
|
+
export { INSTALLATION_MODULE };
|
|
92
|
+
/**
|
|
93
|
+
* The studio itself, over the whole picture it was opened from.
|
|
94
|
+
*
|
|
95
|
+
* A face rather than a route: you are still in your app, and closing puts
|
|
96
|
+
* you back exactly where you were rather than at whatever the studio's own
|
|
97
|
+
* address happened to be.
|
|
98
|
+
*/
|
|
99
|
+
function StudioOverlay({ app, within, onClose, }) {
|
|
100
|
+
const { principal, brand, scheme } = useGraview();
|
|
101
|
+
const studio = useMemo(() => createStudio(app, { principal }), [app, principal]);
|
|
102
|
+
/*
|
|
103
|
+
* A DIALOG GIVES THE KEYBOARD BACK. The studio opens over the app from a
|
|
104
|
+
* button in the profile; closing it removed the dialog the keyboard was
|
|
105
|
+
* in and left it on <body>. Whatever held the keyboard when it opened
|
|
106
|
+
* holds it again when it closes — and inside, an act that removes what
|
|
107
|
+
* the keyboard stood on lands it on what still stands.
|
|
108
|
+
*/
|
|
109
|
+
const dialog = useRef(null);
|
|
110
|
+
useTheKeyboardLandsSomewhere(dialog);
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
const opener = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
113
|
+
// Opened, it takes the keyboard: a dialog the keyboard is not in is one it cannot reach.
|
|
114
|
+
dialog.current?.focus({ preventScroll: true });
|
|
115
|
+
/*
|
|
116
|
+
* AND HOLDS IT WHILE IT IS OPEN. Taken once, at mount, the keyboard could
|
|
117
|
+
* still be taken back by what opened the studio — the profile's menu
|
|
118
|
+
* closing behind it — and on the nightly's runner it sat on <body> with
|
|
119
|
+
* the studio open. A modal dialog keeps the keyboard inside itself: when
|
|
120
|
+
* it lands on nothing while the studio is open, it comes back to the
|
|
121
|
+
* studio.
|
|
122
|
+
*/
|
|
123
|
+
const onNothing = () => {
|
|
124
|
+
const active = document.activeElement;
|
|
125
|
+
return active === null || active === document.body || active === document.documentElement;
|
|
126
|
+
};
|
|
127
|
+
const holdIt = () => {
|
|
128
|
+
if (onNothing())
|
|
129
|
+
dialog.current?.focus({ preventScroll: true });
|
|
130
|
+
};
|
|
131
|
+
const watch = (event) => {
|
|
132
|
+
if (event.relatedTarget === null)
|
|
133
|
+
setTimeout(holdIt, 0);
|
|
134
|
+
};
|
|
135
|
+
document.addEventListener("focusout", watch, true);
|
|
136
|
+
const sweep = setInterval(holdIt, 250);
|
|
137
|
+
const stopSweep = setTimeout(() => clearInterval(sweep), 3000);
|
|
138
|
+
return () => {
|
|
139
|
+
document.removeEventListener("focusout", watch, true);
|
|
140
|
+
clearInterval(sweep);
|
|
141
|
+
clearTimeout(stopSweep);
|
|
142
|
+
const active = document.activeElement;
|
|
143
|
+
const onNothing = active === null || active === document.body || dialog.current?.contains(active);
|
|
144
|
+
if (onNothing && opener?.isConnected)
|
|
145
|
+
opener.focus({ preventScroll: true });
|
|
146
|
+
else if (onNothing)
|
|
147
|
+
setTimeout(() => {
|
|
148
|
+
// The opener went with the menu it was in: the profile button that opened that.
|
|
149
|
+
document.querySelector('[data-testid="profile-button"]')?.focus({ preventScroll: true });
|
|
150
|
+
}, 0);
|
|
151
|
+
};
|
|
152
|
+
}, []);
|
|
153
|
+
const views = useMemo(() => studioViews(app), [app]);
|
|
154
|
+
/*
|
|
155
|
+
* Re-read on every change rather than cached: the checker is cheap, the
|
|
156
|
+
* declaration is small, and a verdict that can go stale is a verdict
|
|
157
|
+
* nobody should trust. The store's own subscription is what says a change
|
|
158
|
+
* happened — an act taken from the strip, from the keyboard, from an
|
|
159
|
+
* agent's seat or from an undo all arrive the same way.
|
|
160
|
+
*/
|
|
161
|
+
const turn = useStoreTick(studio.store);
|
|
162
|
+
const verdict = useMemo(() => studio.check(), [studio, turn]);
|
|
163
|
+
const [applied, setApplied] = useState(null);
|
|
164
|
+
const door = useStudioDoor();
|
|
165
|
+
const [calls, setCalls] = useState(NO_CALLS);
|
|
166
|
+
const noteCall = useCallback((call) => {
|
|
167
|
+
setCalls((current) => {
|
|
168
|
+
const settling = call.phase !== "running" && current[0]?.name === call.name && current[0]?.at === call.at;
|
|
169
|
+
return [call, ...(settling ? current.slice(1) : current)].slice(0, 12);
|
|
170
|
+
});
|
|
171
|
+
}, []);
|
|
172
|
+
return (_jsx(GraviewProvider, { store: studio.store, views: views, scheme: scheme, principal: principal, ...(brand ? { brand } : {}), initialView: AT_ALTITUDE, children: _jsxs("div", { ref: dialog, "data-testid": "studio", "data-graview-speaks-ids": "", tabIndex: -1, role: "dialog", "aria-modal": "true", "aria-label": `Studio · ${app.name}`,
|
|
173
|
+
/*
|
|
174
|
+
* ESCAPE CLOSES THE INNERMOST THING.
|
|
175
|
+
*
|
|
176
|
+
* The studio's own rail and any other popover in it already close on
|
|
177
|
+
* Escape; this closed the WHOLE STUDIO at the same time, so opening
|
|
178
|
+
* the history and pressing Escape to dismiss it threw away the studio
|
|
179
|
+
* around it. Anything marked as an overlay inside gets the press
|
|
180
|
+
* first, and the studio takes the next one.
|
|
181
|
+
*/
|
|
182
|
+
onKeyDown: (event) => {
|
|
183
|
+
if (event.key !== "Escape")
|
|
184
|
+
return;
|
|
185
|
+
if (event.currentTarget.querySelector("[data-graview-overlay]"))
|
|
186
|
+
return;
|
|
187
|
+
onClose();
|
|
188
|
+
}, style: {
|
|
189
|
+
position: within === "page" ? "fixed" : "absolute",
|
|
190
|
+
inset: 0,
|
|
191
|
+
zIndex: 40,
|
|
192
|
+
display: "flex",
|
|
193
|
+
flexDirection: "column",
|
|
194
|
+
background: "var(--graview-ground-deep)",
|
|
195
|
+
}, children: [_jsxs("header", { style: {
|
|
196
|
+
display: "flex",
|
|
197
|
+
alignItems: "center",
|
|
198
|
+
flexWrap: "wrap",
|
|
199
|
+
gap: 12,
|
|
200
|
+
rowGap: 6,
|
|
201
|
+
padding: "6px 18px",
|
|
202
|
+
minHeight: 49,
|
|
203
|
+
boxSizing: "border-box",
|
|
204
|
+
flex: "0 0 auto",
|
|
205
|
+
borderBottom: "1px solid var(--graview-edge)",
|
|
206
|
+
background: "var(--graview-bar)",
|
|
207
|
+
}, children: [_jsx("strong", { style: { fontSize: "0.9375rem", fontWeight: 550 }, children: "Studio" }), _jsx("span", { style: { fontSize: "0.875rem", color: "var(--graview-ink-muted)" }, children: app.name }), _jsx(Places, {}), _jsx("span", { "data-testid": "studio-verdict", "data-errors": verdict.errors, "data-warnings": verdict.warnings, style: {
|
|
208
|
+
marginLeft: "auto",
|
|
209
|
+
fontSize: "0.875rem",
|
|
210
|
+
color: verdict.errors > 0 ? "var(--graview-warn)" : "var(--graview-ink-muted)",
|
|
211
|
+
}, children: said(verdict) }), _jsx(StudioAgentPanel, { studio: studio }), _jsx(ActivityRail, { calls: calls, seat: _jsx(StudioSeat, { studio: studio, onCall: noteCall }) }), _jsx("button", { type: "button", "data-testid": "studio-apply", onClick: () => {
|
|
212
|
+
const result = studio.apply();
|
|
213
|
+
setApplied(result.ok
|
|
214
|
+
? { ok: true, files: studio.files(), migration: result.migration?.title ?? null, door: door !== null }
|
|
215
|
+
: { ok: false, check: result.check });
|
|
216
|
+
}, style: { padding: "3px 11px", fontSize: "0.875rem" }, children: "Apply" }), _jsx("button", { type: "button", "data-testid": "studio-close", onClick: onClose, "aria-label": "Close the studio", style: { padding: "3px 11px", fontSize: "0.875rem" }, children: "Close" })] }), applied ? _jsx(Written, { applied: applied, studio: studio, onDismiss: () => setApplied(null) }) : null, _jsxs("main", { style: { position: "relative", flex: "1 1 auto", minHeight: 0, containerType: "size" }, children: [_jsx(Scene, { renderer: "dom" }), _jsx(Inspector, {})] })] }) }));
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* The studio OPENS FROM ALTITUDE: a declaration's first honest picture is
|
|
220
|
+
* the map of what it declares — kinds, acts, rules, roles — as districts,
|
|
221
|
+
* rather than one of them chosen arbitrarily.
|
|
222
|
+
*/
|
|
223
|
+
const AT_ALTITUDE = { ...EMPTY_VIEW, overview: true };
|
|
224
|
+
/** The studio has no agent turns of its own yet; the rail is here for the history. */
|
|
225
|
+
const NO_CALLS = [];
|
|
226
|
+
/**
|
|
227
|
+
* WHAT APPLYING ACTUALLY GIVES YOU.
|
|
228
|
+
*
|
|
229
|
+
* On errors, the findings — each naming the thing to change, because the
|
|
230
|
+
* checker's messages are written for somebody editing the declaration. On
|
|
231
|
+
* success, with the dev server's studio door open, the change written into
|
|
232
|
+
* the checkout's own files. Without it — a deployed app, or a change the
|
|
233
|
+
* studio cannot yet write in place, each reason said — the files `graview
|
|
234
|
+
* create` would write, as downloads: a browser cannot write your checkout,
|
|
235
|
+
* and a button that claimed to would be the one lie in a flow whose whole
|
|
236
|
+
* point is that nothing is hidden.
|
|
237
|
+
*/
|
|
238
|
+
function Written({ applied, studio, onDismiss, }) {
|
|
239
|
+
return (_jsxs("section", { "data-testid": "studio-applied", "aria-label": applied.ok ? "What the studio wrote" : "What the checker refused", style: {
|
|
240
|
+
flex: "0 0 auto",
|
|
241
|
+
display: "grid",
|
|
242
|
+
gap: 8,
|
|
243
|
+
padding: "10px 18px",
|
|
244
|
+
borderBottom: "1px solid var(--graview-edge)",
|
|
245
|
+
background: applied.ok ? "var(--graview-panel)" : "var(--graview-panel-warning)",
|
|
246
|
+
}, children: [applied.ok && applied.door ? (_jsx(InPlaceWriter, { studio: studio, migration: applied.migration, files: applied.files })) : applied.ok ? (_jsxs(_Fragment, { children: [_jsxs("strong", { style: { fontSize: "0.875rem", fontWeight: 550 }, children: ["The checker is happy. ", applied.files.length, " file", applied.files.length === 1 ? "" : "s", " to write", applied.migration ? `, and a migration: ${applied.migration}` : ", and no migration needed", "."] }), _jsx("span", { style: { fontSize: "0.8125rem", color: "var(--graview-ink-muted)" }, children: "A browser cannot write your checkout. Run the app with the studio door (studioDoor() from @graview/ship/dev) and Apply writes the change in place." }), _jsx(Downloads, { files: applied.files })] })) : (_jsxs(_Fragment, { children: [_jsxs("strong", { style: { fontSize: "0.875rem", fontWeight: 550, color: "var(--graview-warn)" }, children: ["Not applied \u2014 ", applied.check.errors, " error", applied.check.errors === 1 ? "" : "s", " in the declaration as it stands."] }), _jsx("ul", { style: { margin: 0, paddingLeft: 18, display: "grid", gap: 4 }, children: applied.check.findings
|
|
247
|
+
.filter((finding) => finding.severity === "error")
|
|
248
|
+
.slice(0, 6)
|
|
249
|
+
.map((finding) => (_jsxs("li", { style: { fontSize: "0.875rem" }, children: [_jsx("code", { children: finding.where }), " \u2014 ", finding.message, " ", _jsx("em", { children: finding.fix })] }, `${finding.code}:${finding.where}`))) })] })), _jsx("button", { type: "button", onClick: onDismiss, style: { justifySelf: "start", padding: "3px 10px", fontSize: "0.8125rem" }, children: "Dismiss" })] }));
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* AN AGENT SEAT IN THE STUDIO — and the thing it is actually good for.
|
|
253
|
+
*
|
|
254
|
+
* A rule that says what is wrong without naming what puts it right is a
|
|
255
|
+
* rule the interface can only complain about: no repair in the strip, no
|
|
256
|
+
* repair in the menu, nothing an agent may lawfully do about it. That is
|
|
257
|
+
* the framework's own central seam, left unconnected. Finding the rules in
|
|
258
|
+
* this state, and the act that plausibly repairs each, is a derivation over
|
|
259
|
+
* the declaration graph — no model, no prompt.
|
|
260
|
+
*
|
|
261
|
+
* Every proposal is an ordinary act under the AGENT's own name, in a batch
|
|
262
|
+
* of its own, so the trail beside it says who did it and one press takes it
|
|
263
|
+
* back. Keeping is doing nothing; declining is undo. That is the whole
|
|
264
|
+
* review mechanism, and it is the same one a person's own changes get.
|
|
265
|
+
*/
|
|
266
|
+
function StudioSeat({ studio, onCall, }) {
|
|
267
|
+
const { principal } = useGraview();
|
|
268
|
+
const unrepaired = useMemo(() => unnamedRepairs(studio), [studio, studio.store.batches().length]);
|
|
269
|
+
return (_jsx(AgentSeat, { who: "studio", testId: "studio-seat", count: unrepaired.length, gate: "name-repair", label: (n) => `Name a repair for ${n} rule${n === 1 ? "" : "s"}`, busyLabel: "Reading the declaration\u2026", idle: "Every rule names what puts it right", onCall: onCall, run: async () => {
|
|
270
|
+
for (const { rule, act, why } of unnamedRepairs(studio)) {
|
|
271
|
+
studio.propose({ name: "name-repair", args: { rule, act } }, { kind: "agent", id: "studio", session: "ui", ...(principal.roles ? { roles: principal.roles } : {}) }, why);
|
|
272
|
+
}
|
|
273
|
+
} }));
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* The rules that name no repair, each with the act that plausibly puts it
|
|
277
|
+
* right: an act whose subject is the kind the rule judges. Read off the
|
|
278
|
+
* declaration graph, so the seat proposes something the checker and the
|
|
279
|
+
* store would both accept rather than something a model imagined.
|
|
280
|
+
*/
|
|
281
|
+
function unnamedRepairs(studio) {
|
|
282
|
+
const graph = studio.store.graph;
|
|
283
|
+
const named = new Set(graph.allEdges().filter((edge) => edge.kind === "repairs").map((edge) => edge.from));
|
|
284
|
+
const found = [];
|
|
285
|
+
for (const rule of graph.allNodes().filter((node) => node.kind === "rule")) {
|
|
286
|
+
if (named.has(rule.id))
|
|
287
|
+
continue;
|
|
288
|
+
const judged = graph.out(rule.id, "judges").map((kind) => kind.id);
|
|
289
|
+
if (judged.length === 0)
|
|
290
|
+
continue;
|
|
291
|
+
const act = graph
|
|
292
|
+
.allNodes()
|
|
293
|
+
.filter((node) => node.kind === "act")
|
|
294
|
+
.find((candidate) => graph.out(candidate.id, "on").some((kind) => judged.includes(kind.id)));
|
|
295
|
+
if (!act)
|
|
296
|
+
continue;
|
|
297
|
+
const say = (node) => String(node["label"] ?? node.id);
|
|
298
|
+
found.push({
|
|
299
|
+
rule: rule.id,
|
|
300
|
+
act: act.id,
|
|
301
|
+
why: `"${say(rule)}" names no repair; "${say(act)}" acts on what it judges`,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
return found;
|
|
305
|
+
}
|
|
306
|
+
/** The default views over the meta-schema, plus the checker's own place. */
|
|
307
|
+
function studioViews(app) {
|
|
308
|
+
const meta = studioApp();
|
|
309
|
+
const check = createStudioLens(app);
|
|
310
|
+
return registerDefaultViews(meta.schema, createViews(meta.schema))
|
|
311
|
+
.register("kind", { cardinality: "many", fidelity: "full" }, check.View, {
|
|
312
|
+
title: "What the checker says",
|
|
313
|
+
})
|
|
314
|
+
.register("kind", { cardinality: "many", fidelity: "summary" }, check.View, {
|
|
315
|
+
title: "What the checker says",
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
function said(verdict) {
|
|
319
|
+
if (verdict.errors === 0 && verdict.warnings === 0)
|
|
320
|
+
return "The checker finds nothing wrong";
|
|
321
|
+
const parts = [];
|
|
322
|
+
if (verdict.errors > 0)
|
|
323
|
+
parts.push(`${verdict.errors} error${verdict.errors === 1 ? "" : "s"}`);
|
|
324
|
+
if (verdict.warnings > 0)
|
|
325
|
+
parts.push(`${verdict.warnings} warning${verdict.warnings === 1 ? "" : "s"}`);
|
|
326
|
+
return parts.join(" · ");
|
|
327
|
+
}
|
|
328
|
+
//# sourceMappingURL=place.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"place.js","sourceRoot":"","sources":["../src/place.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { DeclarationChange } from "@graview/core";
|
|
2
|
+
import type { Completion } from "@graview/tools";
|
|
3
|
+
import type { Rewrite } from "./changes.js";
|
|
4
|
+
/**
|
|
5
|
+
* AN ACT OR A RULE, REWRITTEN FOR THE DECLARATION IT NOW SERVES.
|
|
6
|
+
*
|
|
7
|
+
* The one piece of an app the studio cannot derive is a body: what an act
|
|
8
|
+
* actually does, what a rule actually judges. When a change leaves one of
|
|
9
|
+
* them written for a declaration that has moved on, a model is a fair
|
|
10
|
+
* first draft — given the code as it is, what changed and why the code is
|
|
11
|
+
* affected — and the draft is the person's to read, correct or refuse
|
|
12
|
+
* before a byte is written, and the compiler's to judge after.
|
|
13
|
+
*/
|
|
14
|
+
export interface RewriteAsk extends Rewrite {
|
|
15
|
+
/** The declaration object as the checkout writes it now: `{ title: …, apply(ctx, args) { … } }`. */
|
|
16
|
+
readonly text: string;
|
|
17
|
+
readonly changes: readonly DeclarationChange[];
|
|
18
|
+
/** The kinds as they will be, when the door could say: what the new code is written against. */
|
|
19
|
+
readonly schema?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function rewriteCode(complete: Completion, ask: RewriteAsk): Promise<string>;
|
|
22
|
+
/**
|
|
23
|
+
* The object out of whatever a model wrapped it in: a fence, a sentence
|
|
24
|
+
* before it, the call it was asked to leave off. From the first `{` to the
|
|
25
|
+
* `}` that closes it, counted, so a brace in a string does not end it early.
|
|
26
|
+
*/
|
|
27
|
+
export declare function theObject(answer: string): string;
|
|
28
|
+
//# sourceMappingURL=rewrite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rewrite.d.ts","sourceRoot":"","sources":["../src/rewrite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C;;;;;;;;;GASG;AACH,MAAM,WAAW,UAAW,SAAQ,OAAO;IACzC,oGAAoG;IACpG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC/C,gGAAgG;IAChG,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAQD,wBAAsB,WAAW,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAaxF;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAoBhD"}
|
package/dist/rewrite.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const HOW = `You are rewriting one declaration in a TypeScript app built on Graview, a typed context-graph framework.
|
|
2
|
+
An act is declared as defineMutation(name, { title, description, subject, creates, connects, severs, writes, input: z.object({ … }), describe(args, graph), apply(ctx, args) { … } }).
|
|
3
|
+
In apply, ctx.addNode, ctx.patchNode, ctx.removeNode, ctx.addEdge({ kind, from, to }) and ctx.removeEdge change the graph; ctx.graph.out(id, edgeKind) and ctx.graph.in(id, edgeKind) read it. An edge is declared on the kind at its "from" end.
|
|
4
|
+
A rule is declared as defineInvariant(name, { scope, label, description, repairs, evaluate({ graph, subject }) { … return violations } }).
|
|
5
|
+
The app's declaration has changed, and the declaration below was written for the old one.`;
|
|
6
|
+
export async function rewriteCode(complete, ask) {
|
|
7
|
+
const prompt = [
|
|
8
|
+
HOW,
|
|
9
|
+
`The ${ask.sort} "${ask.name}" as it is written now:\n${ask.text}`,
|
|
10
|
+
`What changed in the declaration:\n${ask.changes.map((change) => `- ${JSON.stringify(change)}`).join("\n")}`,
|
|
11
|
+
`Why this ${ask.sort} is affected: ${ask.why}`,
|
|
12
|
+
ask.schema ? `The kinds as they will be:\n${ask.schema}` : "",
|
|
13
|
+
`Rewrite the object so it is true of the new declaration. Keep its name, its title, its words and everything that is still right; change only what the change requires. Keep the comments that are still true.
|
|
14
|
+
Answer with ONLY the object, from its opening { to its closing } — no defineMutation(…) around it, no explanation, no code fence.`,
|
|
15
|
+
]
|
|
16
|
+
.filter(Boolean)
|
|
17
|
+
.join("\n\n");
|
|
18
|
+
return theObject(await complete(prompt));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The object out of whatever a model wrapped it in: a fence, a sentence
|
|
22
|
+
* before it, the call it was asked to leave off. From the first `{` to the
|
|
23
|
+
* `}` that closes it, counted, so a brace in a string does not end it early.
|
|
24
|
+
*/
|
|
25
|
+
export function theObject(answer) {
|
|
26
|
+
const text = answer.replace(/```[a-z]*\n?/gi, "");
|
|
27
|
+
const start = text.indexOf("{");
|
|
28
|
+
if (start < 0)
|
|
29
|
+
throw new Error("The model answered with no object to use.");
|
|
30
|
+
let depth = 0;
|
|
31
|
+
let quote = null;
|
|
32
|
+
for (let at = start; at < text.length; at++) {
|
|
33
|
+
const char = text[at];
|
|
34
|
+
if (quote) {
|
|
35
|
+
if (char === "\\")
|
|
36
|
+
at++;
|
|
37
|
+
else if (char === quote)
|
|
38
|
+
quote = null;
|
|
39
|
+
}
|
|
40
|
+
else if (char === '"' || char === "'" || char === "`") {
|
|
41
|
+
quote = char;
|
|
42
|
+
}
|
|
43
|
+
else if (char === "{") {
|
|
44
|
+
depth++;
|
|
45
|
+
}
|
|
46
|
+
else if (char === "}" && --depth === 0) {
|
|
47
|
+
return text.slice(start, at + 1);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
throw new Error("The model's answer never closed the object it opened.");
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=rewrite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rewrite.js","sourceRoot":"","sources":["../src/rewrite.ts"],"names":[],"mappings":"AAsBA,MAAM,GAAG,GAAG;;;;0FAI8E,CAAC;AAE3F,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAoB,EAAE,GAAe;IACrE,MAAM,MAAM,GAAG;QACb,GAAG;QACH,OAAO,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,4BAA4B,GAAG,CAAC,IAAI,EAAE;QAClE,qCAAqC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QAC5G,YAAY,GAAG,CAAC,IAAI,iBAAiB,GAAG,CAAC,GAAG,EAAE;QAC9C,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,+BAA+B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE;QAC7D;kIAC8H;KAC/H;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,MAAM,CAAC,CAAC;IAChB,OAAO,SAAS,CAAC,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,MAAc;IACtC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,KAAK,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC5E,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,KAAK,GAAkB,IAAI,CAAC;IAChC,KAAK,IAAI,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAE,CAAC;QACvB,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,IAAI,KAAK,IAAI;gBAAE,EAAE,EAAE,CAAC;iBACnB,IAAI,IAAI,KAAK,KAAK;gBAAE,KAAK,GAAG,IAAI,CAAC;QACxC,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACxD,KAAK,GAAG,IAAI,CAAC;QACf,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACxB,KAAK,EAAE,CAAC;QACV,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,IAAI,EAAE,KAAK,KAAK,CAAC,EAAE,CAAC;YACzC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;AAC3E,CAAC"}
|