@opengeni/react 7.4.0-canary.36855269964001 → 7.4.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/README.md +3 -48
- package/dist/artifacts-document.js +2 -3
- package/dist/artifacts-presentation.js +2 -3
- package/dist/artifacts-spreadsheet.js +2 -2
- package/dist/artifacts.d.ts +0 -1
- package/dist/artifacts.js +1402 -505
- package/dist/artifacts.js.map +1 -1
- package/dist/{browser-viewer-R6KK5VKR.js → browser-viewer-2E6R2Y4W.js} +4 -4
- package/dist/{chunk-WUISZ3WU.js → chunk-3E2AITTZ.js} +28 -32
- package/dist/{chunk-WUISZ3WU.js.map → chunk-3E2AITTZ.js.map} +1 -1
- package/dist/{chunk-PWUILT2U.js → chunk-5AZSK6MV.js} +2 -2
- package/dist/{chunk-Y2PRMYLC.js → chunk-DUEBTL3N.js} +3 -4
- package/dist/{chunk-Y2PRMYLC.js.map → chunk-DUEBTL3N.js.map} +1 -1
- package/dist/{chunk-7UAMYXJY.js → chunk-KNDIXZN6.js} +18 -25
- package/dist/{chunk-7UAMYXJY.js.map → chunk-KNDIXZN6.js.map} +1 -1
- package/dist/{chunk-P4G6K2E2.js → chunk-L4OSXQ6H.js} +884 -1119
- package/dist/chunk-L4OSXQ6H.js.map +1 -0
- package/dist/{chunk-LLIH7Q4B.js → chunk-S5JQ4R22.js} +19 -47
- package/dist/chunk-S5JQ4R22.js.map +1 -0
- package/dist/{chunk-A4UJB2MM.js → chunk-SEEVCT36.js} +2 -2
- package/dist/{chunk-UXJCQ5GH.js → chunk-UDD6DLLT.js} +1 -6
- package/dist/chunk-UDD6DLLT.js.map +1 -0
- package/dist/chunk-UGMKPUEM.js +299 -0
- package/dist/chunk-UGMKPUEM.js.map +1 -0
- package/dist/{chunk-ZCZHKJKZ.js → chunk-USXVQACU.js} +3 -3
- package/dist/{chunk-VABBF52G.js → chunk-V2ABIVYJ.js} +6 -70
- package/dist/chunk-V2ABIVYJ.js.map +1 -0
- package/dist/{chunk-TVO6GXR6.js → chunk-X4HIN6TV.js} +162 -71
- package/dist/chunk-X4HIN6TV.js.map +1 -0
- package/dist/{chunk-IIDEIBMC.js → chunk-XEJEOAOV.js} +38 -49
- package/dist/chunk-XEJEOAOV.js.map +1 -0
- package/dist/{chunk-ZKLCPBWN.js → chunk-Y3QTZN2F.js} +5 -5
- package/dist/{chunk-73BUNGLF.js → chunk-YZ3YYMOM.js} +1 -1
- package/dist/components/artifacts/editable-artifact-ui.d.ts +1 -2
- package/dist/components/artifacts/index.d.ts +0 -7
- package/dist/components/browser-select-control.d.ts +1 -3
- package/dist/components/message-timeline.d.ts +1 -18
- package/dist/components/open-geni-links.d.ts +0 -16
- package/dist/components/session-conversation.d.ts +1 -20
- package/dist/composer.js +3 -3
- package/dist/{computer-viewer-DJHPSP2J.js → computer-viewer-WMJE6OA3.js} +3 -3
- package/dist/connect.js +6 -7
- package/dist/connect.js.map +1 -1
- package/dist/hooks/latest-question.d.ts +1 -1
- package/dist/index.d.ts +2 -5
- package/dist/index.js +28 -39
- package/dist/index.js.map +1 -1
- package/dist/interaction.js +4 -4
- package/dist/{latest-question-KGCDK3XX.js → latest-question-QB4EUCW5.js} +3 -3
- package/dist/lib/format.d.ts +0 -3
- package/dist/machines.js +2 -2
- package/dist/{markdown-table-layout-QXSLK4BY.js → markdown-table-layout-PFUEZ2U4.js} +5 -37
- package/dist/markdown-table-layout-PFUEZ2U4.js.map +1 -0
- package/dist/{sandbox-files-4PMXDSDV.js → sandbox-files-PXPIZAFG.js} +2 -2
- package/dist/session-ui.d.ts +2 -5
- package/dist/session-ui.js +13 -23
- package/dist/session-ui.js.map +1 -1
- package/dist/session.js +3 -3
- package/dist/sites.js +289 -4
- package/dist/sites.js.map +1 -1
- package/dist/timeline/types.d.ts +1 -7
- package/dist/{timeline-annotation-selection-DMLMM2TX.js → timeline-annotation-selection-ODLVF4OI.js} +1 -6
- package/dist/timeline-annotation-selection-ODLVF4OI.js.map +1 -0
- package/package.json +3 -7
- package/src/artifacts.ts +0 -37
- package/src/components/artifacts/editable-artifact-ui.tsx +1 -3
- package/src/components/artifacts/editable-artifact-workbench.tsx +2 -5
- package/src/components/artifacts/editable-document.tsx +36 -34
- package/src/components/artifacts/editable-presentation.tsx +16 -21
- package/src/components/artifacts/index.ts +0 -41
- package/src/components/browser-select-control.tsx +1 -4
- package/src/components/browser-viewer.tsx +22 -81
- package/src/components/computer-viewer.tsx +23 -51
- package/src/components/markdown-table-layout.ts +5 -49
- package/src/components/markdown.tsx +2 -5
- package/src/components/message-timeline.tsx +434 -515
- package/src/components/open-geni-links.tsx +0 -24
- package/src/components/session-conversation.tsx +20 -131
- package/src/components/timeline-annotation-selection.tsx +0 -7
- package/src/hooks/use-available-models.ts +1 -1
- package/src/index.ts +0 -9
- package/src/lib/format.ts +0 -13
- package/src/session-ui.ts +0 -9
- package/src/timeline/projection.ts +4 -78
- package/src/timeline/types.ts +0 -7
- package/styles/compiled.css +0 -325
- package/dist/chat-interactive-block-VAGABN7J.js +0 -11
- package/dist/chunk-5CVXZA3Y.js +0 -292
- package/dist/chunk-5CVXZA3Y.js.map +0 -1
- package/dist/chunk-B3V6TG77.js +0 -41
- package/dist/chunk-B3V6TG77.js.map +0 -1
- package/dist/chunk-IIDEIBMC.js.map +0 -1
- package/dist/chunk-LLIH7Q4B.js.map +0 -1
- package/dist/chunk-P4G6K2E2.js.map +0 -1
- package/dist/chunk-RAIQYITC.js +0 -1772
- package/dist/chunk-RAIQYITC.js.map +0 -1
- package/dist/chunk-SCOTPE2I.js +0 -589
- package/dist/chunk-SCOTPE2I.js.map +0 -1
- package/dist/chunk-TVO6GXR6.js.map +0 -1
- package/dist/chunk-UXJCQ5GH.js.map +0 -1
- package/dist/chunk-VABBF52G.js.map +0 -1
- package/dist/chunk-WEHMPOXK.js +0 -39
- package/dist/chunk-WEHMPOXK.js.map +0 -1
- package/dist/chunk-XCHWDJ22.js +0 -107
- package/dist/chunk-XCHWDJ22.js.map +0 -1
- package/dist/components/artifacts/artifact-chrome.d.ts +0 -120
- package/dist/components/artifacts/artifact-sandbox.d.ts +0 -27
- package/dist/components/artifacts/chat-interactive-block.d.ts +0 -29
- package/dist/components/artifacts/deferred-chat-media.d.ts +0 -15
- package/dist/components/artifacts/editable-artifact-view.d.ts +0 -46
- package/dist/components/artifacts/latest-task-runner.d.ts +0 -15
- package/dist/components/artifacts/session-artifact-viewer.d.ts +0 -39
- package/dist/components/artifacts/site-view.d.ts +0 -23
- package/dist/components/timeline-pill-geometry.d.ts +0 -6
- package/dist/components/timeline-pill-placement.d.ts +0 -18
- package/dist/components/usage-limit-notice.d.ts +0 -49
- package/dist/components/usage-member-list.d.ts +0 -91
- package/dist/components/usage-meter.d.ts +0 -73
- package/dist/hooks/use-usage.d.ts +0 -40
- package/dist/markdown-table-layout-QXSLK4BY.js.map +0 -1
- package/dist/sandbox-files-4PMXDSDV.js.map +0 -1
- package/dist/timeline/allowance-exhausted-row.d.ts +0 -24
- package/dist/timeline-annotation-selection-DMLMM2TX.js.map +0 -1
- package/dist/timeline-pill-geometry-2G6EK47V.js +0 -73
- package/dist/timeline-pill-geometry-2G6EK47V.js.map +0 -1
- package/dist/usage/allowance-copy.d.ts +0 -25
- package/dist/usage/summary.d.ts +0 -35
- package/dist/usage.d.ts +0 -13
- package/dist/usage.js +0 -1073
- package/dist/usage.js.map +0 -1
- package/src/components/artifacts/artifact-chrome.tsx +0 -413
- package/src/components/artifacts/artifact-sandbox.tsx +0 -185
- package/src/components/artifacts/chat-interactive-block.tsx +0 -260
- package/src/components/artifacts/deferred-chat-media.tsx +0 -67
- package/src/components/artifacts/editable-artifact-view.tsx +0 -187
- package/src/components/artifacts/latest-task-runner.ts +0 -49
- package/src/components/artifacts/session-artifact-viewer.tsx +0 -376
- package/src/components/artifacts/site-view.tsx +0 -116
- package/src/components/timeline-pill-geometry.ts +0 -112
- package/src/components/timeline-pill-placement.ts +0 -81
- package/src/components/usage-limit-notice.tsx +0 -179
- package/src/components/usage-member-list.tsx +0 -792
- package/src/components/usage-meter.tsx +0 -382
- package/src/hooks/use-usage.ts +0 -100
- package/src/timeline/allowance-exhausted-row.tsx +0 -86
- package/src/usage/allowance-copy.ts +0 -64
- package/src/usage/summary.ts +0 -93
- package/src/usage.ts +0 -50
- /package/dist/{browser-viewer-R6KK5VKR.js.map → browser-viewer-2E6R2Y4W.js.map} +0 -0
- /package/dist/{chunk-PWUILT2U.js.map → chunk-5AZSK6MV.js.map} +0 -0
- /package/dist/{chunk-A4UJB2MM.js.map → chunk-SEEVCT36.js.map} +0 -0
- /package/dist/{chunk-ZCZHKJKZ.js.map → chunk-USXVQACU.js.map} +0 -0
- /package/dist/{chunk-ZKLCPBWN.js.map → chunk-Y3QTZN2F.js.map} +0 -0
- /package/dist/{chunk-73BUNGLF.js.map → chunk-YZ3YYMOM.js.map} +0 -0
- /package/dist/{chat-interactive-block-VAGABN7J.js.map → computer-viewer-WMJE6OA3.js.map} +0 -0
- /package/dist/{latest-question-KGCDK3XX.js.map → latest-question-QB4EUCW5.js.map} +0 -0
- /package/dist/{computer-viewer-DJHPSP2J.js.map → sandbox-files-PXPIZAFG.js.map} +0 -0
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ArrowLeftIcon,
|
|
3
|
-
Globe2Icon,
|
|
4
|
-
Maximize2Icon,
|
|
5
|
-
PlugZapIcon,
|
|
6
|
-
RefreshCwIcon,
|
|
7
|
-
SparklesIcon,
|
|
8
|
-
} from "lucide-react";
|
|
9
|
-
import { useLayoutEffect, useRef, useState, type ReactNode } from "react";
|
|
10
|
-
|
|
11
|
-
import { cn } from "../../lib/cn";
|
|
12
|
-
import { ArtifactBadge, ArtifactButton, useArtifactLabels } from "./artifact-chrome";
|
|
13
|
-
import {
|
|
14
|
-
PublishedHtmlArtifactFrame,
|
|
15
|
-
type PublishedHtmlArtifactToolBridge,
|
|
16
|
-
} from "./published-html-artifact-frame";
|
|
17
|
-
|
|
18
|
-
export type ArtifactSandboxProps = {
|
|
19
|
-
html: string;
|
|
20
|
-
height?: number | undefined;
|
|
21
|
-
autoHeight?: boolean | undefined;
|
|
22
|
-
theme?: "light" | "dark" | undefined;
|
|
23
|
-
headerControls?: ReactNode | undefined;
|
|
24
|
-
title: string;
|
|
25
|
-
/** Hide the visible title/icon while retaining the accessible iframe title. */
|
|
26
|
-
showTitle?: boolean | undefined;
|
|
27
|
-
showLiveStatus?: boolean | undefined;
|
|
28
|
-
versionLabel?: string | undefined;
|
|
29
|
-
className?: string | undefined;
|
|
30
|
-
editDisabled?: boolean | undefined;
|
|
31
|
-
onEdit?: (() => void) | undefined;
|
|
32
|
-
toolBridge?: PublishedHtmlArtifactToolBridge | undefined;
|
|
33
|
-
connectedToolCount?: number | undefined;
|
|
34
|
-
sourceFileCount?: number | undefined;
|
|
35
|
-
fill?: boolean | undefined;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* The Site/preview frame chrome shared by the console and embedding hosts:
|
|
40
|
-
* title, version and tool badges, live status, reload, and a full-screen mode
|
|
41
|
-
* that escapes the host's scroll containers through the modal top layer.
|
|
42
|
-
*/
|
|
43
|
-
export function ArtifactSandbox(props: ArtifactSandboxProps) {
|
|
44
|
-
const labels = useArtifactLabels();
|
|
45
|
-
const [reloadKey, setReloadKey] = useState(0);
|
|
46
|
-
const [focused, setFocused] = useState(false);
|
|
47
|
-
const frameRef = useRef<HTMLDialogElement>(null);
|
|
48
|
-
const modalRef = useRef(false);
|
|
49
|
-
useLayoutEffect(() => {
|
|
50
|
-
const frame = frameRef.current;
|
|
51
|
-
if (!frame) return;
|
|
52
|
-
if (focused) {
|
|
53
|
-
// A fixed child of the chat timeline is still clipped and layered by its
|
|
54
|
-
// scroll pane and the sibling workspace dock. The modal top layer escapes
|
|
55
|
-
// both while keeping the live Site iframe mounted in the same DOM node.
|
|
56
|
-
frame.close();
|
|
57
|
-
frame.showModal();
|
|
58
|
-
modalRef.current = true;
|
|
59
|
-
} else if (modalRef.current) {
|
|
60
|
-
frame.close();
|
|
61
|
-
frame.show();
|
|
62
|
-
modalRef.current = false;
|
|
63
|
-
}
|
|
64
|
-
}, [focused]);
|
|
65
|
-
const reload = () => {
|
|
66
|
-
setReloadKey((value) => value + 1);
|
|
67
|
-
};
|
|
68
|
-
return (
|
|
69
|
-
<dialog
|
|
70
|
-
ref={frameRef}
|
|
71
|
-
open
|
|
72
|
-
aria-label={props.title}
|
|
73
|
-
onCancel={(event) => {
|
|
74
|
-
event.preventDefault();
|
|
75
|
-
setFocused(false);
|
|
76
|
-
}}
|
|
77
|
-
className={cn(
|
|
78
|
-
"og-root static m-0 w-full max-h-none max-w-none overflow-hidden rounded-2xl border border-border/80 bg-white p-0 text-left shadow-sm",
|
|
79
|
-
props.className,
|
|
80
|
-
props.fill && "flex min-h-0 flex-col",
|
|
81
|
-
focused &&
|
|
82
|
-
"fixed inset-0 z-50 flex h-dvh w-dvw flex-col rounded-none border-0 bg-surface shadow-none",
|
|
83
|
-
)}
|
|
84
|
-
>
|
|
85
|
-
<div className="flex min-h-12 shrink-0 items-center justify-between gap-3 border-b border-border/80 bg-surface/95 px-3 sm:px-4">
|
|
86
|
-
<div className="flex min-w-0 items-center gap-2.5">
|
|
87
|
-
{focused ? (
|
|
88
|
-
<ArtifactButton
|
|
89
|
-
variant="ghost"
|
|
90
|
-
size="sm"
|
|
91
|
-
className="h-8 shrink-0 px-2"
|
|
92
|
-
onClick={() => setFocused(false)}
|
|
93
|
-
>
|
|
94
|
-
<ArrowLeftIcon className="mr-2 size-3.5" />
|
|
95
|
-
{labels.back}
|
|
96
|
-
</ArtifactButton>
|
|
97
|
-
) : null}
|
|
98
|
-
{!focused && props.showTitle !== false ? (
|
|
99
|
-
<span className="grid size-6 shrink-0 place-items-center rounded-md bg-surface-2 text-fg-muted">
|
|
100
|
-
<Globe2Icon className="size-3.5" />
|
|
101
|
-
</span>
|
|
102
|
-
) : null}
|
|
103
|
-
{props.showTitle !== false && (
|
|
104
|
-
<span className="truncate text-xs font-semibold text-fg">{props.title}</span>
|
|
105
|
-
)}
|
|
106
|
-
{props.headerControls}
|
|
107
|
-
{props.versionLabel ? (
|
|
108
|
-
<ArtifactBadge className="hidden h-5 rounded-md border-border/80 px-1.5 text-2xs font-normal text-fg-muted sm:inline-flex">
|
|
109
|
-
{props.versionLabel}
|
|
110
|
-
</ArtifactBadge>
|
|
111
|
-
) : null}
|
|
112
|
-
{props.connectedToolCount ? (
|
|
113
|
-
<ArtifactBadge
|
|
114
|
-
className="hidden h-5 max-w-40 gap-1 rounded-md border-border/80 px-1.5 text-2xs font-normal text-fg-muted sm:inline-flex"
|
|
115
|
-
title={labels.toolsAvailable(props.connectedToolCount)}
|
|
116
|
-
>
|
|
117
|
-
<PlugZapIcon className="size-3" />
|
|
118
|
-
{labels.toolCount(props.connectedToolCount)}
|
|
119
|
-
</ArtifactBadge>
|
|
120
|
-
) : null}
|
|
121
|
-
{props.sourceFileCount ? (
|
|
122
|
-
<span className="hidden text-2xs text-fg-subtle xl:inline">
|
|
123
|
-
{labels.sourceFileCount(props.sourceFileCount)}
|
|
124
|
-
</span>
|
|
125
|
-
) : null}
|
|
126
|
-
</div>
|
|
127
|
-
<div className="flex shrink-0 items-center gap-1">
|
|
128
|
-
{focused && props.onEdit ? (
|
|
129
|
-
<ArtifactButton
|
|
130
|
-
variant="ghost"
|
|
131
|
-
size="sm"
|
|
132
|
-
className="h-8 px-2"
|
|
133
|
-
disabled={props.editDisabled}
|
|
134
|
-
onClick={props.onEdit}
|
|
135
|
-
>
|
|
136
|
-
<SparklesIcon className="mr-2 size-3.5" />
|
|
137
|
-
<span className="hidden sm:inline">{labels.editWithAgent}</span>
|
|
138
|
-
<span className="sm:hidden">{labels.editShort}</span>
|
|
139
|
-
</ArtifactButton>
|
|
140
|
-
) : null}
|
|
141
|
-
{props.showLiveStatus !== false && (
|
|
142
|
-
<span className="mr-1 hidden items-center gap-1.5 text-2xs font-medium text-fg-muted sm:inline-flex">
|
|
143
|
-
<span className="size-1.5 rounded-full bg-status-success ring-4 ring-status-success/10" />
|
|
144
|
-
{labels.live}
|
|
145
|
-
</span>
|
|
146
|
-
)}
|
|
147
|
-
<ArtifactButton
|
|
148
|
-
variant="ghost"
|
|
149
|
-
size="icon"
|
|
150
|
-
className="size-8 rounded-md text-fg-muted hover:text-fg"
|
|
151
|
-
aria-label={labels.reloadSite}
|
|
152
|
-
onClick={reload}
|
|
153
|
-
>
|
|
154
|
-
<RefreshCwIcon className="size-3.5" />
|
|
155
|
-
</ArtifactButton>
|
|
156
|
-
{!focused ? (
|
|
157
|
-
<ArtifactButton
|
|
158
|
-
variant="ghost"
|
|
159
|
-
size="icon"
|
|
160
|
-
className="size-8 rounded-md text-fg-muted hover:text-fg"
|
|
161
|
-
aria-label={labels.openFullScreen}
|
|
162
|
-
onClick={() => setFocused(true)}
|
|
163
|
-
>
|
|
164
|
-
<Maximize2Icon className="size-3.5" />
|
|
165
|
-
</ArtifactButton>
|
|
166
|
-
) : null}
|
|
167
|
-
</div>
|
|
168
|
-
</div>
|
|
169
|
-
<PublishedHtmlArtifactFrame
|
|
170
|
-
key={reloadKey}
|
|
171
|
-
title={props.title}
|
|
172
|
-
html={props.html}
|
|
173
|
-
autoHeight={Boolean(props.autoHeight && !focused)}
|
|
174
|
-
{...(props.theme ? { theme: props.theme } : {})}
|
|
175
|
-
{...(!focused && props.height ? { style: { height: props.height } } : {})}
|
|
176
|
-
{...(props.toolBridge ? { toolBridge: props.toolBridge } : {})}
|
|
177
|
-
className={cn(
|
|
178
|
-
"block h-[clamp(30rem,62vh,48rem)] w-full border-0 bg-white",
|
|
179
|
-
props.fill && "h-0 min-h-0 flex-1",
|
|
180
|
-
focused && "min-h-0 flex-1",
|
|
181
|
-
)}
|
|
182
|
-
/>
|
|
183
|
-
</dialog>
|
|
184
|
-
);
|
|
185
|
-
}
|
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
import type { OpenGeniClient, ToolGatewayIdentity } from "@opengeni/sdk";
|
|
2
|
-
import { useEffect, useMemo, useState } from "react";
|
|
3
|
-
|
|
4
|
-
import { loadSiteSnapshot } from "../../sites-ui";
|
|
5
|
-
import { useOpenGeniLinkResolver } from "../open-geni-links";
|
|
6
|
-
import {
|
|
7
|
-
ArtifactButton,
|
|
8
|
-
ArtifactLabelsProvider,
|
|
9
|
-
ArtifactSelect,
|
|
10
|
-
useArtifactLabels,
|
|
11
|
-
type ArtifactLabels,
|
|
12
|
-
} from "./artifact-chrome";
|
|
13
|
-
import { ArtifactSandbox } from "./artifact-sandbox";
|
|
14
|
-
import { DeferredChatMedia } from "./deferred-chat-media";
|
|
15
|
-
import { inlineHtmlDocument } from "./inline-html-document";
|
|
16
|
-
import type { PublishedHtmlArtifactToolBridge } from "./published-html-artifact-frame";
|
|
17
|
-
|
|
18
|
-
// Fixed chat viewports keep async Site loads and fragment resize messages from
|
|
19
|
-
// moving the conversation. Full-screen remains available for larger content.
|
|
20
|
-
const INLINE_PREVIEW_HEIGHT = 360;
|
|
21
|
-
const SITE_PREVIEW_HEIGHT = 400;
|
|
22
|
-
const PREVIEW_CHROME_HEIGHT = 50;
|
|
23
|
-
|
|
24
|
-
/** Reads a Site needs to render; the console client, the SDK client, or a proxy. */
|
|
25
|
-
export type SiteSnapshotClient = Pick<
|
|
26
|
-
OpenGeniClient,
|
|
27
|
-
"getWorkspaceArtifact" | "getWorkspaceArtifactHtml"
|
|
28
|
-
> &
|
|
29
|
-
Partial<Pick<OpenGeniClient, "getWorkspaceArtifactContent">>;
|
|
30
|
-
|
|
31
|
-
/** The exact saved Site a tool bridge is pinned to (absent for inline HTML). */
|
|
32
|
-
export type SiteToolScope = {
|
|
33
|
-
artifactId: string;
|
|
34
|
-
siteVersionId: string;
|
|
35
|
-
requestedTools: readonly ToolGatewayIdentity[];
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
/** Host-owned Site API access. Omit it and Sites render without workspace tools. */
|
|
39
|
-
export type SiteToolBridgeFactory = (
|
|
40
|
-
site?: SiteToolScope,
|
|
41
|
-
) => PublishedHtmlArtifactToolBridge | undefined;
|
|
42
|
-
|
|
43
|
-
export type ChatInteractiveBlockProps = {
|
|
44
|
-
workspaceId: string;
|
|
45
|
-
kind: "html" | "site";
|
|
46
|
-
content: string;
|
|
47
|
-
client: SiteSnapshotClient;
|
|
48
|
-
toolBridge?: SiteToolBridgeFactory | undefined;
|
|
49
|
-
theme?: "light" | "dark" | undefined;
|
|
50
|
-
/** Translations for the preview's copy; defaults to English. */
|
|
51
|
-
labels?: Partial<ArtifactLabels> | undefined;
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Inline preview for an assistant `opengeni-html` or `opengeni-site` fence, as
|
|
56
|
-
* the OpenGeni console renders it. "Open Site" goes through the nearest
|
|
57
|
-
* `resolveLink`, so a host decides where a Site opens.
|
|
58
|
-
*/
|
|
59
|
-
export function ChatInteractiveBlock({ labels, ...props }: ChatInteractiveBlockProps) {
|
|
60
|
-
return (
|
|
61
|
-
<ArtifactLabelsProvider labels={labels}>
|
|
62
|
-
<InteractiveBlock {...props} />
|
|
63
|
-
</ArtifactLabelsProvider>
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function InteractiveBlock(props: ChatInteractiveBlockProps) {
|
|
68
|
-
const labels = useArtifactLabels();
|
|
69
|
-
const height =
|
|
70
|
-
(props.kind === "html" ? INLINE_PREVIEW_HEIGHT : SITE_PREVIEW_HEIGHT) + PREVIEW_CHROME_HEIGHT;
|
|
71
|
-
return (
|
|
72
|
-
<DeferredChatMedia
|
|
73
|
-
key={`${props.workspaceId}:${props.kind}:${props.kind === "site" ? props.content : "inline"}`}
|
|
74
|
-
height={height}
|
|
75
|
-
actionLabel={props.kind === "html" ? labels.loadPreview : labels.loadSitePreview}
|
|
76
|
-
>
|
|
77
|
-
<div style={{ height }}>
|
|
78
|
-
<LoadedChatInteractiveBlock {...props} />
|
|
79
|
-
</div>
|
|
80
|
-
</DeferredChatMedia>
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function LoadedChatInteractiveBlock(props: ChatInteractiveBlockProps) {
|
|
85
|
-
const labels = useArtifactLabels();
|
|
86
|
-
if (props.kind === "html") return <InlineHtml {...props} />;
|
|
87
|
-
try {
|
|
88
|
-
const value = JSON.parse(props.content);
|
|
89
|
-
if (
|
|
90
|
-
!value ||
|
|
91
|
-
typeof value.siteId !== "string" ||
|
|
92
|
-
!/^[0-9a-f-]{36}$/i.test(value.siteId) ||
|
|
93
|
-
(value.versionId !== undefined &&
|
|
94
|
-
(typeof value.versionId !== "string" || !/^[0-9a-f-]{36}$/i.test(value.versionId)))
|
|
95
|
-
)
|
|
96
|
-
throw new Error("Invalid Site reference");
|
|
97
|
-
return (
|
|
98
|
-
<SiteEmbed
|
|
99
|
-
key={`${props.workspaceId}:${value.siteId}:${value.versionId ?? "current"}`}
|
|
100
|
-
{...props}
|
|
101
|
-
siteId={value.siteId}
|
|
102
|
-
initialVersionId={value.versionId}
|
|
103
|
-
/>
|
|
104
|
-
);
|
|
105
|
-
} catch {
|
|
106
|
-
return <p role="alert">{labels.siteReferenceInvalid}</p>;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function InlineHtml({ content, toolBridge, theme }: ChatInteractiveBlockProps) {
|
|
111
|
-
const labels = useArtifactLabels();
|
|
112
|
-
const html = useMemo(() => inlineHtmlDocument(content), [content]);
|
|
113
|
-
const bridge = useMemo(() => toolBridge?.(), [toolBridge]);
|
|
114
|
-
return (
|
|
115
|
-
<ArtifactSandbox
|
|
116
|
-
title={labels.preview}
|
|
117
|
-
showTitle={false}
|
|
118
|
-
showLiveStatus={false}
|
|
119
|
-
html={html}
|
|
120
|
-
toolBridge={bridge}
|
|
121
|
-
height={INLINE_PREVIEW_HEIGHT}
|
|
122
|
-
className="h-full"
|
|
123
|
-
fill
|
|
124
|
-
theme={theme}
|
|
125
|
-
/>
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function SiteEmbed(
|
|
130
|
-
props: ChatInteractiveBlockProps & { siteId: string; initialVersionId?: string },
|
|
131
|
-
) {
|
|
132
|
-
const [versionId, setVersionId] = useState(props.initialVersionId);
|
|
133
|
-
return (
|
|
134
|
-
<SiteEmbedContent
|
|
135
|
-
key={versionId ?? "current"}
|
|
136
|
-
{...props}
|
|
137
|
-
versionId={versionId}
|
|
138
|
-
onVersionChange={setVersionId}
|
|
139
|
-
/>
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function SiteEmbedContent({
|
|
144
|
-
workspaceId,
|
|
145
|
-
client,
|
|
146
|
-
toolBridge,
|
|
147
|
-
theme,
|
|
148
|
-
siteId,
|
|
149
|
-
versionId,
|
|
150
|
-
onVersionChange,
|
|
151
|
-
}: ChatInteractiveBlockProps & {
|
|
152
|
-
siteId: string;
|
|
153
|
-
versionId?: string | undefined;
|
|
154
|
-
onVersionChange: (id: string) => void;
|
|
155
|
-
}) {
|
|
156
|
-
const [loaded, setLoaded] = useState<{
|
|
157
|
-
client: SiteSnapshotClient;
|
|
158
|
-
snapshot: Awaited<ReturnType<typeof loadSiteSnapshot>>;
|
|
159
|
-
} | null>(null);
|
|
160
|
-
const snapshot = loaded?.client === client ? loaded.snapshot : null;
|
|
161
|
-
const [error, setError] = useState(false);
|
|
162
|
-
const [retry, setRetry] = useState(0);
|
|
163
|
-
useEffect(() => {
|
|
164
|
-
const abort = new AbortController();
|
|
165
|
-
setError(false);
|
|
166
|
-
setLoaded(null);
|
|
167
|
-
void loadSiteSnapshot(client, workspaceId, siteId, {
|
|
168
|
-
signal: abort.signal,
|
|
169
|
-
...(versionId ? { versionId } : {}),
|
|
170
|
-
})
|
|
171
|
-
.then((value) => {
|
|
172
|
-
if (!abort.signal.aborted) setLoaded({ client, snapshot: value });
|
|
173
|
-
})
|
|
174
|
-
.catch(() => {
|
|
175
|
-
if (!abort.signal.aborted) setError(true);
|
|
176
|
-
});
|
|
177
|
-
return () => abort.abort();
|
|
178
|
-
}, [client, workspaceId, siteId, versionId, retry]);
|
|
179
|
-
const content = snapshot?.content;
|
|
180
|
-
const bridge = useMemo(
|
|
181
|
-
() =>
|
|
182
|
-
content
|
|
183
|
-
? toolBridge?.({
|
|
184
|
-
artifactId: siteId,
|
|
185
|
-
siteVersionId: content.versionId,
|
|
186
|
-
requestedTools: content.requestedTools,
|
|
187
|
-
})
|
|
188
|
-
: undefined,
|
|
189
|
-
[toolBridge, siteId, content],
|
|
190
|
-
);
|
|
191
|
-
const open = useOpenGeniLinkResolver()?.({ kind: "site", artifactId: siteId, workspaceId });
|
|
192
|
-
const labels = useArtifactLabels();
|
|
193
|
-
if (error)
|
|
194
|
-
return (
|
|
195
|
-
<p role="alert">
|
|
196
|
-
{labels.siteLoadFailed}{" "}
|
|
197
|
-
<ArtifactButton size="sm" onClick={() => setRetry((v) => v + 1)}>
|
|
198
|
-
{labels.retry}
|
|
199
|
-
</ArtifactButton>
|
|
200
|
-
</p>
|
|
201
|
-
);
|
|
202
|
-
if (!snapshot) return <p role="status">{labels.loadingSite}</p>;
|
|
203
|
-
if (!content) return <p>{labels.siteUnpublished}</p>;
|
|
204
|
-
return (
|
|
205
|
-
<ArtifactSandbox
|
|
206
|
-
title={snapshot.detail.artifact.title}
|
|
207
|
-
html={content.html}
|
|
208
|
-
toolBridge={bridge}
|
|
209
|
-
height={SITE_PREVIEW_HEIGHT}
|
|
210
|
-
className="h-full"
|
|
211
|
-
fill
|
|
212
|
-
theme={theme}
|
|
213
|
-
headerControls={
|
|
214
|
-
<>
|
|
215
|
-
{/* One published version has nothing to choose; keep the bar for the title. */}
|
|
216
|
-
{snapshot.detail.versions.length > 1 ||
|
|
217
|
-
!snapshot.detail.versions.some((v) => v.id === content.versionId) ? (
|
|
218
|
-
<ArtifactSelect
|
|
219
|
-
aria-label={labels.siteVersion}
|
|
220
|
-
className="bg-transparent text-xs"
|
|
221
|
-
value={content.versionId}
|
|
222
|
-
onChange={(e) => onVersionChange(e.target.value)}
|
|
223
|
-
>
|
|
224
|
-
{!snapshot.detail.versions.some((v) => v.id === content.versionId) && (
|
|
225
|
-
<option value={content.versionId}>{labels.savedVersion}</option>
|
|
226
|
-
)}
|
|
227
|
-
{snapshot.detail.versions.map((v) => (
|
|
228
|
-
<option key={v.id} value={v.id}>
|
|
229
|
-
{labels.version(v.revision)}
|
|
230
|
-
</option>
|
|
231
|
-
))}
|
|
232
|
-
</ArtifactSelect>
|
|
233
|
-
) : null}
|
|
234
|
-
{open?.href ? (
|
|
235
|
-
<a
|
|
236
|
-
className="shrink-0 whitespace-nowrap text-xs underline"
|
|
237
|
-
href={open.href}
|
|
238
|
-
data-og-open-site=""
|
|
239
|
-
>
|
|
240
|
-
{labels.openSite}
|
|
241
|
-
</a>
|
|
242
|
-
) : open?.open ? (
|
|
243
|
-
<button
|
|
244
|
-
type="button"
|
|
245
|
-
className="shrink-0 cursor-pointer whitespace-nowrap text-xs underline"
|
|
246
|
-
data-og-open-site=""
|
|
247
|
-
onClick={() =>
|
|
248
|
-
void Promise.resolve()
|
|
249
|
-
.then(open.open)
|
|
250
|
-
.catch(() => undefined)
|
|
251
|
-
}
|
|
252
|
-
>
|
|
253
|
-
{labels.openSite}
|
|
254
|
-
</button>
|
|
255
|
-
) : null}
|
|
256
|
-
</>
|
|
257
|
-
}
|
|
258
|
-
/>
|
|
259
|
-
);
|
|
260
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { useEffect, useRef, useState, type ReactNode } from "react";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Reserve the chat slot before starting expensive media work. Activation is
|
|
5
|
-
* one-way: scrolling away must not discard an interactive preview's state.
|
|
6
|
-
* The timeline parks at its initial tip in layout effects before this observer
|
|
7
|
-
* is attached, so historical previews above the entry viewport stay dormant.
|
|
8
|
-
*/
|
|
9
|
-
export function DeferredChatMedia({
|
|
10
|
-
children,
|
|
11
|
-
height,
|
|
12
|
-
label,
|
|
13
|
-
actionLabel,
|
|
14
|
-
}: {
|
|
15
|
-
children: ReactNode;
|
|
16
|
-
height: number;
|
|
17
|
-
/** What is loading, as in "Load {label}". */
|
|
18
|
-
label?: string | undefined;
|
|
19
|
-
/** The complete (translated) activation label; overrides `label`. */
|
|
20
|
-
actionLabel?: string | undefined;
|
|
21
|
-
}) {
|
|
22
|
-
const host = useRef<HTMLDivElement>(null);
|
|
23
|
-
const [active, setActive] = useState(false);
|
|
24
|
-
useEffect(() => {
|
|
25
|
-
const node = host.current;
|
|
26
|
-
if (active || !node) return;
|
|
27
|
-
if (typeof IntersectionObserver === "undefined") {
|
|
28
|
-
setActive(true);
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
let disposed = false;
|
|
32
|
-
const observer = new IntersectionObserver(
|
|
33
|
-
(entries) => {
|
|
34
|
-
if (disposed || !entries.some((entry) => entry.isIntersecting)) return;
|
|
35
|
-
setActive(true);
|
|
36
|
-
observer.disconnect();
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
root: node.closest("[data-og-timeline-scroller]"),
|
|
40
|
-
rootMargin: "200px 0px",
|
|
41
|
-
},
|
|
42
|
-
);
|
|
43
|
-
observer.observe(node);
|
|
44
|
-
return () => {
|
|
45
|
-
disposed = true;
|
|
46
|
-
observer.disconnect();
|
|
47
|
-
};
|
|
48
|
-
}, [active]);
|
|
49
|
-
|
|
50
|
-
return (
|
|
51
|
-
<div ref={host} data-chat-media={active ? "active" : "deferred"}>
|
|
52
|
-
{active ? (
|
|
53
|
-
children
|
|
54
|
-
) : (
|
|
55
|
-
<div className="flex w-full items-center justify-center" style={{ height }}>
|
|
56
|
-
<button
|
|
57
|
-
type="button"
|
|
58
|
-
className="rounded-md px-3 py-2 text-sm text-fg-muted hover:text-fg focus-visible:outline-2 focus-visible:outline-ring"
|
|
59
|
-
onClick={() => setActive(true)}
|
|
60
|
-
>
|
|
61
|
-
{actionLabel ?? `Load ${label ?? "media"}`}
|
|
62
|
-
</button>
|
|
63
|
-
</div>
|
|
64
|
-
)}
|
|
65
|
-
</div>
|
|
66
|
-
);
|
|
67
|
-
}
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
import type { EditableArtifactResource } from "@opengeni/sdk/artifacts";
|
|
2
|
-
import {
|
|
3
|
-
createBrowserEditableArtifactSession,
|
|
4
|
-
type CreateBrowserEditableArtifactSessionOptions,
|
|
5
|
-
type EditableArtifactBrowserRuntime,
|
|
6
|
-
type EditableArtifactCacheAuthority,
|
|
7
|
-
type EditableArtifactModality,
|
|
8
|
-
} from "@opengeni/sdk/editable-artifacts";
|
|
9
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
ArtifactLoading,
|
|
13
|
-
ArtifactProblem,
|
|
14
|
-
artifactLoadErrorView,
|
|
15
|
-
useArtifactLabels,
|
|
16
|
-
type ArtifactLoadErrorView,
|
|
17
|
-
} from "./artifact-chrome";
|
|
18
|
-
import { EditableArtifactWorkbenchHost } from "./editable-artifact-workbench";
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* The browser kernels an editor needs, one per modality, plus the host-built
|
|
22
|
-
* Worker URL (for Vite: `@opengeni/sdk/editable-artifacts/worker?worker&url`).
|
|
23
|
-
* Kernels come from `@opengeni/artifact-kernel-wasm-{document,spreadsheet,presentation}`.
|
|
24
|
-
*/
|
|
25
|
-
export type EditableArtifactRuntimes = Readonly<{
|
|
26
|
-
document: Omit<EditableArtifactBrowserRuntime, "workerUrl" | "workerFactory">;
|
|
27
|
-
spreadsheet: Omit<EditableArtifactBrowserRuntime, "workerUrl" | "workerFactory">;
|
|
28
|
-
presentation: Omit<EditableArtifactBrowserRuntime, "workerUrl" | "workerFactory">;
|
|
29
|
-
workerUrl: string;
|
|
30
|
-
applicationOrigin?: string | undefined;
|
|
31
|
-
/** Loopback development only. */
|
|
32
|
-
allowInsecureDevelopmentAssets?: boolean | undefined;
|
|
33
|
-
}>;
|
|
34
|
-
|
|
35
|
-
/** Everything needed to open one artifact for the current principal. */
|
|
36
|
-
export type OpenedEditableArtifact = Readonly<{
|
|
37
|
-
artifact: EditableArtifactResource;
|
|
38
|
-
authority: EditableArtifactCacheAuthority;
|
|
39
|
-
replicaId: string;
|
|
40
|
-
}>;
|
|
41
|
-
|
|
42
|
-
export type EditableArtifactViewProps = Readonly<{
|
|
43
|
-
/** Absolute API (or session proxy) base the live transport talks to. */
|
|
44
|
-
baseUrl: URL;
|
|
45
|
-
workspaceId: string;
|
|
46
|
-
artifactId: string;
|
|
47
|
-
/** Resolve metadata, cache authority, and replica; called again on retry. */
|
|
48
|
-
open: (signal: AbortSignal) => Promise<OpenedEditableArtifact>;
|
|
49
|
-
runtimes: EditableArtifactRuntimes;
|
|
50
|
-
transport?: CreateBrowserEditableArtifactSessionOptions["transport"];
|
|
51
|
-
/** Show the editor's own title header (hosts with their own header hide it). */
|
|
52
|
-
showHeader?: boolean | undefined;
|
|
53
|
-
/** Re-open when this changes (for example the host's credential version). */
|
|
54
|
-
authorityKey?: string | undefined;
|
|
55
|
-
describeError?: ((error: unknown) => ArtifactLoadErrorView) | undefined;
|
|
56
|
-
onTitle?: ((title: string) => void) | undefined;
|
|
57
|
-
/** Loading copy; defaults to the `opening` label. */
|
|
58
|
-
loadingLabel?: string | undefined;
|
|
59
|
-
}>;
|
|
60
|
-
|
|
61
|
-
type LoadState =
|
|
62
|
-
| Readonly<{ key: string | null; kind: "loading" }>
|
|
63
|
-
| Readonly<{ key: string; kind: "ready"; value: OpenedEditableArtifact }>
|
|
64
|
-
| Readonly<{ key: string; kind: "error"; error: unknown }>;
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* One editable document, spreadsheet, or presentation with its first-party
|
|
68
|
-
* editor. The console dock/page and embedding hosts supply only data access.
|
|
69
|
-
*/
|
|
70
|
-
export function EditableArtifactView({
|
|
71
|
-
baseUrl,
|
|
72
|
-
workspaceId,
|
|
73
|
-
artifactId,
|
|
74
|
-
open,
|
|
75
|
-
runtimes,
|
|
76
|
-
transport,
|
|
77
|
-
showHeader = true,
|
|
78
|
-
authorityKey,
|
|
79
|
-
describeError,
|
|
80
|
-
onTitle,
|
|
81
|
-
loadingLabel,
|
|
82
|
-
}: EditableArtifactViewProps) {
|
|
83
|
-
const [loadEpoch, setLoadEpoch] = useState(0);
|
|
84
|
-
const labels = useArtifactLabels();
|
|
85
|
-
const loadKey = JSON.stringify([artifactId, authorityKey, baseUrl.href, workspaceId, loadEpoch]);
|
|
86
|
-
const [state, setState] = useState<LoadState>({ key: null, kind: "loading" });
|
|
87
|
-
const current = state.key === loadKey ? state : null;
|
|
88
|
-
const openRef = useRef(open);
|
|
89
|
-
openRef.current = open;
|
|
90
|
-
const onTitleRef = useRef(onTitle);
|
|
91
|
-
onTitleRef.current = onTitle;
|
|
92
|
-
useEffect(() => {
|
|
93
|
-
const abort = new AbortController();
|
|
94
|
-
setState({ key: loadKey, kind: "loading" });
|
|
95
|
-
void openRef
|
|
96
|
-
.current(abort.signal)
|
|
97
|
-
.then((value) => {
|
|
98
|
-
if (abort.signal.aborted) return;
|
|
99
|
-
setState({ key: loadKey, kind: "ready", value });
|
|
100
|
-
onTitleRef.current?.(value.artifact.title);
|
|
101
|
-
})
|
|
102
|
-
.catch((error: unknown) => {
|
|
103
|
-
if (!abort.signal.aborted) setState({ key: loadKey, kind: "error", error });
|
|
104
|
-
});
|
|
105
|
-
return () => abort.abort();
|
|
106
|
-
}, [loadKey]);
|
|
107
|
-
|
|
108
|
-
const ready = current?.kind === "ready" ? current.value : null;
|
|
109
|
-
const transportRef = useRef(transport);
|
|
110
|
-
transportRef.current = transport;
|
|
111
|
-
const sessionKey = useMemo(
|
|
112
|
-
() =>
|
|
113
|
-
ready
|
|
114
|
-
? JSON.stringify({
|
|
115
|
-
baseUrl: baseUrl.href,
|
|
116
|
-
authorityKey,
|
|
117
|
-
workspaceId,
|
|
118
|
-
artifact: { id: ready.artifact.id, modality: ready.artifact.modality },
|
|
119
|
-
authority: ready.authority,
|
|
120
|
-
replicaId: ready.replicaId,
|
|
121
|
-
workerUrl: runtimes.workerUrl,
|
|
122
|
-
})
|
|
123
|
-
: "",
|
|
124
|
-
[authorityKey, baseUrl.href, ready, runtimes.workerUrl, workspaceId],
|
|
125
|
-
);
|
|
126
|
-
const createSession = useCallback(() => {
|
|
127
|
-
if (!ready) throw new Error("Artifact is not open");
|
|
128
|
-
return createBrowserEditableArtifactSession({
|
|
129
|
-
baseUrl,
|
|
130
|
-
workspaceId,
|
|
131
|
-
artifact: ready.artifact,
|
|
132
|
-
storageAuthority: ready.authority,
|
|
133
|
-
replicaId: ready.replicaId,
|
|
134
|
-
runtime: {
|
|
135
|
-
...runtimeFor(runtimes, ready.artifact.modality),
|
|
136
|
-
workerUrl: runtimes.workerUrl,
|
|
137
|
-
...(runtimes.applicationOrigin ? { applicationOrigin: runtimes.applicationOrigin } : {}),
|
|
138
|
-
...(runtimes.allowInsecureDevelopmentAssets
|
|
139
|
-
? { allowInsecureDevelopmentAssets: true }
|
|
140
|
-
: {}),
|
|
141
|
-
},
|
|
142
|
-
...(transportRef.current ? { transport: transportRef.current } : {}),
|
|
143
|
-
});
|
|
144
|
-
}, [baseUrl, ready, runtimes, workspaceId]);
|
|
145
|
-
|
|
146
|
-
if (!current || current.kind === "loading")
|
|
147
|
-
return <ArtifactLoading label={loadingLabel ?? labels.opening} />;
|
|
148
|
-
if (current.kind === "error") {
|
|
149
|
-
return (
|
|
150
|
-
<ArtifactProblem
|
|
151
|
-
view={
|
|
152
|
-
describeError
|
|
153
|
-
? describeError(current.error)
|
|
154
|
-
: artifactLoadErrorView(current.error, "editable", labels)
|
|
155
|
-
}
|
|
156
|
-
onRetry={() => setLoadEpoch((value) => value + 1)}
|
|
157
|
-
/>
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
const { artifact } = current.value;
|
|
161
|
-
const surface = { title: artifact.title, showHeader };
|
|
162
|
-
return (
|
|
163
|
-
<div className="h-full min-h-0 bg-og-bg text-og-fg">
|
|
164
|
-
<EditableArtifactWorkbenchHost
|
|
165
|
-
sessionKey={sessionKey}
|
|
166
|
-
createSession={createSession}
|
|
167
|
-
document={surface}
|
|
168
|
-
spreadsheet={surface}
|
|
169
|
-
presentation={surface}
|
|
170
|
-
/>
|
|
171
|
-
</div>
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
function runtimeFor(
|
|
176
|
-
runtimes: EditableArtifactRuntimes,
|
|
177
|
-
modality: EditableArtifactModality,
|
|
178
|
-
): Omit<EditableArtifactBrowserRuntime, "workerUrl" | "workerFactory"> {
|
|
179
|
-
switch (modality) {
|
|
180
|
-
case "document":
|
|
181
|
-
return runtimes.document;
|
|
182
|
-
case "spreadsheet":
|
|
183
|
-
return runtimes.spreadsheet;
|
|
184
|
-
case "presentation":
|
|
185
|
-
return runtimes.presentation;
|
|
186
|
-
}
|
|
187
|
-
}
|