@floegence/floe-webapp-core 0.56.17 → 0.57.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chat-media.d.ts +1 -0
- package/dist/chat-media.js +8 -0
- package/dist/chat.css +34 -0
- package/dist/chat.js +89 -81
- package/dist/components/chat/blocks/MarkdownMedia.d.ts +30 -0
- package/dist/components/chat/blocks/MarkdownMedia.js +220 -0
- package/dist/components/chat/index.d.ts +2 -0
- package/dist/components/chat/markdown/media.d.ts +16 -0
- package/dist/components/chat/markdown/media.js +42 -0
- package/dist/full.js +496 -488
- package/dist/styles.css +1 -1
- package/package.json +5 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './components/chat/markdown/media';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { markdownMediaKind as e, markdownMediaPlaceholder as o, readMarkdownMediaPlaceholder as r, safeMarkdownMediaURL as n, sandboxedMarkdownHtml as M } from "./components/chat/markdown/media.js";
|
|
2
|
+
export {
|
|
3
|
+
e as markdownMediaKind,
|
|
4
|
+
o as markdownMediaPlaceholder,
|
|
5
|
+
r as readMarkdownMediaPlaceholder,
|
|
6
|
+
n as safeMarkdownMediaURL,
|
|
7
|
+
M as sandboxedMarkdownHtml
|
|
8
|
+
};
|
package/dist/chat.css
CHANGED
|
@@ -1843,3 +1843,37 @@ pre.chat-md-code-block *::selection,
|
|
|
1843
1843
|
}
|
|
1844
1844
|
|
|
1845
1845
|
} /* End of @layer components */
|
|
1846
|
+
|
|
1847
|
+
@layer components {
|
|
1848
|
+
.chat-media { position: relative; display: flex; flex-direction: column; width: fit-content; max-width: min(100%, 42rem); min-width: 0; margin: .8rem 0 1rem; color: var(--foreground); text-align: left; }
|
|
1849
|
+
.chat-media[data-media-kind="html"] { width: 100%; }
|
|
1850
|
+
.chat-media[data-media-kind="video"] { width: min(100%, 36rem); }
|
|
1851
|
+
.chat-media[data-media-kind="audio"] { width: min(100%, 28rem); }
|
|
1852
|
+
.chat-media-header { display: flex; align-items: center; min-width: 0; padding: .4rem .15rem 0; }
|
|
1853
|
+
.chat-media-heading { min-width: 0; }
|
|
1854
|
+
.chat-media-kind { display: none; }
|
|
1855
|
+
.chat-media-title { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .6875rem; line-height: 1.5; color: var(--muted-foreground); }
|
|
1856
|
+
.chat-media-actions { position: absolute; top: .5rem; right: .5rem; display: flex; align-items: center; gap: .15rem; padding: .2rem; border-radius: .55rem; background: rgb(24 24 24 / .78); color: white; opacity: 0; transform: translateY(-2px); transition: opacity 120ms ease, transform 120ms ease; }
|
|
1857
|
+
.chat-media:hover .chat-media-actions, .chat-media:focus-within .chat-media-actions { opacity: 1; transform: none; }
|
|
1858
|
+
.chat-media-action { display: inline-flex; align-items: center; justify-content: center; width: 1.8rem; height: 1.8rem; border: 0; padding: 0; border-radius: .35rem; background: transparent; color: inherit; cursor: pointer; }
|
|
1859
|
+
.chat-media-action:hover { background: rgb(255 255 255 / .16); }
|
|
1860
|
+
.chat-media-action svg, .chat-media-retry svg { width: .95rem; height: .95rem; }
|
|
1861
|
+
.chat-media-action:focus-visible { outline: 2px solid white; outline-offset: -2px; }
|
|
1862
|
+
.chat-media-image-button:focus-visible, .chat-media-retry:focus-visible { outline: 2px solid var(--ring); outline-offset: 3px; }
|
|
1863
|
+
.chat-media-placeholder { display: flex; align-items: center; justify-content: center; gap: .75rem; width: min(22rem, 100%); min-height: 7rem; padding: 1rem; border-radius: .75rem; background: var(--muted); font-size: .75rem; color: var(--muted-foreground); }
|
|
1864
|
+
.chat-media-retry { display: inline-flex; align-items: center; gap: .4rem; padding: .4rem .65rem; border-radius: .4rem; cursor: pointer; color: var(--foreground); }
|
|
1865
|
+
.chat-media-retry:hover { background: var(--background); }
|
|
1866
|
+
.chat-media-image-button { display: block; max-width: 100%; padding: 0; border: 0; border-radius: .75rem; overflow: hidden; cursor: zoom-in; background: transparent; }
|
|
1867
|
+
.chat-media-image { display: block; width: auto; height: auto; max-width: 100%; max-height: 28rem; object-fit: contain; margin: 0; border: 0; border-radius: .75rem; }
|
|
1868
|
+
.chat-media-video { display: block; width: 100%; max-width: 100%; max-height: 28rem; border: 0; border-radius: .75rem; background: #111; }
|
|
1869
|
+
.chat-media-audio { display: block; width: min(28rem, 100%); }
|
|
1870
|
+
.chat-media-html { display: block; width: 100%; height: 22rem; border: 0; border-radius: .75rem; background: white; color-scheme: light; }
|
|
1871
|
+
.chat-media-expanded { max-width: 100%; }
|
|
1872
|
+
.chat-media-expanded .chat-media-html { height: min(70vh, 48rem); }
|
|
1873
|
+
.chat-media-dialog { width: min(92vw, 80rem); max-width: 80rem; }
|
|
1874
|
+
.chat-media-dialog-body { min-height: 0; overflow: auto; }
|
|
1875
|
+
.chat-media-full-image { display: block; max-width: 100%; max-height: 75vh; margin: auto; object-fit: contain; }
|
|
1876
|
+
@media (hover: none) { .chat-media-actions { opacity: 1; transform: none; } }
|
|
1877
|
+
@media (prefers-reduced-motion: reduce) { .chat-media-actions { transition: none; } }
|
|
1878
|
+
@media (max-width: 480px) { .chat-media-html { height: 18rem; } }
|
|
1879
|
+
}
|
package/dist/chat.js
CHANGED
|
@@ -1,95 +1,103 @@
|
|
|
1
1
|
import { AttachmentPreview as o } from "./components/chat/input/AttachmentPreview.js";
|
|
2
|
-
import { BlockRenderer as
|
|
3
|
-
import { ChatContainer as
|
|
2
|
+
import { BlockRenderer as a } from "./components/chat/blocks/BlockRenderer.js";
|
|
3
|
+
import { ChatContainer as f } from "./components/chat/ChatContainer.js";
|
|
4
4
|
import { ChatInput as n } from "./components/chat/input/ChatInput.js";
|
|
5
|
-
import { ChatProvider as
|
|
6
|
-
import { ChecklistBlock as
|
|
7
|
-
import { CodeBlock as
|
|
8
|
-
import { CodeDiffBlock as
|
|
5
|
+
import { ChatProvider as d, useChatContext as p } from "./components/chat/ChatProvider.js";
|
|
6
|
+
import { ChecklistBlock as c } from "./components/chat/blocks/ChecklistBlock.js";
|
|
7
|
+
import { CodeBlock as s } from "./components/chat/blocks/CodeBlock.js";
|
|
8
|
+
import { CodeDiffBlock as g } from "./components/chat/blocks/CodeDiffBlock.js";
|
|
9
9
|
import { ConnectionStatus as h } from "./components/chat/status/ConnectionStatus.js";
|
|
10
|
-
import { DEFAULT_VIRTUAL_LIST_CONFIG as
|
|
11
|
-
import { FileBlock as
|
|
10
|
+
import { DEFAULT_VIRTUAL_LIST_CONFIG as C } from "./components/chat/types.js";
|
|
11
|
+
import { FileBlock as W } from "./components/chat/blocks/FileBlock.js";
|
|
12
12
|
import { ImageBlock as D } from "./components/chat/blocks/ImageBlock.js";
|
|
13
13
|
import { MarkdownBlock as v } from "./components/chat/blocks/MarkdownBlock.js";
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
14
|
+
import { MarkdownMedia as L } from "./components/chat/blocks/MarkdownMedia.js";
|
|
15
|
+
import { MermaidBlock as F } from "./components/chat/blocks/MermaidBlock.js";
|
|
16
|
+
import { MessageActions as y } from "./components/chat/message/MessageActions.js";
|
|
17
|
+
import { MessageAvatar as P } from "./components/chat/message/MessageAvatar.js";
|
|
18
|
+
import { MessageBubble as R } from "./components/chat/message/MessageBubble.js";
|
|
19
|
+
import { MessageItem as V } from "./components/chat/message/MessageItem.js";
|
|
20
|
+
import { MessageMeta as N } from "./components/chat/message/MessageMeta.js";
|
|
21
|
+
import { ShellBlock as K } from "./components/chat/blocks/ShellBlock.js";
|
|
22
|
+
import { StreamingCursor as j } from "./components/chat/status/StreamingCursor.js";
|
|
23
|
+
import { SvgBlock as z } from "./components/chat/blocks/SvgBlock.js";
|
|
24
|
+
import { TextBlock as Q } from "./components/chat/blocks/TextBlock.js";
|
|
25
|
+
import { ThinkingBlock as Y } from "./components/chat/blocks/ThinkingBlock.js";
|
|
26
|
+
import { ToolCallBlock as $ } from "./components/chat/blocks/ToolCallBlock.js";
|
|
27
|
+
import { VirtualMessageList as er } from "./components/chat/message-list/VirtualMessageList.js";
|
|
28
|
+
import { WorkingIndicator as tr } from "./components/chat/status/WorkingIndicator.js";
|
|
29
|
+
import { buildAssistantNoticeEvents as ir, createStreamEventBuilder as fr, isStreamEvent as mr } from "./components/chat/streamEvents.js";
|
|
30
|
+
import { computeCodeDiff as kr, computeCodeDiffSync as dr, configureDiffWorker as pr, createDiffWorker as xr, hasDiffWorker as cr, terminateDiffWorker as lr, waitForDiffWorker as sr } from "./components/chat/hooks/useCodeDiff.js";
|
|
31
|
+
import { configureMarkdownWorker as gr, createMarkdownWorker as ur, hasMarkdownWorker as hr, renderMarkdown as wr, renderMarkdownSync as Cr, terminateMarkdownWorker as Br, waitForMarkdownWorker as Wr } from "./components/chat/hooks/useMarkdown.js";
|
|
32
|
+
import { configureMermaidWorker as Dr, configureSyncMermaid as Ar, renderMermaid as vr, terminateMermaidWorker as Ir, useMermaid as Lr } from "./components/chat/hooks/useMermaid.js";
|
|
33
|
+
import { configureShikiWorker as Fr, configureSyncHighlighter as br, highlightCode as yr, terminateShikiWorker as Er, useCodeHighlight as Pr } from "./components/chat/hooks/useCodeHighlight.js";
|
|
34
|
+
import { markdownMediaKind as Rr, markdownMediaPlaceholder as Ur, readMarkdownMediaPlaceholder as Vr, safeMarkdownMediaURL as _r, sandboxedMarkdownHtml as Nr } from "./components/chat/markdown/media.js";
|
|
35
|
+
import { useAttachments as Kr } from "./components/chat/hooks/useAttachments.js";
|
|
36
|
+
import { useAutoScroll as jr } from "./components/chat/hooks/useAutoScroll.js";
|
|
37
|
+
import { useVirtualList as zr } from "./components/chat/hooks/useVirtualList.js";
|
|
36
38
|
export {
|
|
37
39
|
o as AttachmentPreview,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
a as BlockRenderer,
|
|
41
|
+
f as ChatContainer,
|
|
40
42
|
n as ChatInput,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
d as ChatProvider,
|
|
44
|
+
c as ChecklistBlock,
|
|
45
|
+
s as CodeBlock,
|
|
46
|
+
g as CodeDiffBlock,
|
|
45
47
|
h as ConnectionStatus,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
C as DEFAULT_VIRTUAL_LIST_CONFIG,
|
|
49
|
+
W as FileBlock,
|
|
48
50
|
D as ImageBlock,
|
|
49
51
|
v as MarkdownBlock,
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
Q as
|
|
61
|
-
Y as
|
|
62
|
-
$ as
|
|
63
|
-
er as
|
|
64
|
-
tr as
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
Fr as
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
52
|
+
L as MarkdownMedia,
|
|
53
|
+
F as MermaidBlock,
|
|
54
|
+
y as MessageActions,
|
|
55
|
+
P as MessageAvatar,
|
|
56
|
+
R as MessageBubble,
|
|
57
|
+
V as MessageItem,
|
|
58
|
+
N as MessageMeta,
|
|
59
|
+
K as ShellBlock,
|
|
60
|
+
j as StreamingCursor,
|
|
61
|
+
z as SvgBlock,
|
|
62
|
+
Q as TextBlock,
|
|
63
|
+
Y as ThinkingBlock,
|
|
64
|
+
$ as ToolCallBlock,
|
|
65
|
+
er as VirtualMessageList,
|
|
66
|
+
tr as WorkingIndicator,
|
|
67
|
+
ir as buildAssistantNoticeEvents,
|
|
68
|
+
kr as computeCodeDiff,
|
|
69
|
+
dr as computeCodeDiffSync,
|
|
70
|
+
pr as configureDiffWorker,
|
|
71
|
+
gr as configureMarkdownWorker,
|
|
72
|
+
Dr as configureMermaidWorker,
|
|
73
|
+
Fr as configureShikiWorker,
|
|
74
|
+
br as configureSyncHighlighter,
|
|
75
|
+
Ar as configureSyncMermaid,
|
|
76
|
+
xr as createDiffWorker,
|
|
77
|
+
ur as createMarkdownWorker,
|
|
75
78
|
fr as createStreamEventBuilder,
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
Cr as
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
79
|
+
cr as hasDiffWorker,
|
|
80
|
+
hr as hasMarkdownWorker,
|
|
81
|
+
yr as highlightCode,
|
|
82
|
+
mr as isStreamEvent,
|
|
83
|
+
Rr as markdownMediaKind,
|
|
84
|
+
Ur as markdownMediaPlaceholder,
|
|
85
|
+
Vr as readMarkdownMediaPlaceholder,
|
|
86
|
+
wr as renderMarkdown,
|
|
87
|
+
Cr as renderMarkdownSync,
|
|
88
|
+
vr as renderMermaid,
|
|
89
|
+
_r as safeMarkdownMediaURL,
|
|
90
|
+
Nr as sandboxedMarkdownHtml,
|
|
91
|
+
lr as terminateDiffWorker,
|
|
92
|
+
Br as terminateMarkdownWorker,
|
|
93
|
+
Ir as terminateMermaidWorker,
|
|
94
|
+
Er as terminateShikiWorker,
|
|
95
|
+
Kr as useAttachments,
|
|
96
|
+
jr as useAutoScroll,
|
|
97
|
+
p as useChatContext,
|
|
98
|
+
Pr as useCodeHighlight,
|
|
99
|
+
Lr as useMermaid,
|
|
100
|
+
zr as useVirtualList,
|
|
93
101
|
sr as waitForDiffWorker,
|
|
94
|
-
|
|
102
|
+
Wr as waitForMarkdownWorker
|
|
95
103
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type Component } from 'solid-js';
|
|
2
|
+
import { type MarkdownMediaSource } from '../markdown/media';
|
|
3
|
+
export interface MarkdownMediaLabels {
|
|
4
|
+
image: string;
|
|
5
|
+
video: string;
|
|
6
|
+
audio: string;
|
|
7
|
+
html: string;
|
|
8
|
+
loading: string;
|
|
9
|
+
unavailable: string;
|
|
10
|
+
retry: string;
|
|
11
|
+
expand: string;
|
|
12
|
+
collapse: string;
|
|
13
|
+
open: string;
|
|
14
|
+
close: string;
|
|
15
|
+
}
|
|
16
|
+
export interface ResolvedMarkdownMedia {
|
|
17
|
+
/** Host-authorized media URL; HTML uses loadHTML instead. */
|
|
18
|
+
src?: string;
|
|
19
|
+
/** Optional host-authorized source link. */
|
|
20
|
+
openURL?: string;
|
|
21
|
+
loadHTML?: (signal: AbortSignal) => Promise<string>;
|
|
22
|
+
}
|
|
23
|
+
export interface MarkdownMediaProps {
|
|
24
|
+
source: MarkdownMediaSource;
|
|
25
|
+
labels: MarkdownMediaLabels;
|
|
26
|
+
resolve?: (source: MarkdownMediaSource, signal: AbortSignal) => Promise<ResolvedMarkdownMedia>;
|
|
27
|
+
class?: string;
|
|
28
|
+
}
|
|
29
|
+
/** Stable inline media with host-owned resource resolution and an isolated HTML document. */
|
|
30
|
+
export declare const MarkdownMedia: Component<MarkdownMediaProps>;
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { use as V, insert as d, createComponent as o, effect as h, setAttribute as i, memo as j, className as B, template as c, delegateEvents as F } from "solid-js/web";
|
|
2
|
+
import { createSignal as y, onMount as G, onCleanup as q, createMemo as J, createEffect as K, Switch as U, Match as f, Show as _ } from "solid-js";
|
|
3
|
+
import { Dialog as P } from "../../ui/Dialog.js";
|
|
4
|
+
import { Refresh as Q, Maximize as W, ExternalLink as X } from "../../icons/index.js";
|
|
5
|
+
import { cn as Y } from "../../../utils/cn.js";
|
|
6
|
+
import { sandboxedMarkdownHtml as A, safeMarkdownMediaURL as Z } from "../markdown/media.js";
|
|
7
|
+
var p = /* @__PURE__ */ c("<span class=chat-media-placeholder role=status>"), ee = /* @__PURE__ */ c("<span class=chat-media-placeholder role=status><span></span><button type=button class=chat-media-retry>"), te = /* @__PURE__ */ c("<button type=button class=chat-media-image-button><img class=chat-media-image loading=lazy decoding=async referrerpolicy=no-referrer>", !0, !1, !1), re = /* @__PURE__ */ c("<video class=chat-media-video controls playsinline preload=metadata>"), ae = /* @__PURE__ */ c("<audio class=chat-media-audio controls preload=metadata>"), ne = /* @__PURE__ */ c("<iframe class=chat-media-html sandbox=allow-scripts referrerpolicy=no-referrer>"), le = /* @__PURE__ */ c("<button type=button class=chat-media-action>"), ie = /* @__PURE__ */ c("<img referrerpolicy=no-referrer class=chat-media-full-image>"), oe = /* @__PURE__ */ c("<span><span class=chat-media-header><span class=chat-media-heading><span class=chat-media-kind></span><span class=chat-media-title></span></span><span class=chat-media-actions>"), se = /* @__PURE__ */ c('<a class=chat-media-action target=_blank rel="noopener noreferrer">');
|
|
8
|
+
async function de(a) {
|
|
9
|
+
const m = Z(a.src ?? "");
|
|
10
|
+
if (!m || a.kind === "html") throw new Error("A host resolver is required");
|
|
11
|
+
return {
|
|
12
|
+
src: m,
|
|
13
|
+
openURL: m
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const fe = (a) => {
|
|
17
|
+
let m;
|
|
18
|
+
const [I, R] = y(!1);
|
|
19
|
+
G(() => {
|
|
20
|
+
if (typeof IntersectionObserver > "u") {
|
|
21
|
+
R(!0);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const l = new IntersectionObserver((k) => {
|
|
25
|
+
k.some((s) => s.isIntersecting) && (R(!0), l.disconnect());
|
|
26
|
+
}, {
|
|
27
|
+
rootMargin: "400px"
|
|
28
|
+
});
|
|
29
|
+
l.observe(m), q(() => l.disconnect());
|
|
30
|
+
});
|
|
31
|
+
const [$, S] = y(), [O, C] = y(), [L, b] = y("loading"), [z, D] = y(0), [w, E] = y(!1), u = () => a.source.title || a.labels[a.source.kind], N = J(() => a.source);
|
|
32
|
+
return K(() => {
|
|
33
|
+
if (!I()) return;
|
|
34
|
+
const l = N(), k = a.resolve ?? de;
|
|
35
|
+
z();
|
|
36
|
+
const s = new AbortController();
|
|
37
|
+
q(() => s.abort()), S(void 0), C(void 0), b("loading"), E(!1), (async () => {
|
|
38
|
+
if (l.kind === "html" && l.html !== void 0) {
|
|
39
|
+
if (l.html.length > 1e6) throw new Error("HTML preview is too large");
|
|
40
|
+
s.signal.aborted || C(A(l.html));
|
|
41
|
+
} else {
|
|
42
|
+
const g = await k(l, s.signal);
|
|
43
|
+
if (s.signal.aborted) return;
|
|
44
|
+
if (l.kind === "html") {
|
|
45
|
+
if (!g.loadHTML) throw new Error("HTML loader is required");
|
|
46
|
+
const x = await g.loadHTML(s.signal);
|
|
47
|
+
if (s.signal.aborted) return;
|
|
48
|
+
if (x.length > 1e6) throw new Error("HTML preview is too large");
|
|
49
|
+
C(A(x));
|
|
50
|
+
} else if (!g.src) throw new Error("Media URL is required");
|
|
51
|
+
S(g);
|
|
52
|
+
}
|
|
53
|
+
s.signal.aborted || b("ready");
|
|
54
|
+
})().catch(() => {
|
|
55
|
+
s.signal.aborted || b("error");
|
|
56
|
+
});
|
|
57
|
+
}), (() => {
|
|
58
|
+
var l = oe(), k = l.firstChild, s = k.firstChild, g = s.firstChild, x = g.nextSibling, H = s.nextSibling, T = m;
|
|
59
|
+
return typeof T == "function" ? V(T, l) : m = l, d(l, o(U, {
|
|
60
|
+
get children() {
|
|
61
|
+
return [o(f, {
|
|
62
|
+
get when() {
|
|
63
|
+
return L() === "loading";
|
|
64
|
+
},
|
|
65
|
+
get children() {
|
|
66
|
+
var t = p();
|
|
67
|
+
return d(t, () => a.labels.loading), t;
|
|
68
|
+
}
|
|
69
|
+
}), o(f, {
|
|
70
|
+
get when() {
|
|
71
|
+
return L() === "error";
|
|
72
|
+
},
|
|
73
|
+
get children() {
|
|
74
|
+
var t = ee(), e = t.firstChild, r = e.nextSibling;
|
|
75
|
+
return d(e, () => a.labels.unavailable), r.$$click = () => D((n) => n + 1), d(r, o(Q, {}), null), d(r, () => a.labels.retry, null), t;
|
|
76
|
+
}
|
|
77
|
+
}), o(f, {
|
|
78
|
+
get when() {
|
|
79
|
+
return L() === "ready";
|
|
80
|
+
},
|
|
81
|
+
get children() {
|
|
82
|
+
return o(U, {
|
|
83
|
+
get children() {
|
|
84
|
+
return [o(f, {
|
|
85
|
+
get when() {
|
|
86
|
+
return a.source.kind === "image";
|
|
87
|
+
},
|
|
88
|
+
get children() {
|
|
89
|
+
var t = te(), e = t.firstChild;
|
|
90
|
+
return t.$$click = () => E(!0), e.addEventListener("error", () => b("error")), h((r) => {
|
|
91
|
+
var n = `${a.labels.expand}: ${u()}`, v = $()?.src, M = u();
|
|
92
|
+
return n !== r.e && i(t, "aria-label", r.e = n), v !== r.t && i(e, "src", r.t = v), M !== r.a && i(e, "alt", r.a = M), r;
|
|
93
|
+
}, {
|
|
94
|
+
e: void 0,
|
|
95
|
+
t: void 0,
|
|
96
|
+
a: void 0
|
|
97
|
+
}), t;
|
|
98
|
+
}
|
|
99
|
+
}), o(f, {
|
|
100
|
+
get when() {
|
|
101
|
+
return a.source.kind === "video";
|
|
102
|
+
},
|
|
103
|
+
get children() {
|
|
104
|
+
var t = re();
|
|
105
|
+
return t.addEventListener("error", () => b("error")), h((e) => {
|
|
106
|
+
var r = $()?.src, n = u();
|
|
107
|
+
return r !== e.e && i(t, "src", e.e = r), n !== e.t && i(t, "aria-label", e.t = n), e;
|
|
108
|
+
}, {
|
|
109
|
+
e: void 0,
|
|
110
|
+
t: void 0
|
|
111
|
+
}), t;
|
|
112
|
+
}
|
|
113
|
+
}), o(f, {
|
|
114
|
+
get when() {
|
|
115
|
+
return a.source.kind === "audio";
|
|
116
|
+
},
|
|
117
|
+
get children() {
|
|
118
|
+
var t = ae();
|
|
119
|
+
return t.addEventListener("error", () => b("error")), h((e) => {
|
|
120
|
+
var r = $()?.src, n = u();
|
|
121
|
+
return r !== e.e && i(t, "src", e.e = r), n !== e.t && i(t, "aria-label", e.t = n), e;
|
|
122
|
+
}, {
|
|
123
|
+
e: void 0,
|
|
124
|
+
t: void 0
|
|
125
|
+
}), t;
|
|
126
|
+
}
|
|
127
|
+
}), o(f, {
|
|
128
|
+
get when() {
|
|
129
|
+
return a.source.kind === "html";
|
|
130
|
+
},
|
|
131
|
+
get children() {
|
|
132
|
+
var t = ne();
|
|
133
|
+
return h((e) => {
|
|
134
|
+
var r = u(), n = O();
|
|
135
|
+
return r !== e.e && i(t, "title", e.e = r), n !== e.t && i(t, "srcdoc", e.t = n), e;
|
|
136
|
+
}, {
|
|
137
|
+
e: void 0,
|
|
138
|
+
t: void 0
|
|
139
|
+
}), t;
|
|
140
|
+
}
|
|
141
|
+
})];
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
})];
|
|
146
|
+
}
|
|
147
|
+
}), k), d(g, () => a.labels[a.source.kind]), d(x, u), d(H, o(_, {
|
|
148
|
+
get when() {
|
|
149
|
+
return j(() => L() === "ready")() && ["image", "html"].includes(a.source.kind);
|
|
150
|
+
},
|
|
151
|
+
get children() {
|
|
152
|
+
var t = le();
|
|
153
|
+
return t.$$click = () => E(!w()), d(t, o(W, {})), h((e) => {
|
|
154
|
+
var r = w() ? a.labels.collapse : a.labels.expand, n = w() ? a.labels.collapse : a.labels.expand, v = w();
|
|
155
|
+
return r !== e.e && i(t, "aria-label", e.e = r), n !== e.t && i(t, "title", e.t = n), v !== e.a && i(t, "aria-expanded", e.a = v), e;
|
|
156
|
+
}, {
|
|
157
|
+
e: void 0,
|
|
158
|
+
t: void 0,
|
|
159
|
+
a: void 0
|
|
160
|
+
}), t;
|
|
161
|
+
}
|
|
162
|
+
}), null), d(H, o(_, {
|
|
163
|
+
get when() {
|
|
164
|
+
return $()?.openURL;
|
|
165
|
+
},
|
|
166
|
+
children: (t) => (() => {
|
|
167
|
+
var e = se();
|
|
168
|
+
return d(e, o(X, {})), h((r) => {
|
|
169
|
+
var n = t(), v = a.labels.open, M = a.labels.open;
|
|
170
|
+
return n !== r.e && i(e, "href", r.e = n), v !== r.t && i(e, "aria-label", r.t = v), M !== r.a && i(e, "title", r.a = M), r;
|
|
171
|
+
}, {
|
|
172
|
+
e: void 0,
|
|
173
|
+
t: void 0,
|
|
174
|
+
a: void 0
|
|
175
|
+
}), e;
|
|
176
|
+
})()
|
|
177
|
+
}), null), d(l, o(_, {
|
|
178
|
+
get when() {
|
|
179
|
+
return a.source.kind === "image";
|
|
180
|
+
},
|
|
181
|
+
get children() {
|
|
182
|
+
return o(P, {
|
|
183
|
+
get open() {
|
|
184
|
+
return w();
|
|
185
|
+
},
|
|
186
|
+
onOpenChange: E,
|
|
187
|
+
get title() {
|
|
188
|
+
return u();
|
|
189
|
+
},
|
|
190
|
+
get closeLabel() {
|
|
191
|
+
return a.labels.close;
|
|
192
|
+
},
|
|
193
|
+
class: "chat-media-dialog",
|
|
194
|
+
contentClass: "chat-media-dialog-body",
|
|
195
|
+
get children() {
|
|
196
|
+
var t = ie();
|
|
197
|
+
return h((e) => {
|
|
198
|
+
var r = $()?.src, n = u();
|
|
199
|
+
return r !== e.e && i(t, "src", e.e = r), n !== e.t && i(t, "alt", e.t = n), e;
|
|
200
|
+
}, {
|
|
201
|
+
e: void 0,
|
|
202
|
+
t: void 0
|
|
203
|
+
}), t;
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}), null), h((t) => {
|
|
208
|
+
var e = Y("chat-media", w() && a.source.kind === "html" && "chat-media-expanded", a.class), r = a.source.kind, n = u();
|
|
209
|
+
return e !== t.e && B(l, t.e = e), r !== t.t && i(l, "data-media-kind", t.t = r), n !== t.a && i(x, "title", t.a = n), t;
|
|
210
|
+
}, {
|
|
211
|
+
e: void 0,
|
|
212
|
+
t: void 0,
|
|
213
|
+
a: void 0
|
|
214
|
+
}), l;
|
|
215
|
+
})();
|
|
216
|
+
};
|
|
217
|
+
F(["click"]);
|
|
218
|
+
export {
|
|
219
|
+
fe as MarkdownMedia
|
|
220
|
+
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { ChatContainer, type ChatContainerProps } from './ChatContainer';
|
|
2
2
|
export { ChatProvider, useChatContext, type ChatProviderProps, type ChatContextValue } from './ChatProvider';
|
|
3
3
|
export * from './types';
|
|
4
|
+
export { MarkdownMedia, type MarkdownMediaProps, type MarkdownMediaLabels, type ResolvedMarkdownMedia } from './blocks/MarkdownMedia';
|
|
5
|
+
export { markdownMediaKind, markdownMediaPlaceholder, readMarkdownMediaPlaceholder, safeMarkdownMediaURL, sandboxedMarkdownHtml, type MarkdownMediaKind, type MarkdownMediaSource } from './markdown/media';
|
|
4
6
|
export { createStreamEventBuilder, buildAssistantNoticeEvents, isStreamEvent, type StreamEventBuilder } from './streamEvents';
|
|
5
7
|
export { VirtualMessageList, type VirtualMessageListProps } from './message-list';
|
|
6
8
|
export { MessageItem, MessageBubble, MessageAvatar, MessageMeta, MessageActions, type MessageItemProps, type MessageBubbleProps, type MessageAvatarProps, type MessageMetaProps, type MessageActionsProps, } from './message';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type MarkdownMediaKind = 'image' | 'video' | 'audio' | 'html';
|
|
2
|
+
/** A display request, never an authorization or filesystem capability. */
|
|
3
|
+
export interface MarkdownMediaSource {
|
|
4
|
+
kind: MarkdownMediaKind;
|
|
5
|
+
title: string;
|
|
6
|
+
src?: string;
|
|
7
|
+
html?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function markdownMediaKind(source: string): MarkdownMediaKind | undefined;
|
|
10
|
+
/** Inert placeholder: mount trusted components only after Markdown has been rendered. */
|
|
11
|
+
export declare function markdownMediaPlaceholder(source: MarkdownMediaSource): string;
|
|
12
|
+
export declare function readMarkdownMediaPlaceholder(element: Element): MarkdownMediaSource | undefined;
|
|
13
|
+
/** Remote display URLs only. Hosts resolve opaque/local references through their own authority. */
|
|
14
|
+
export declare function safeMarkdownMediaURL(raw: string): string | undefined;
|
|
15
|
+
/** The CSP precedes supplied markup; the opaque sandbox also denies shell/storage access. */
|
|
16
|
+
export declare function sandboxedMarkdownHtml(html: string): string;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
function o(t) {
|
|
2
|
+
const e = t.split(/[?#]/, 1)[0].toLowerCase();
|
|
3
|
+
if (/\.(png|jpe?g|gif|webp|avif|svg)$/.test(e)) return "image";
|
|
4
|
+
if (/\.(mp4|webm|ogv|mov)$/.test(e)) return "video";
|
|
5
|
+
if (/\.(mp3|wav|ogg|m4a|aac|flac)$/.test(e)) return "audio";
|
|
6
|
+
if (/\.html?$/.test(e)) return "html";
|
|
7
|
+
}
|
|
8
|
+
function n(t) {
|
|
9
|
+
if (!t || typeof t != "object") return !1;
|
|
10
|
+
const e = t;
|
|
11
|
+
return ["image", "video", "audio", "html"].includes(e.kind) && typeof e.title == "string" && (typeof e.src == "string" && e.src.length > 0 && e.src.length <= 8192 && e.html === void 0 || e.kind === "html" && typeof e.html == "string" && e.html.length <= 1e6 && e.src === void 0);
|
|
12
|
+
}
|
|
13
|
+
function r(t) {
|
|
14
|
+
return n(t) ? `<span data-floe-markdown-media="${encodeURIComponent(JSON.stringify(t)).replace(/'/g, "%27")}"></span>` : "";
|
|
15
|
+
}
|
|
16
|
+
function a(t) {
|
|
17
|
+
try {
|
|
18
|
+
const e = JSON.parse(decodeURIComponent(t.getAttribute("data-floe-markdown-media") ?? ""));
|
|
19
|
+
return n(e) ? e : void 0;
|
|
20
|
+
} catch {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function i(t) {
|
|
25
|
+
if (![...t].some((e) => e.charCodeAt(0) <= 32 || e.charCodeAt(0) === 127 || e === "\\"))
|
|
26
|
+
try {
|
|
27
|
+
const e = new URL(t);
|
|
28
|
+
return !["https:", "http:"].includes(e.protocol) || e.username || e.password ? void 0 : e.href;
|
|
29
|
+
} catch {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function d(t) {
|
|
34
|
+
return `<!doctype html><html><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; img-src data: blob:; media-src data: blob:; font-src data:; connect-src 'none'; frame-src 'none'; object-src 'none'; base-uri 'none'; form-action 'none'"><meta name="referrer" content="no-referrer"><meta name="viewport" content="width=device-width, initial-scale=1"><style>html{color-scheme:light}body{margin:16px;font:14px/1.5 system-ui,sans-serif;overflow-wrap:anywhere}img,video,svg,canvas{max-width:100%}button,a,input,select{touch-action:manipulation}</style></head><body>${t}</body></html>`;
|
|
35
|
+
}
|
|
36
|
+
export {
|
|
37
|
+
o as markdownMediaKind,
|
|
38
|
+
r as markdownMediaPlaceholder,
|
|
39
|
+
a as readMarkdownMediaPlaceholder,
|
|
40
|
+
i as safeMarkdownMediaURL,
|
|
41
|
+
d as sandboxedMarkdownHtml
|
|
42
|
+
};
|