@datalayer/agent-runtimes 1.5.89 → 1.5.91
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 +29 -297
- package/dist-embed/datalayer-app-main.js +40 -36
- package/lib/apps/embed/element.js +20 -5
- package/lib/apps/embed/visitorApp.d.ts +23 -45
- package/lib/apps/embed/visitorApp.js +65 -13
- package/lib/components/teams/A2ATeamGraph.d.ts +58 -152
- package/lib/components/teams/A2ATeamGraph.js +169 -410
- package/lib/components/teams/SceneTranscript.d.ts +5 -1
- package/lib/components/teams/SceneTranscript.js +2 -2
- package/lib/components/teams/SceneView.d.ts +17 -5
- package/lib/components/teams/SceneView.js +7 -3
- package/lib/components/teams/a2aTeamFlow.d.ts +16 -7
- package/lib/components/teams/a2aTeamFlow.js +17 -14
- package/lib/components/teams/backdrops/catalogue.d.ts +35 -0
- package/lib/components/teams/backdrops/catalogue.js +34 -0
- package/lib/components/teams/backdrops/edges.d.ts +20 -0
- package/lib/components/teams/backdrops/edges.js +29 -0
- package/lib/components/teams/backdrops/faces.d.ts +24 -0
- package/lib/components/teams/backdrops/faces.js +39 -0
- package/lib/components/teams/backdrops/halo.d.ts +14 -0
- package/lib/components/teams/backdrops/halo.js +5 -0
- package/lib/components/teams/backdrops/hero.d.ts +14 -0
- package/lib/components/teams/backdrops/hero.js +178 -0
- package/lib/components/teams/backdrops/index.d.ts +22 -0
- package/lib/components/teams/backdrops/index.js +38 -0
- package/lib/components/teams/backdrops/nodes.d.ts +123 -0
- package/lib/components/teams/backdrops/nodes.js +265 -0
- package/lib/components/teams/backdrops/plain.d.ts +14 -0
- package/lib/components/teams/backdrops/plain.js +116 -0
- package/lib/components/teams/backdrops/studio.d.ts +17 -0
- package/lib/components/teams/backdrops/studio.js +122 -0
- package/lib/components/teams/backdrops/theme.d.ts +14 -0
- package/lib/components/teams/backdrops/theme.js +19 -0
- package/lib/components/teams/backdrops/types.d.ts +214 -0
- package/lib/components/teams/backdrops/types.js +5 -0
- package/lib/components/teams/index.d.ts +2 -0
- package/lib/components/teams/index.js +2 -0
- package/lib/components/teams/sceneTranscriptRules.d.ts +32 -1
- package/lib/components/teams/sceneTranscriptRules.js +104 -2
- package/lib/components/teams/transcript/RecordingLabel.d.ts +17 -0
- package/lib/components/teams/transcript/RecordingLabel.js +7 -0
- package/lib/components/teams/transcript/SequenceDiagram.d.ts +39 -0
- package/lib/components/teams/transcript/SequenceDiagram.js +190 -0
- package/lib/components/teams/transcript/TranscriptDetail.d.ts +27 -0
- package/lib/components/teams/transcript/TranscriptDetail.js +48 -0
- package/lib/components/teams/transcript/TranscriptTable.d.ts +23 -0
- package/lib/components/teams/transcript/TranscriptTable.js +112 -0
- package/lib/components/teams/transcript/TranscriptViews.d.ts +66 -0
- package/lib/components/teams/transcript/TranscriptViews.js +135 -0
- package/lib/components/teams/transcript/TranscriptViewsTypes.d.ts +13 -0
- package/lib/components/teams/transcript/TranscriptViewsTypes.js +5 -0
- package/lib/components/teams/transcript/index.d.ts +23 -0
- package/lib/components/teams/transcript/index.js +27 -0
- package/lib/components/teams/transcript/recordingPlayback.d.ts +52 -0
- package/lib/components/teams/transcript/recordingPlayback.js +146 -0
- package/lib/components/teams/transcript/selection.d.ts +59 -0
- package/lib/components/teams/transcript/selection.js +79 -0
- package/lib/components/teams/transcript/sequenceDiagramRules.d.ts +35 -0
- package/lib/components/teams/transcript/sequenceDiagramRules.js +158 -0
- package/lib/components/teams/transcript/transcriptDetailRules.d.ts +80 -0
- package/lib/components/teams/transcript/transcriptDetailRules.js +208 -0
- package/lib/components/teams/transcript/transcriptExport.d.ts +31 -0
- package/lib/components/teams/transcript/transcriptExport.js +82 -0
- package/lib/components/teams/transcript/transcriptRows.d.ts +76 -0
- package/lib/components/teams/transcript/transcriptRows.js +187 -0
- package/lib/components/teams/transcript/useSceneRecording.d.ts +45 -0
- package/lib/components/teams/transcript/useSceneRecording.js +96 -0
- package/lib/examples/ScenesExample.js +16 -3
- package/lib/portable/hosts/agentClient.d.ts +8 -0
- package/lib/portable/hosts/agentClient.js +2 -0
- package/lib/portable/hosts/approvalRenderers.d.ts +10 -2
- package/lib/portable/hosts/approvalRenderers.js +81 -2
- package/lib/portable/hosts/contracts.d.ts +1 -0
- package/lib/portable/hosts/contracts.js +2 -0
- package/lib/portable/hosts/contracts.json +56 -2
- package/lib/specs/actions.js +2 -0
- package/lib/specs/apps.d.ts +1 -0
- package/lib/specs/apps.js +219 -0
- package/lib/specs/sceneRecordings.d.ts +14 -0
- package/lib/specs/sceneRecordings.js +12 -0
- package/lib/specs/sceneSchema.js +11 -0
- package/lib/specs/scenes.d.ts +1 -0
- package/lib/specs/scenes.js +159 -0
- package/lib/types/scenes.d.ts +54 -0
- package/package.json +2 -1
- package/scripts/codegen/generate_mcp_servers.py +5 -16
- package/scripts/codegen/generate_scenes.py +80 -0
|
@@ -23,7 +23,11 @@ export type SceneTranscriptProps = {
|
|
|
23
23
|
copy?: boolean;
|
|
24
24
|
/** The clipboard: `navigator.clipboard.writeText` unless a test gives one. */
|
|
25
25
|
writeText?: (text: string) => Promise<void>;
|
|
26
|
+
/** The selected line's key: drawn marked (SCENES S2-03). */
|
|
27
|
+
selected?: string | null;
|
|
28
|
+
/** A line was clicked: its key. */
|
|
29
|
+
onSelect?: (key: string) => void;
|
|
26
30
|
};
|
|
27
31
|
/** The transcript as a list of lines, newest last, with *Copy as text*. */
|
|
28
|
-
export declare function SceneTranscript({ lines, emptyText, maxHeight, copy, writeText, }: SceneTranscriptProps): JSX.Element;
|
|
32
|
+
export declare function SceneTranscript({ lines, emptyText, maxHeight, copy, writeText, selected, onSelect, }: SceneTranscriptProps): JSX.Element;
|
|
29
33
|
export default SceneTranscript;
|
|
@@ -13,7 +13,7 @@ export function useSceneTranscript(tracer, members) {
|
|
|
13
13
|
/** How long *Copied* stays, in milliseconds. */
|
|
14
14
|
const COPIED_MS = 1500;
|
|
15
15
|
/** The transcript as a list of lines, newest last, with *Copy as text*. */
|
|
16
|
-
export function SceneTranscript({ lines, emptyText = 'What the scene says and does shows here, line by line.', maxHeight, copy = true, writeText, }) {
|
|
16
|
+
export function SceneTranscript({ lines, emptyText = 'What the scene says and does shows here, line by line.', maxHeight, copy = true, writeText, selected, onSelect, }) {
|
|
17
17
|
const [copied, setCopied] = useState(false);
|
|
18
18
|
const onCopy = async () => {
|
|
19
19
|
const write = writeText ??
|
|
@@ -27,7 +27,7 @@ export function SceneTranscript({ lines, emptyText = 'What the scene says and do
|
|
|
27
27
|
// The clipboard refused: nothing to say but the text, still on screen.
|
|
28
28
|
}
|
|
29
29
|
};
|
|
30
|
-
return (_jsxs(Box, { "data-scene-transcript": "", "data-scene-lines": lines.length, children: [lines.length === 0 ? (_jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: emptyText })) : (_jsx(Box, { as: "ol", "aria-label": "Transcript", listStyle: "none", m: 0, p: 0, fontSize: 1, sx: maxHeight ? { maxHeight, overflowY: 'auto' } : {}, children: lines.map(line => (_jsxs(Box, { as: "li", "data-transcript-line": line.kind, "data-transcript-from": line.from, "data-transcript-to": line.to, "aria-busy": line.open ? 'true' : undefined, display: "grid", gridTemplateColumns: "auto 1fr", gap: 2, py: 1, borderBottom: "1px solid", borderColor: "border.muted", opacity: line.open ? 0.75 : 1, children: [_jsx(Text, { as: "time", sx: {
|
|
30
|
+
return (_jsxs(Box, { "data-scene-transcript": "", "data-scene-lines": lines.length, children: [lines.length === 0 ? (_jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: emptyText })) : (_jsx(Box, { as: "ol", "aria-label": "Transcript", listStyle: "none", m: 0, p: 0, fontSize: 1, sx: maxHeight ? { maxHeight, overflowY: 'auto' } : {}, children: lines.map(line => (_jsxs(Box, { as: "li", "data-transcript-line": line.kind, "data-transcript-from": line.from, "data-transcript-to": line.to, "aria-busy": line.open ? 'true' : undefined, "aria-selected": onSelect ? selected === line.key : undefined, onClick: onSelect ? () => onSelect(line.key) : undefined, bg: selected === line.key ? 'accent.subtle' : undefined, display: "grid", gridTemplateColumns: "auto 1fr", gap: 2, py: 1, borderBottom: "1px solid", borderColor: "border.muted", opacity: line.open ? 0.75 : 1, sx: onSelect ? { cursor: 'pointer' } : undefined, children: [_jsx(Text, { as: "time", sx: {
|
|
31
31
|
color: 'fg.muted',
|
|
32
32
|
fontFamily: 'mono',
|
|
33
33
|
fontSize: 0,
|
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A scene on a page: its graph (`A2ATeamGraph`) and its transcript
|
|
3
|
-
* ({@link
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* ({@link TranscriptViews}: the lines, the table, the sequence diagram, the
|
|
4
|
+
* drill-down — SCENES S2, S3), one shown at a time behind a *Graph ·
|
|
5
|
+
* Transcript* toggle (A-06). The graph stays mounted while the transcript
|
|
6
|
+
* shows, so that what its members were doing is still there when it comes
|
|
7
|
+
* back.
|
|
6
8
|
*
|
|
7
9
|
* The lines come from the Agent Inspector's tracer the graph's members
|
|
8
10
|
* record into (`tracer`, with the `members` to name them), or are given
|
|
9
|
-
* (`lines`: a finished run's, from its record
|
|
11
|
+
* (`lines`: a finished run's, from its record — a recording, whose
|
|
12
|
+
* drill-down says it has no span to open). *Open in the Inspector* opens
|
|
13
|
+
* the Agent Inspector over the page on the tracer's record.
|
|
10
14
|
*
|
|
11
15
|
* @module components/teams/SceneView
|
|
12
16
|
*/
|
|
13
17
|
import type { JSX, ReactNode } from 'react';
|
|
14
18
|
import type { OtelLiveTracer } from '@datalayer/core/lib/otel/live';
|
|
15
19
|
import type { SceneTranscriptLine, SceneTranscriptMember } from './sceneTranscriptRules';
|
|
20
|
+
import type { TranscriptSelection } from './transcript/selection';
|
|
21
|
+
import type { TranscriptSpanIds } from './transcript/transcriptDetailRules';
|
|
16
22
|
/** Which of the two the scene shows. */
|
|
17
23
|
export type SceneViewChoice = 'graph' | 'transcript';
|
|
18
24
|
export type SceneViewProps = {
|
|
@@ -35,7 +41,13 @@ export type SceneViewProps = {
|
|
|
35
41
|
maxHeight?: number;
|
|
36
42
|
/** Something of the page's beside the toggle: a clock, a line. */
|
|
37
43
|
aside?: ReactNode;
|
|
44
|
+
/** The scene, by id: the transcript's export is named after it. */
|
|
45
|
+
scene?: string;
|
|
46
|
+
/** The selected line changed (SCENES S3-02): the page hands the stage its edge (`selectedEdgeOf`). */
|
|
47
|
+
onSelect?: (selection: TranscriptSelection | null) => void;
|
|
48
|
+
/** The Inspector's page for a span, when the site has one. */
|
|
49
|
+
inspectorHref?: (ids: TranscriptSpanIds) => string | undefined;
|
|
38
50
|
};
|
|
39
51
|
/** The graph and the transcript of a scene, behind a *Graph · Transcript* toggle. */
|
|
40
|
-
export declare function SceneView({ children, members, tracer, lines, defaultView, view, onViewChange, emptyText, maxHeight, aside, }: SceneViewProps): JSX.Element;
|
|
52
|
+
export declare function SceneView({ children, members, tracer, lines, defaultView, view, onViewChange, emptyText, maxHeight, aside, scene, onSelect, inspectorHref, }: SceneViewProps): JSX.Element;
|
|
41
53
|
export default SceneView;
|
|
@@ -2,11 +2,15 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useState } from 'react';
|
|
3
3
|
import { SegmentedControl } from '@primer/react';
|
|
4
4
|
import { Box } from '@datalayer/primer-addons';
|
|
5
|
-
import {
|
|
5
|
+
import { AgentInspectorDialog } from '../inspector/AgentInspectorDialog.js';
|
|
6
|
+
import { useSceneTranscript } from './SceneTranscript.js';
|
|
7
|
+
import { TranscriptViews } from './transcript/TranscriptViews.js';
|
|
6
8
|
const NO_MEMBERS = [];
|
|
7
9
|
/** The graph and the transcript of a scene, behind a *Graph · Transcript* toggle. */
|
|
8
|
-
export function SceneView({ children, members = NO_MEMBERS, tracer, lines, defaultView = 'graph', view, onViewChange, emptyText, maxHeight = 360, aside, }) {
|
|
10
|
+
export function SceneView({ children, members = NO_MEMBERS, tracer, lines, defaultView = 'graph', view, onViewChange, emptyText, maxHeight = 360, aside, scene, onSelect, inspectorHref, }) {
|
|
9
11
|
const [own, setOwn] = useState(defaultView);
|
|
12
|
+
// *Open in the Inspector*: the Agent Inspector over the page, on the tracer's record.
|
|
13
|
+
const [inspecting, setInspecting] = useState(false);
|
|
10
14
|
const shown = view ?? own;
|
|
11
15
|
const choose = (next) => {
|
|
12
16
|
setOwn(next);
|
|
@@ -16,6 +20,6 @@ export function SceneView({ children, members = NO_MEMBERS, tracer, lines, defau
|
|
|
16
20
|
const transcript = lines ?? live;
|
|
17
21
|
return (_jsxs(Box, { "data-scene-view": shown, children: [_jsxs(Box, { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 2, flexWrap: "wrap", mb: 2, children: [_jsxs(SegmentedControl, { "aria-label": "Scene view", size: "small", children: [_jsx(SegmentedControl.Button, { selected: shown === 'graph', onClick: () => choose('graph'), "data-scene-choice": "graph", children: "Graph" }), _jsx(SegmentedControl.Button, { selected: shown === 'transcript', onClick: () => choose('transcript'), "data-scene-choice": "transcript", children: transcript.length
|
|
18
22
|
? `Transcript (${transcript.length})`
|
|
19
|
-
: 'Transcript' })] }), aside] }), _jsx(Box, { hidden: shown !== 'graph', "data-scene-graph": "", children: children }), shown === 'transcript' && (_jsx(
|
|
23
|
+
: 'Transcript' })] }), aside] }), _jsx(Box, { hidden: shown !== 'graph', "data-scene-graph": "", children: children }), shown === 'transcript' && (_jsx(TranscriptViews, { lines: transcript, members: members, tracer: lines ? null : tracer, recorded: Boolean(lines), scene: scene, emptyText: emptyText, maxHeight: maxHeight, onSelect: onSelect, inspectorHref: inspectorHref, onOpenInspector: tracer && !lines ? () => setInspecting(true) : undefined })), inspecting && tracer && (_jsx(AgentInspectorDialog, { tracer: tracer, onClose: () => setInspecting(false) }))] }));
|
|
20
24
|
}
|
|
21
25
|
export default SceneView;
|
|
@@ -65,11 +65,20 @@ export type A2ATeamCall = {
|
|
|
65
65
|
id?: string;
|
|
66
66
|
/** When it started, in milliseconds. */
|
|
67
67
|
started: number;
|
|
68
|
-
/**
|
|
69
|
-
|
|
68
|
+
/**
|
|
69
|
+
* When it ended: its result is shown coming back from the connection
|
|
70
|
+
* until {@link RESULT_SHOWN_MS} after.
|
|
71
|
+
*/
|
|
72
|
+
ended?: number;
|
|
70
73
|
};
|
|
71
|
-
/**
|
|
72
|
-
|
|
74
|
+
/**
|
|
75
|
+
* How long a call's result is shown coming back to the member, in
|
|
76
|
+
* milliseconds: the link to a connection flows like the A2A link, out with
|
|
77
|
+
* the call, back with its result.
|
|
78
|
+
*/
|
|
79
|
+
export declare const RESULT_SHOWN_MS = 1200;
|
|
80
|
+
/** Which way a member's link to a connection carries a call now. */
|
|
81
|
+
export declare function callFlow(call: A2ATeamCall): A2ATeamFlow;
|
|
73
82
|
/**
|
|
74
83
|
* The connection a tool is of: one whose tools name it (a toolset's prefix
|
|
75
84
|
* before the name is allowed, as a host may add one), else one whose
|
|
@@ -85,8 +94,8 @@ export declare function toolWords(tool: string, connection?: A2ATeamConnection):
|
|
|
85
94
|
export declare function toolOwnName(tool: string, connections: A2ATeamConnection[]): string;
|
|
86
95
|
/**
|
|
87
96
|
* The calls running after an event of the peer's (`member`): a call it
|
|
88
|
-
* starts to one of its connections is added; its end marks it ended,
|
|
89
|
-
*
|
|
97
|
+
* starts to one of its connections is added; its end marks it ended, its
|
|
98
|
+
* result coming back, for {@link RESULT_SHOWN_MS} (`holdMs` says when to
|
|
90
99
|
* look again, with {@link pruneCalls}). A new request, an answer or a
|
|
91
100
|
* failure ends them all.
|
|
92
101
|
*/
|
|
@@ -94,5 +103,5 @@ export declare function callsAfter(calls: A2ATeamCall[], event: A2APeerEvent, me
|
|
|
94
103
|
calls: A2ATeamCall[];
|
|
95
104
|
holdMs?: number;
|
|
96
105
|
};
|
|
97
|
-
/** The calls without those
|
|
106
|
+
/** The calls without those whose result has been shown long enough. */
|
|
98
107
|
export declare function pruneCalls(calls: A2ATeamCall[], now: number): A2ATeamCall[];
|
|
@@ -30,8 +30,16 @@ export function flowEnds(flow, entry, peer) {
|
|
|
30
30
|
}
|
|
31
31
|
return undefined;
|
|
32
32
|
}
|
|
33
|
-
/**
|
|
34
|
-
|
|
33
|
+
/**
|
|
34
|
+
* How long a call's result is shown coming back to the member, in
|
|
35
|
+
* milliseconds: the link to a connection flows like the A2A link, out with
|
|
36
|
+
* the call, back with its result.
|
|
37
|
+
*/
|
|
38
|
+
export const RESULT_SHOWN_MS = 1200;
|
|
39
|
+
/** Which way a member's link to a connection carries a call now. */
|
|
40
|
+
export function callFlow(call) {
|
|
41
|
+
return call.ended === undefined ? 'asking' : 'answering';
|
|
42
|
+
}
|
|
35
43
|
/**
|
|
36
44
|
* The connection a tool is of: one whose tools name it (a toolset's prefix
|
|
37
45
|
* before the name is allowed, as a host may add one), else one whose
|
|
@@ -65,8 +73,8 @@ export function toolOwnName(tool, connections) {
|
|
|
65
73
|
}
|
|
66
74
|
/**
|
|
67
75
|
* The calls running after an event of the peer's (`member`): a call it
|
|
68
|
-
* starts to one of its connections is added; its end marks it ended,
|
|
69
|
-
*
|
|
76
|
+
* starts to one of its connections is added; its end marks it ended, its
|
|
77
|
+
* result coming back, for {@link RESULT_SHOWN_MS} (`holdMs` says when to
|
|
70
78
|
* look again, with {@link pruneCalls}). A new request, an answer or a
|
|
71
79
|
* failure ends them all.
|
|
72
80
|
*/
|
|
@@ -96,24 +104,19 @@ export function callsAfter(calls, event, member, connections, now) {
|
|
|
96
104
|
],
|
|
97
105
|
};
|
|
98
106
|
}
|
|
99
|
-
const index = calls.findIndex(call =>
|
|
107
|
+
const index = calls.findIndex(call => call.ended === undefined &&
|
|
100
108
|
call.connection === connection.id &&
|
|
101
109
|
(step.id && call.id ? call.id === step.id : call.tool === step.name));
|
|
102
110
|
if (index < 0) {
|
|
103
111
|
return { calls };
|
|
104
112
|
}
|
|
105
|
-
const call = calls[index];
|
|
106
|
-
const left = call.started + CALL_SHOWN_MS - now;
|
|
107
|
-
if (left <= 0) {
|
|
108
|
-
return { calls: calls.filter((_, at) => at !== index) };
|
|
109
|
-
}
|
|
110
113
|
return {
|
|
111
|
-
calls: calls.map((c, at) => (at === index ? { ...c, ended:
|
|
112
|
-
holdMs:
|
|
114
|
+
calls: calls.map((c, at) => (at === index ? { ...c, ended: now } : c)),
|
|
115
|
+
holdMs: RESULT_SHOWN_MS,
|
|
113
116
|
};
|
|
114
117
|
}
|
|
115
|
-
/** The calls without those
|
|
118
|
+
/** The calls without those whose result has been shown long enough. */
|
|
116
119
|
export function pruneCalls(calls, now) {
|
|
117
|
-
const kept = calls.filter(call =>
|
|
120
|
+
const kept = calls.filter(call => call.ended === undefined || call.ended + RESULT_SHOWN_MS > now);
|
|
118
121
|
return kept.length === calls.length ? calls : kept;
|
|
119
122
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The backdrops by name: the id a scene keeps (`stage.backdrop`, agentspecs'
|
|
3
|
+
* `Backdrop`), the name a chooser shows, and one line of what the stage
|
|
4
|
+
* looks like. Pure — no React, no React Flow — so a chooser, an editor or a
|
|
5
|
+
* test lists them without loading the drawings; `backdrops/index.ts` draws
|
|
6
|
+
* each one.
|
|
7
|
+
*
|
|
8
|
+
* @module components/teams/backdrops/catalogue
|
|
9
|
+
*/
|
|
10
|
+
import type { SceneBackdropId } from '../../../types/scenes';
|
|
11
|
+
/** A backdrop as a chooser offers it. */
|
|
12
|
+
export interface SceneBackdropChoice {
|
|
13
|
+
id: SceneBackdropId;
|
|
14
|
+
/** `Studio`, `Hero`, `Plain`. */
|
|
15
|
+
name: string;
|
|
16
|
+
/** One line of what the stage looks like. */
|
|
17
|
+
description: string;
|
|
18
|
+
}
|
|
19
|
+
/** The three backdrops, in a chooser's order: the drawing every scene had first. */
|
|
20
|
+
export declare const SCENE_BACKDROP_CHOICES: readonly SceneBackdropChoice[];
|
|
21
|
+
/** The backdrop of a scene that says none: every scene written before draws as before. */
|
|
22
|
+
export declare const DEFAULT_SCENE_BACKDROP_ID: SceneBackdropId;
|
|
23
|
+
/** The choice an id names; `studio` for none, and for an id no backdrop has. */
|
|
24
|
+
export declare const sceneBackdropChoice: (id?: string) => SceneBackdropChoice;
|
|
25
|
+
/**
|
|
26
|
+
* The backdrop a stage is drawn with: its scene's `stage.backdrop`, `studio`
|
|
27
|
+
* when the scene says none or one no backdrop has. Every stage reads it
|
|
28
|
+
* here — a card's thumbnail, a stage's page, the home page — so that a
|
|
29
|
+
* scene plays on the same backdrop wherever it plays.
|
|
30
|
+
*/
|
|
31
|
+
export declare const stageBackdropOf: (scene?: {
|
|
32
|
+
stage?: {
|
|
33
|
+
backdrop?: string;
|
|
34
|
+
};
|
|
35
|
+
} | null) => SceneBackdropId;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/** The three backdrops, in a chooser's order: the drawing every scene had first. */
|
|
6
|
+
export const SCENE_BACKDROP_CHOICES = [
|
|
7
|
+
{
|
|
8
|
+
id: 'studio',
|
|
9
|
+
name: 'Studio',
|
|
10
|
+
description: 'Characters with speech balloons; each message flows along its line.',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
id: 'hero',
|
|
14
|
+
name: 'Hero',
|
|
15
|
+
description: 'Round faces on a deep tint, thin lines, and a dot that flies with each message.',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: 'plain',
|
|
19
|
+
name: 'Plain',
|
|
20
|
+
description: 'Boxes and arrows, nothing moves: for a printout or a slide.',
|
|
21
|
+
},
|
|
22
|
+
];
|
|
23
|
+
/** The backdrop of a scene that says none: every scene written before draws as before. */
|
|
24
|
+
export const DEFAULT_SCENE_BACKDROP_ID = 'studio';
|
|
25
|
+
/** The choice an id names; `studio` for none, and for an id no backdrop has. */
|
|
26
|
+
export const sceneBackdropChoice = (id) => SCENE_BACKDROP_CHOICES.find(choice => choice.id === id) ??
|
|
27
|
+
SCENE_BACKDROP_CHOICES[0];
|
|
28
|
+
/**
|
|
29
|
+
* The backdrop a stage is drawn with: its scene's `stage.backdrop`, `studio`
|
|
30
|
+
* when the scene says none or one no backdrop has. Every stage reads it
|
|
31
|
+
* here — a card's thumbnail, a stage's page, the home page — so that a
|
|
32
|
+
* scene plays on the same backdrop wherever it plays.
|
|
33
|
+
*/
|
|
34
|
+
export const stageBackdropOf = (scene) => sceneBackdropChoice(scene?.stage?.backdrop).id;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What every backdrop's edges share: the straight path between two ends,
|
|
3
|
+
* and the arrowhead at the end a message goes to.
|
|
4
|
+
*
|
|
5
|
+
* @module components/teams/backdrops/edges
|
|
6
|
+
*/
|
|
7
|
+
/** A point of the graph. */
|
|
8
|
+
export type Point = {
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
};
|
|
12
|
+
/** The straight path from one end to the other. */
|
|
13
|
+
export declare const straightPath: (source: Point, target: Point) => string;
|
|
14
|
+
/**
|
|
15
|
+
* An arrowhead at the end a message goes to — the target's when `forward`,
|
|
16
|
+
* the source's otherwise — pointing along the edge.
|
|
17
|
+
*/
|
|
18
|
+
export declare function arrowPath(source: Point, target: Point, forward: boolean, length?: number): string;
|
|
19
|
+
/** The middle of an edge, where its words go. */
|
|
20
|
+
export declare const midpoint: (source: Point, target: Point) => Point;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/** The straight path from one end to the other. */
|
|
6
|
+
export const straightPath = (source, target) => `M ${source.x},${source.y} L ${target.x},${target.y}`;
|
|
7
|
+
const ARROW = 9;
|
|
8
|
+
/**
|
|
9
|
+
* An arrowhead at the end a message goes to — the target's when `forward`,
|
|
10
|
+
* the source's otherwise — pointing along the edge.
|
|
11
|
+
*/
|
|
12
|
+
export function arrowPath(source, target, forward, length = ARROW) {
|
|
13
|
+
const tip = forward ? target : source;
|
|
14
|
+
const from = forward ? source : target;
|
|
15
|
+
const span = Math.hypot(tip.x - from.x, tip.y - from.y) || 1;
|
|
16
|
+
// Along the edge, toward the tip; and across it.
|
|
17
|
+
const ax = (tip.x - from.x) / span;
|
|
18
|
+
const ay = (tip.y - from.y) / span;
|
|
19
|
+
const bx = tip.x - ax * length;
|
|
20
|
+
const by = tip.y - ay * length;
|
|
21
|
+
const px = -ay * (length / 1.6);
|
|
22
|
+
const py = ax * (length / 1.6);
|
|
23
|
+
return `M ${tip.x},${tip.y} L ${bx + px},${by + py} L ${bx - px},${by - py} Z`;
|
|
24
|
+
}
|
|
25
|
+
/** The middle of an edge, where its words go. */
|
|
26
|
+
export const midpoint = (source, target) => ({
|
|
27
|
+
x: (source.x + target.x) / 2,
|
|
28
|
+
y: (source.y + target.y) / 2,
|
|
29
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A member's face, as a figure `AssistantStage` draws: its emoji, large;
|
|
3
|
+
* else its character drawn small inside a frame; else its initial. The
|
|
4
|
+
* `hero` backdrop frames it in a ring, the `plain` one in a box — the
|
|
5
|
+
* frame is the backdrop's (`FaceFrame`), the face is the member's.
|
|
6
|
+
*
|
|
7
|
+
* It is an `AssistantCharacter`, so the stage keeps everything it does for
|
|
8
|
+
* a character — the balloon, the menu, the drag, the description *Its
|
|
9
|
+
* avatar: …* — and only the drawing changes.
|
|
10
|
+
*
|
|
11
|
+
* @module components/teams/backdrops/faces
|
|
12
|
+
*/
|
|
13
|
+
import type { CSSProperties } from 'react';
|
|
14
|
+
import type { AssistantCharacter } from '../../../chat/assistant/characters';
|
|
15
|
+
import type { SceneBackdropFace } from './types';
|
|
16
|
+
/** How a backdrop frames a face. */
|
|
17
|
+
export interface FaceFrame {
|
|
18
|
+
/** The figure's id, for the stage. */
|
|
19
|
+
id: string;
|
|
20
|
+
/** The frame's style: its corners, its border, its colours. */
|
|
21
|
+
ring: CSSProperties;
|
|
22
|
+
}
|
|
23
|
+
/** A member's face in a frame, as a character the stage draws. */
|
|
24
|
+
export declare function faceCharacter(member: SceneBackdropFace, frame: FaceFrame): AssistantCharacter;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { shippedAssistantCharacter } from '../../../chat/assistant/catalogue.js';
|
|
3
|
+
/** The character a member's `character` id names, when one does; none for a 3D model or an id the catalogue does not know. */
|
|
4
|
+
function drawnCharacter(member) {
|
|
5
|
+
if (typeof member.character !== 'string') {
|
|
6
|
+
return undefined;
|
|
7
|
+
}
|
|
8
|
+
try {
|
|
9
|
+
return shippedAssistantCharacter(member.character);
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/** A member's face in a frame, as a character the stage draws. */
|
|
16
|
+
export function faceCharacter(member, frame) {
|
|
17
|
+
const inner = member.emoji ? undefined : drawnCharacter(member);
|
|
18
|
+
const initial = member.name.trim().charAt(0).toUpperCase() || '?';
|
|
19
|
+
const Drawing = ({ size, mode, state, }) => (_jsx("span", { "data-scene-face": member.emoji ? 'emoji' : inner ? 'character' : 'initial', style: {
|
|
20
|
+
display: 'flex',
|
|
21
|
+
alignItems: 'center',
|
|
22
|
+
justifyContent: 'center',
|
|
23
|
+
width: size,
|
|
24
|
+
height: size,
|
|
25
|
+
borderRadius: '50%',
|
|
26
|
+
boxSizing: 'border-box',
|
|
27
|
+
overflow: 'hidden',
|
|
28
|
+
fontSize: Math.round(size * (member.emoji ? 0.5 : 0.42)),
|
|
29
|
+
fontWeight: 600,
|
|
30
|
+
lineHeight: 1,
|
|
31
|
+
userSelect: 'none',
|
|
32
|
+
...frame.ring,
|
|
33
|
+
}, children: member.emoji ? (_jsx("span", { "aria-hidden": "true", children: member.emoji })) : inner ? (_jsx(inner.Drawing, { size: Math.round(size * 0.72), mode: mode, state: state })) : (_jsx("span", { "aria-hidden": "true", children: initial })) }));
|
|
34
|
+
return {
|
|
35
|
+
id: frame.id,
|
|
36
|
+
name: `${member.name}’s face`,
|
|
37
|
+
Drawing,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The halo round a selected edge (SCENES S3-02): a wide, faint stroke under
|
|
3
|
+
* the edge, in the backdrop's colour, so the exchange chosen in the
|
|
4
|
+
* transcript is seen on the stage, on every backdrop.
|
|
5
|
+
*
|
|
6
|
+
* @module components/teams/backdrops/halo
|
|
7
|
+
*/
|
|
8
|
+
import type { JSX } from 'react';
|
|
9
|
+
/** A wide, faint stroke under a selected edge's path. */
|
|
10
|
+
export declare function EdgeHalo({ path, color, }: {
|
|
11
|
+
path: string;
|
|
12
|
+
/** The halo's colour: a CSS value, `var(--scene-stage-glow)`. */
|
|
13
|
+
color: string;
|
|
14
|
+
}): JSX.Element;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/** A wide, faint stroke under a selected edge's path. */
|
|
3
|
+
export function EdgeHalo({ path, color, }) {
|
|
4
|
+
return (_jsx("path", { d: path, fill: "none", stroke: color, strokeWidth: 12, strokeLinecap: "round", opacity: 0.35, "data-edge-selected": "" }));
|
|
5
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type Edge, type EdgeProps, type Node, type NodeProps } from '@xyflow/react';
|
|
2
|
+
import type { CallData, ConnectionData, LinkData, MemberData, SceneBackdrop, SceneBackdropLayout } from './types';
|
|
3
|
+
/** The hero's layout: faces closer together than the studio's characters, a smaller ring beside each. */
|
|
4
|
+
export declare const HERO_LAYOUT: SceneBackdropLayout;
|
|
5
|
+
/** A member: its face in a ring, and its name under it. */
|
|
6
|
+
export declare const HeroMemberNode: import("react").NamedExoticComponent<NodeProps<Node<MemberData>>>;
|
|
7
|
+
/** A system: a smaller ring with its mark. */
|
|
8
|
+
export declare const HeroConnectionNode: import("react").NamedExoticComponent<NodeProps<Node<ConnectionData>>>;
|
|
9
|
+
/** The A2A link: a thin line, and the dot that flies along it. */
|
|
10
|
+
export declare const HeroLinkEdge: import("react").NamedExoticComponent<EdgeProps<Edge<LinkData>>>;
|
|
11
|
+
/** A member's link to a system: the same thin line, the dot out with the call and back with its result. */
|
|
12
|
+
export declare const HeroCallEdge: import("react").NamedExoticComponent<EdgeProps<Edge<CallData>>>;
|
|
13
|
+
/** The `hero` backdrop. */
|
|
14
|
+
export declare const HERO_BACKDROP: SceneBackdrop;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
import { BaseEdge, EdgeLabelRenderer, } from '@xyflow/react';
|
|
4
|
+
import { Box } from '@datalayer/primer-addons';
|
|
5
|
+
import { prefersReducedMotion } from '../../../chat/assistant/avatar3dModel.js';
|
|
6
|
+
import { ConnectionNodeBase, MemberNodeBase, } from './nodes.js';
|
|
7
|
+
import { arrowPath, midpoint, straightPath } from './edges.js';
|
|
8
|
+
import { faceCharacter } from './faces.js';
|
|
9
|
+
import { EdgeHalo } from './halo.js';
|
|
10
|
+
import { sceneBackdropChoice } from './catalogue.js';
|
|
11
|
+
const NODE_WIDTH = 160;
|
|
12
|
+
const CONNECTION_WIDTH = 88;
|
|
13
|
+
/** The hero's layout: faces closer together than the studio's characters, a smaller ring beside each. */
|
|
14
|
+
export const HERO_LAYOUT = {
|
|
15
|
+
nodeWidth: NODE_WIDTH,
|
|
16
|
+
gap: 200,
|
|
17
|
+
rowGap: 40,
|
|
18
|
+
// The face, its name and where it runs.
|
|
19
|
+
memberHeight: size => size + 50,
|
|
20
|
+
connectionScale: 0.5,
|
|
21
|
+
connectionWidth: CONNECTION_WIDTH,
|
|
22
|
+
connectionGap: 120,
|
|
23
|
+
connectionsApart: 14,
|
|
24
|
+
connectionHeight: size => size + 50,
|
|
25
|
+
connectionsTop: size => size / 4,
|
|
26
|
+
balloonRoom: 144,
|
|
27
|
+
};
|
|
28
|
+
/** The faces drawn so far, by member: the same figure for the same member. */
|
|
29
|
+
const FACES = new Map();
|
|
30
|
+
/** The member's face in a ring: made once per member, so the figure is not drawn anew. */
|
|
31
|
+
function heroFace(member) {
|
|
32
|
+
const key = `${member.id}\u0000${member.emoji ?? ''}\u0000${typeof member.character === 'string' ? member.character : member.character.url}`;
|
|
33
|
+
let face = FACES.get(key);
|
|
34
|
+
if (!face) {
|
|
35
|
+
face = faceCharacter(member, {
|
|
36
|
+
id: `hero-face-${member.id}`,
|
|
37
|
+
ring: {
|
|
38
|
+
background: 'var(--scene-stage-node)',
|
|
39
|
+
boxShadow: '0 0 0 2px var(--scene-stage-ring), 0 0 28px var(--scene-stage-glow)',
|
|
40
|
+
color: 'var(--scene-stage-fg)',
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
FACES.set(key, face);
|
|
44
|
+
}
|
|
45
|
+
return face;
|
|
46
|
+
}
|
|
47
|
+
const MEMBER_LOOK = {
|
|
48
|
+
width: NODE_WIDTH,
|
|
49
|
+
figure: heroFace,
|
|
50
|
+
name: {
|
|
51
|
+
fontWeight: 600,
|
|
52
|
+
textAlign: 'center',
|
|
53
|
+
color: 'var(--scene-stage-fg)',
|
|
54
|
+
letterSpacing: '0.01em',
|
|
55
|
+
},
|
|
56
|
+
where: {
|
|
57
|
+
fontSize: '11px',
|
|
58
|
+
color: 'var(--scene-stage-muted)',
|
|
59
|
+
textAlign: 'center',
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
const CONNECTION_LOOK = {
|
|
63
|
+
width: CONNECTION_WIDTH,
|
|
64
|
+
mark: busy => ({
|
|
65
|
+
borderRadius: '50%',
|
|
66
|
+
border: '1.5px solid',
|
|
67
|
+
borderColor: busy ? 'var(--scene-stage-dot)' : 'var(--scene-stage-ring)',
|
|
68
|
+
background: 'var(--scene-stage-node)',
|
|
69
|
+
boxShadow: busy ? '0 0 18px var(--scene-stage-glow)' : 'none',
|
|
70
|
+
}),
|
|
71
|
+
markScale: 0.58,
|
|
72
|
+
label: {
|
|
73
|
+
fontWeight: 600,
|
|
74
|
+
fontSize: 1,
|
|
75
|
+
textAlign: 'center',
|
|
76
|
+
color: 'var(--scene-stage-fg)',
|
|
77
|
+
},
|
|
78
|
+
via: {
|
|
79
|
+
fontSize: '10px',
|
|
80
|
+
color: 'var(--scene-stage-muted)',
|
|
81
|
+
textAlign: 'center',
|
|
82
|
+
},
|
|
83
|
+
details: { fontSize: '10px', color: 'var(--scene-stage-muted)' },
|
|
84
|
+
};
|
|
85
|
+
/** A member: its face in a ring, and its name under it. */
|
|
86
|
+
export const HeroMemberNode = memo(function HeroMemberNode(props) {
|
|
87
|
+
return _jsx(MemberNodeBase, { ...props, look: MEMBER_LOOK });
|
|
88
|
+
});
|
|
89
|
+
/** A system: a smaller ring with its mark. */
|
|
90
|
+
export const HeroConnectionNode = memo(function HeroConnectionNode(props) {
|
|
91
|
+
return _jsx(ConnectionNodeBase, { ...props, look: CONNECTION_LOOK });
|
|
92
|
+
});
|
|
93
|
+
/** How long the dot takes from one end to the other, in seconds. */
|
|
94
|
+
const DOT_SECONDS = 1.4;
|
|
95
|
+
/**
|
|
96
|
+
* The dot that flies along the edge: from the source to the target while
|
|
97
|
+
* asking, back while answering, again and again while the flow lasts; a
|
|
98
|
+
* fainter one a little behind it. Under reduced motion, a still dot at
|
|
99
|
+
* the end the message goes to, with an arrowhead.
|
|
100
|
+
*/
|
|
101
|
+
function FlyingDot({ source, target, forward, }) {
|
|
102
|
+
const from = forward ? source : target;
|
|
103
|
+
const to = forward ? target : source;
|
|
104
|
+
if (prefersReducedMotion()) {
|
|
105
|
+
return (_jsxs("g", { "data-scene-dot": "still", children: [_jsx("circle", { cx: to.x, cy: to.y, r: 5, fill: "var(--scene-stage-dot)" }), _jsx("path", { d: arrowPath(source, target, forward, 10), fill: "var(--scene-stage-dot)" })] }));
|
|
106
|
+
}
|
|
107
|
+
const path = straightPath(from, to);
|
|
108
|
+
return (_jsxs("g", { "data-scene-dot": forward ? 'out' : 'back', children: [_jsx("circle", { r: 3.5, fill: "var(--scene-stage-dot)", opacity: 0.45, children: _jsx("animateMotion", { dur: `${DOT_SECONDS}s`, begin: "0.18s", repeatCount: "indefinite", path: path }) }), _jsx("circle", { r: 5, fill: "var(--scene-stage-dot)", className: "scene-hero-dot", children: _jsx("animateMotion", { dur: `${DOT_SECONDS}s`, repeatCount: "indefinite", path: path }) })] }));
|
|
109
|
+
}
|
|
110
|
+
/** The words on an edge: `A2A` faint at rest, the flow's words while it carries a message. */
|
|
111
|
+
function EdgeWords({ at, flowing, children, ...rest }) {
|
|
112
|
+
return (_jsx(EdgeLabelRenderer, { children: _jsx(Box, { className: "nodrag nopan", position: "absolute", transform: `translate(-50%, 10px) translate(${at.x}px, ${at.y}px)`, pointerEvents: "none", textAlign: "center", whiteSpace: "nowrap", fontSize: "11px", fontFamily: "mono", letterSpacing: "0.04em", color: flowing ? 'var(--scene-stage-fg)' : 'var(--scene-stage-muted)', ...rest, children: children }) }));
|
|
113
|
+
}
|
|
114
|
+
/** The A2A link: a thin line, and the dot that flies along it. */
|
|
115
|
+
export const HeroLinkEdge = memo(function HeroLinkEdge({ id, sourceX, sourceY, targetX, targetY, data, }) {
|
|
116
|
+
const flow = data?.flow ?? 'still';
|
|
117
|
+
const source = { x: sourceX, y: sourceY };
|
|
118
|
+
const target = { x: targetX, y: targetY };
|
|
119
|
+
return (_jsxs(_Fragment, { children: [data?.selected && (_jsx(EdgeHalo, { path: straightPath(source, target), color: "var(--scene-stage-glow)" })), _jsx(BaseEdge, { id: id, path: straightPath(source, target), style: {
|
|
120
|
+
stroke: data?.selected
|
|
121
|
+
? 'var(--scene-stage-dot)'
|
|
122
|
+
: 'var(--scene-stage-line)',
|
|
123
|
+
strokeWidth: data?.selected ? 1.5 : 1,
|
|
124
|
+
strokeDasharray: data?.connected ? undefined : '4 6',
|
|
125
|
+
opacity: data?.connected ? 1 : 0.6,
|
|
126
|
+
} }), flow !== 'still' && (_jsx("g", { "data-a2a-edge-flow": flow, children: _jsx(FlyingDot, { source: source, target: target, forward: flow === 'asking' }) })), _jsx(EdgeWords, { at: midpoint(source, target), flowing: flow !== 'still', children: data?.label })] }));
|
|
127
|
+
});
|
|
128
|
+
/** A member's link to a system: the same thin line, the dot out with the call and back with its result. */
|
|
129
|
+
export const HeroCallEdge = memo(function HeroCallEdge({ id, sourceX, sourceY, targetX, targetY, data, }) {
|
|
130
|
+
const flow = data?.flow ?? 'still';
|
|
131
|
+
const source = { x: sourceX, y: sourceY };
|
|
132
|
+
const target = { x: targetX, y: targetY };
|
|
133
|
+
return (_jsxs(_Fragment, { children: [data?.selected && (_jsx(EdgeHalo, { path: straightPath(source, target), color: "var(--scene-stage-glow)" })), _jsx(BaseEdge, { id: id, path: straightPath(source, target), style: {
|
|
134
|
+
stroke: data?.selected
|
|
135
|
+
? 'var(--scene-stage-dot)'
|
|
136
|
+
: 'var(--scene-stage-line)',
|
|
137
|
+
strokeWidth: data?.selected ? 1.5 : 1,
|
|
138
|
+
} }), flow !== 'still' && (_jsx("g", { "data-mcp-edge-call": data?.calling, "data-mcp-edge-flow": flow, children: _jsx(FlyingDot, { source: source, target: target, forward: flow === 'asking' }) })), _jsx(EdgeWords, { at: midpoint(source, target), flowing: flow !== 'still', "data-mcp-edge-label": "", children: data?.label })] }));
|
|
139
|
+
});
|
|
140
|
+
const NODE_TYPES = { member: HeroMemberNode, connection: HeroConnectionNode };
|
|
141
|
+
const EDGE_TYPES = { a2a: HeroLinkEdge, mcp: HeroCallEdge };
|
|
142
|
+
/** The `hero` backdrop. */
|
|
143
|
+
export const HERO_BACKDROP = {
|
|
144
|
+
...sceneBackdropChoice('hero'),
|
|
145
|
+
figure: heroFace,
|
|
146
|
+
nodeTypes: NODE_TYPES,
|
|
147
|
+
edgeTypes: EDGE_TYPES,
|
|
148
|
+
theme: {
|
|
149
|
+
// Deep in both modes: the space the faces float in. The words on it
|
|
150
|
+
// are the stage's own, not the page's, so they read on the tint.
|
|
151
|
+
light: {
|
|
152
|
+
'--scene-stage-bg': '#101a33',
|
|
153
|
+
'--scene-stage-fg': '#f0f4ff',
|
|
154
|
+
'--scene-stage-muted': '#9aa8c7',
|
|
155
|
+
'--scene-stage-line': 'rgba(190, 205, 240, 0.45)',
|
|
156
|
+
'--scene-stage-node': '#1a2747',
|
|
157
|
+
'--scene-stage-ring': 'rgba(190, 205, 240, 0.55)',
|
|
158
|
+
'--scene-stage-dot': '#7cc4ff',
|
|
159
|
+
'--scene-stage-glow': 'rgba(124, 196, 255, 0.35)',
|
|
160
|
+
},
|
|
161
|
+
dark: {
|
|
162
|
+
'--scene-stage-bg': '#070b16',
|
|
163
|
+
'--scene-stage-fg': '#e9eefb',
|
|
164
|
+
'--scene-stage-muted': '#8a97b8',
|
|
165
|
+
'--scene-stage-line': 'rgba(170, 190, 235, 0.4)',
|
|
166
|
+
'--scene-stage-node': '#121a30',
|
|
167
|
+
'--scene-stage-ring': 'rgba(170, 190, 235, 0.5)',
|
|
168
|
+
'--scene-stage-dot': '#8fd0ff',
|
|
169
|
+
'--scene-stage-glow': 'rgba(143, 208, 255, 0.4)',
|
|
170
|
+
},
|
|
171
|
+
sx: {
|
|
172
|
+
background: 'radial-gradient(ellipse at 50% 0%, rgba(124, 196, 255, 0.10), transparent 60%), var(--scene-stage-bg)',
|
|
173
|
+
borderRadius: 2,
|
|
174
|
+
color: 'var(--scene-stage-fg)',
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
layout: HERO_LAYOUT,
|
|
178
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The backdrops a scene's stage is drawn with: `studio`, `hero`, `plain`
|
|
3
|
+
* ({@link SCENE_BACKDROPS}, in a chooser's order), and the one an id
|
|
4
|
+
* names ({@link sceneBackdrop}: `studio` for none, and for an id the
|
|
5
|
+
* graph does not know, said once in the console).
|
|
6
|
+
*
|
|
7
|
+
* @module components/teams/backdrops
|
|
8
|
+
*/
|
|
9
|
+
import type { SceneBackdrop } from './types';
|
|
10
|
+
export type { SceneBackdrop, SceneBackdropFace, SceneBackdropId, SceneBackdropLayout, SceneBackdropTheme, StageSx, } from './types';
|
|
11
|
+
export * from './catalogue';
|
|
12
|
+
export { sceneStageSx } from './theme';
|
|
13
|
+
/** The three backdrops, in a chooser's order: the drawing every scene had first. */
|
|
14
|
+
export declare const SCENE_BACKDROPS: readonly SceneBackdrop[];
|
|
15
|
+
/** The backdrop of a scene that says none: every scene written before draws as before. */
|
|
16
|
+
export declare const DEFAULT_SCENE_BACKDROP: SceneBackdrop;
|
|
17
|
+
/**
|
|
18
|
+
* The backdrop an id names; `studio` for none, and for an id no backdrop
|
|
19
|
+
* has — said once in the console, so a scene with a backdrop the graph does
|
|
20
|
+
* not know still plays.
|
|
21
|
+
*/
|
|
22
|
+
export declare function sceneBackdrop(id?: string): SceneBackdrop;
|