@yumiai/chat-widget 0.1.2 → 0.2.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/CHANGELOG.md +100 -0
- package/README.md +119 -22
- package/dist/ExcelCore-DJOIVQMI.js +11 -0
- package/dist/ExcelCore-DJOIVQMI.js.map +1 -0
- package/dist/ExcelViewer-3YLLYYIQ.js +65 -0
- package/dist/ExcelViewer-3YLLYYIQ.js.map +1 -0
- package/dist/GerberViewerA2UI-7CNT7HX4.css +693 -0
- package/dist/GerberViewerA2UI-7CNT7HX4.css.map +1 -0
- package/dist/GerberViewerA2UI-X5FWAD5M.js +57 -0
- package/dist/GerberViewerA2UI-X5FWAD5M.js.map +1 -0
- package/dist/GraphStatsLegend-D5bPeXB_.d.cts +607 -0
- package/dist/GraphStatsLegend-D5bPeXB_.d.ts +607 -0
- package/dist/JsonRenderStandalone-EIZM62JU.js +18 -0
- package/dist/JsonRenderStandalone-EIZM62JU.js.map +1 -0
- package/dist/JsonRenderStandalone-POB4Q3N3.css +2384 -0
- package/dist/JsonRenderStandalone-POB4Q3N3.css.map +1 -0
- package/dist/JsonRenderStandalone-UsTcST4G.d.cts +23 -0
- package/dist/JsonRenderStandalone-UsTcST4G.d.ts +23 -0
- package/dist/KicadViewer-GV6ZC4AQ.js +124 -0
- package/dist/KicadViewer-GV6ZC4AQ.js.map +1 -0
- package/dist/KicadViewerCore-U7BWZHKJ.js +11 -0
- package/dist/KicadViewerCore-U7BWZHKJ.js.map +1 -0
- package/dist/PdfViewer-CHPDRK46.js +51 -0
- package/dist/PdfViewer-CHPDRK46.js.map +1 -0
- package/dist/PdfViewer-LPYGQETK.css +1899 -0
- package/dist/PdfViewer-LPYGQETK.css.map +1 -0
- package/dist/PdfViewerCore-HJPEHSRA.js +364 -0
- package/dist/PdfViewerCore-HJPEHSRA.js.map +1 -0
- package/dist/PowerPointCore-FPDR2BL4.js +11 -0
- package/dist/PowerPointCore-FPDR2BL4.js.map +1 -0
- package/dist/PowerPointViewer-LQTO6UCU.js +61 -0
- package/dist/PowerPointViewer-LQTO6UCU.js.map +1 -0
- package/dist/StepViewerCore-7W3L3R4E.js +285 -0
- package/dist/StepViewerCore-7W3L3R4E.js.map +1 -0
- package/dist/ThreeViewerCore-N3QJD5QI.js +161 -0
- package/dist/ThreeViewerCore-N3QJD5QI.js.map +1 -0
- package/dist/WordCore-JKSXK2XD.js +11 -0
- package/dist/WordCore-JKSXK2XD.js.map +1 -0
- package/dist/WordViewer-ZHCQMHOH.js +61 -0
- package/dist/WordViewer-ZHCQMHOH.js.map +1 -0
- package/dist/chunk-2SKA3F5U.js +88 -0
- package/dist/chunk-2SKA3F5U.js.map +1 -0
- package/dist/chunk-2UC7YLVX.js +318 -0
- package/dist/chunk-2UC7YLVX.js.map +1 -0
- package/dist/chunk-3R6T3LBR.js +24 -0
- package/dist/chunk-3R6T3LBR.js.map +1 -0
- package/dist/chunk-56WRZM3R.js +398 -0
- package/dist/chunk-56WRZM3R.js.map +1 -0
- package/dist/chunk-7A4FY6FK.js +10226 -0
- package/dist/chunk-7A4FY6FK.js.map +1 -0
- package/dist/chunk-7D4SUZUM.js +38 -0
- package/dist/chunk-7D4SUZUM.js.map +1 -0
- package/dist/chunk-7S67DOHQ.js +436 -0
- package/dist/chunk-7S67DOHQ.js.map +1 -0
- package/dist/chunk-CFKGNAJM.js +14013 -0
- package/dist/chunk-CFKGNAJM.js.map +1 -0
- package/dist/chunk-GAMA3VA7.js +99 -0
- package/dist/chunk-GAMA3VA7.js.map +1 -0
- package/dist/chunk-GYXTSY22.js +639 -0
- package/dist/chunk-GYXTSY22.js.map +1 -0
- package/dist/chunk-K4KGNVL5.js +77 -0
- package/dist/chunk-K4KGNVL5.js.map +1 -0
- package/dist/chunk-KQV7IKET.js +1621 -0
- package/dist/chunk-KQV7IKET.js.map +1 -0
- package/dist/chunk-O3NXUM6C.js +1871 -0
- package/dist/chunk-O3NXUM6C.js.map +1 -0
- package/dist/chunk-PZXSASDY.js +83 -0
- package/dist/chunk-PZXSASDY.js.map +1 -0
- package/dist/chunk-QLVPIM6R.js +595 -0
- package/dist/chunk-QLVPIM6R.js.map +1 -0
- package/dist/chunk-VXJWGLZ7.js +21 -0
- package/dist/chunk-VXJWGLZ7.js.map +1 -0
- package/dist/chunk-XQ562W7I.js +116 -0
- package/dist/chunk-XQ562W7I.js.map +1 -0
- package/dist/components/JsonRender/standalone.cjs +39368 -0
- package/dist/components/JsonRender/standalone.cjs.map +1 -0
- package/dist/components/JsonRender/standalone.css +2384 -0
- package/dist/components/JsonRender/standalone.css.map +1 -0
- package/dist/components/JsonRender/standalone.d.cts +16 -0
- package/dist/components/JsonRender/standalone.d.ts +16 -0
- package/dist/components/JsonRender/standalone.js +38 -0
- package/dist/components/JsonRender/standalone.js.map +1 -0
- package/dist/gerber-2d-entry-OQ4SQRBY.js +3950 -0
- package/dist/gerber-2d-entry-OQ4SQRBY.js.map +1 -0
- package/dist/gerber-3d-entry-DEHDBOO2.js +3679 -0
- package/dist/gerber-3d-entry-DEHDBOO2.js.map +1 -0
- package/dist/gerber-simulation-entry-EBDX72XE.js +1801 -0
- package/dist/gerber-simulation-entry-EBDX72XE.js.map +1 -0
- package/dist/index.cjs +60113 -2970
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +11342 -1708
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +3275 -77
- package/dist/index.d.ts +3275 -77
- package/dist/index.js +18078 -2540
- package/dist/index.js.map +1 -1
- package/dist/provenance/index.cjs +2248 -0
- package/dist/provenance/index.cjs.map +1 -0
- package/dist/provenance/index.css +52 -0
- package/dist/provenance/index.css.map +1 -0
- package/dist/provenance/index.d.cts +12 -0
- package/dist/provenance/index.d.ts +12 -0
- package/dist/provenance/index.js +27 -0
- package/dist/provenance/index.js.map +1 -0
- package/dist/resolveToArrayBuffer-AQIDZHSQ.js +23 -0
- package/dist/resolveToArrayBuffer-AQIDZHSQ.js.map +1 -0
- package/package.json +98 -17
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import {
|
|
2
|
+
injectStyles,
|
|
3
|
+
useResource,
|
|
4
|
+
useResourceContext
|
|
5
|
+
} from "./chunk-GAMA3VA7.js";
|
|
6
|
+
import "./chunk-7D4SUZUM.js";
|
|
7
|
+
|
|
8
|
+
// src/components/JsonRender/domain/WordViewer.tsx
|
|
9
|
+
import React, { useEffect } from "react";
|
|
10
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
var STYLE_ID = "jr-styles-word-viewer";
|
|
12
|
+
var SHEET = `
|
|
13
|
+
.jr-word-viewer { width: 100%; min-width: 0; max-width: 100%; min-height: 400px; }
|
|
14
|
+
.jr-word-viewer--loading, .jr-word-viewer--error {
|
|
15
|
+
padding: 1rem; font-family: var(--jr-font, system-ui, sans-serif);
|
|
16
|
+
color: var(--jr-text-muted, #64748b);
|
|
17
|
+
}
|
|
18
|
+
.jr-word-viewer--error { color: var(--jr-danger, #ef4444); }
|
|
19
|
+
`;
|
|
20
|
+
var LazyWordCore = React.lazy(() => import("./WordCore-JKSXK2XD.js"));
|
|
21
|
+
var WordViewer = ({ props, emit }) => {
|
|
22
|
+
injectStyles(STYLE_ID, SHEET);
|
|
23
|
+
const res = useResource({ resource_id: props.resource_id, url: props.url });
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (res.loading) return;
|
|
26
|
+
if (res.error) {
|
|
27
|
+
emit?.("viewer:error", { resource_id: props.resource_id, error: res.error });
|
|
28
|
+
} else {
|
|
29
|
+
emit?.("viewer:loaded", { resource_id: props.resource_id, mimeType: res.mimeType, fileName: res.fileName });
|
|
30
|
+
}
|
|
31
|
+
}, [res.loading, res.error]);
|
|
32
|
+
const ctx = useResourceContext();
|
|
33
|
+
if (res.loading) return /* @__PURE__ */ jsx("div", { className: "jr-word-viewer jr-word-viewer--loading", children: "Loading\u2026" });
|
|
34
|
+
if (res.error) return /* @__PURE__ */ jsx("div", { className: "jr-word-viewer jr-word-viewer--error", children: res.error });
|
|
35
|
+
const src = res.url;
|
|
36
|
+
const isLegacy = res.fileName?.match(/\.doc$/i);
|
|
37
|
+
if (isLegacy && ctx?.resolvePreviewUrl && props.resource_id) {
|
|
38
|
+
return /* @__PURE__ */ jsx(LegacyFallback, { resourceId: props.resource_id, ctx });
|
|
39
|
+
}
|
|
40
|
+
if (!src) return /* @__PURE__ */ jsx("div", { className: "jr-word-viewer jr-word-viewer--error", children: "No document source" });
|
|
41
|
+
return /* @__PURE__ */ jsx("div", { className: "jr-word-viewer ycw-word-viewer", children: /* @__PURE__ */ jsx(React.Suspense, { fallback: /* @__PURE__ */ jsx("div", { className: "jr-word-viewer--loading", children: "Loading Word viewer\u2026" }), children: /* @__PURE__ */ jsx(LazyWordCore, { src }) }) });
|
|
42
|
+
};
|
|
43
|
+
var LegacyFallback = ({ resourceId, ctx }) => {
|
|
44
|
+
const [previewUrl, setPreviewUrl] = React.useState();
|
|
45
|
+
const [error, setError] = React.useState();
|
|
46
|
+
React.useEffect(() => {
|
|
47
|
+
ctx.resolvePreviewUrl?.(resourceId, "html").then((url) => setPreviewUrl(url)).catch((err) => setError(String(err?.message ?? err)));
|
|
48
|
+
}, [resourceId, ctx]);
|
|
49
|
+
if (error) return /* @__PURE__ */ jsxs("div", { className: "jr-word-viewer jr-word-viewer--error", children: [
|
|
50
|
+
".doc preview failed: ",
|
|
51
|
+
error
|
|
52
|
+
] });
|
|
53
|
+
if (!previewUrl) return /* @__PURE__ */ jsx("div", { className: "jr-word-viewer jr-word-viewer--loading", children: "Converting .doc\u2026" });
|
|
54
|
+
return /* @__PURE__ */ jsx("div", { className: "jr-word-viewer", children: /* @__PURE__ */ jsx("iframe", { src: previewUrl, title: "Word Preview", style: { width: "100%", height: 600, border: "none" } }) });
|
|
55
|
+
};
|
|
56
|
+
var WordViewer_default = WordViewer;
|
|
57
|
+
export {
|
|
58
|
+
WordViewer,
|
|
59
|
+
WordViewer_default as default
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=WordViewer-ZHCQMHOH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/JsonRender/domain/WordViewer.tsx"],"sourcesContent":["import React, { useEffect } from 'react'\nimport { useResource } from '../../../hooks/useResource.js'\nimport { useResourceContext } from '../../../contexts/ResourceContext.js'\nimport { injectStyles } from './injectStyles.js'\n\nconst STYLE_ID = 'jr-styles-word-viewer'\nconst SHEET = `\n.jr-word-viewer { width: 100%; min-width: 0; max-width: 100%; min-height: 400px; }\n.jr-word-viewer--loading, .jr-word-viewer--error {\n padding: 1rem; font-family: var(--jr-font, system-ui, sans-serif);\n color: var(--jr-text-muted, #64748b);\n}\n.jr-word-viewer--error { color: var(--jr-danger, #ef4444); }\n`\n\ninterface Props {\n props: {\n resource_id?: string\n url?: string\n title?: string\n }\n emit?: (event: string, data?: unknown) => void\n}\n\nconst LazyWordCore = React.lazy(() => import('../../ViewerCore/WordCore.js'))\n\nexport const WordViewer: React.FC<Props> = ({ props, emit }) => {\n injectStyles(STYLE_ID, SHEET)\n const res = useResource({ resource_id: props.resource_id, url: props.url })\n\n useEffect(() => {\n if (res.loading) return\n if (res.error) {\n emit?.('viewer:error', { resource_id: props.resource_id, error: res.error })\n } else {\n emit?.('viewer:loaded', { resource_id: props.resource_id, mimeType: res.mimeType, fileName: res.fileName })\n }\n }, [res.loading, res.error])\n\n const ctx = useResourceContext()\n\n if (res.loading) return <div className=\"jr-word-viewer jr-word-viewer--loading\">Loading…</div>\n if (res.error) return <div className=\"jr-word-viewer jr-word-viewer--error\">{res.error}</div>\n\n const src = res.url\n const isLegacy = res.fileName?.match(/\\.doc$/i)\n\n if (isLegacy && ctx?.resolvePreviewUrl && props.resource_id) {\n return <LegacyFallback resourceId={props.resource_id} ctx={ctx} />\n }\n\n if (!src) return <div className=\"jr-word-viewer jr-word-viewer--error\">No document source</div>\n\n return (\n <div className=\"jr-word-viewer ycw-word-viewer\">\n <React.Suspense fallback={<div className=\"jr-word-viewer--loading\">Loading Word viewer…</div>}>\n <LazyWordCore src={src} />\n </React.Suspense>\n </div>\n )\n}\n\nconst LegacyFallback: React.FC<{ resourceId: string; ctx: { resolvePreviewUrl?(id: string, fmt: 'html' | 'pdf'): Promise<string> } }> = ({ resourceId, ctx }) => {\n const [previewUrl, setPreviewUrl] = React.useState<string>()\n const [error, setError] = React.useState<string>()\n\n React.useEffect(() => {\n ctx.resolvePreviewUrl?.(resourceId, 'html')\n .then(url => setPreviewUrl(url))\n .catch(err => setError(String(err?.message ?? err)))\n }, [resourceId, ctx])\n\n if (error) return <div className=\"jr-word-viewer jr-word-viewer--error\">.doc preview failed: {error}</div>\n if (!previewUrl) return <div className=\"jr-word-viewer jr-word-viewer--loading\">Converting .doc…</div>\n\n return (\n <div className=\"jr-word-viewer\">\n <iframe src={previewUrl} title=\"Word Preview\" style={{ width: '100%', height: 600, border: 'none' }} />\n </div>\n )\n}\n\nexport default WordViewer\n"],"mappings":";;;;;;;;AAAA,OAAO,SAAS,iBAAiB;AAyCP,cA+BN,YA/BM;AApC1B,IAAM,WAAW;AACjB,IAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBd,IAAM,eAAe,MAAM,KAAK,MAAM,OAAO,wBAA8B,CAAC;AAErE,IAAM,aAA8B,CAAC,EAAE,OAAO,KAAK,MAAM;AAC9D,eAAa,UAAU,KAAK;AAC5B,QAAM,MAAM,YAAY,EAAE,aAAa,MAAM,aAAa,KAAK,MAAM,IAAI,CAAC;AAE1E,YAAU,MAAM;AACd,QAAI,IAAI,QAAS;AACjB,QAAI,IAAI,OAAO;AACb,aAAO,gBAAgB,EAAE,aAAa,MAAM,aAAa,OAAO,IAAI,MAAM,CAAC;AAAA,IAC7E,OAAO;AACL,aAAO,iBAAiB,EAAE,aAAa,MAAM,aAAa,UAAU,IAAI,UAAU,UAAU,IAAI,SAAS,CAAC;AAAA,IAC5G;AAAA,EACF,GAAG,CAAC,IAAI,SAAS,IAAI,KAAK,CAAC;AAE3B,QAAM,MAAM,mBAAmB;AAE/B,MAAI,IAAI,QAAS,QAAO,oBAAC,SAAI,WAAU,0CAAyC,2BAAQ;AACxF,MAAI,IAAI,MAAO,QAAO,oBAAC,SAAI,WAAU,wCAAwC,cAAI,OAAM;AAEvF,QAAM,MAAM,IAAI;AAChB,QAAM,WAAW,IAAI,UAAU,MAAM,SAAS;AAE9C,MAAI,YAAY,KAAK,qBAAqB,MAAM,aAAa;AAC3D,WAAO,oBAAC,kBAAe,YAAY,MAAM,aAAa,KAAU;AAAA,EAClE;AAEA,MAAI,CAAC,IAAK,QAAO,oBAAC,SAAI,WAAU,wCAAuC,gCAAkB;AAEzF,SACE,oBAAC,SAAI,WAAU,kCACb,8BAAC,MAAM,UAAN,EAAe,UAAU,oBAAC,SAAI,WAAU,2BAA0B,uCAAoB,GACrF,8BAAC,gBAAa,KAAU,GAC1B,GACF;AAEJ;AAEA,IAAM,iBAAkI,CAAC,EAAE,YAAY,IAAI,MAAM;AAC/J,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAiB;AAC3D,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAiB;AAEjD,QAAM,UAAU,MAAM;AACpB,QAAI,oBAAoB,YAAY,MAAM,EACvC,KAAK,SAAO,cAAc,GAAG,CAAC,EAC9B,MAAM,SAAO,SAAS,OAAO,KAAK,WAAW,GAAG,CAAC,CAAC;AAAA,EACvD,GAAG,CAAC,YAAY,GAAG,CAAC;AAEpB,MAAI,MAAO,QAAO,qBAAC,SAAI,WAAU,wCAAuC;AAAA;AAAA,IAAsB;AAAA,KAAM;AACpG,MAAI,CAAC,WAAY,QAAO,oBAAC,SAAI,WAAU,0CAAyC,mCAAgB;AAEhG,SACE,oBAAC,SAAI,WAAU,kBACb,8BAAC,YAAO,KAAK,YAAY,OAAM,gBAAe,OAAO,EAAE,OAAO,QAAQ,QAAQ,KAAK,QAAQ,OAAO,GAAG,GACvG;AAEJ;AAEA,IAAO,qBAAQ;","names":[]}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useResourceContext
|
|
3
|
+
} from "./chunk-GAMA3VA7.js";
|
|
4
|
+
|
|
5
|
+
// src/hooks/useProjectFiles.ts
|
|
6
|
+
import { useState, useEffect, useRef } from "react";
|
|
7
|
+
var DISABLED = { files: [], loading: false, error: null };
|
|
8
|
+
function useProjectFiles(opts) {
|
|
9
|
+
const {
|
|
10
|
+
gitPath,
|
|
11
|
+
extensions,
|
|
12
|
+
enabled,
|
|
13
|
+
recursive = true,
|
|
14
|
+
generateUrls = true,
|
|
15
|
+
deps = []
|
|
16
|
+
} = opts;
|
|
17
|
+
const ctx = useResourceContext();
|
|
18
|
+
const [state, setState] = useState(DISABLED);
|
|
19
|
+
const runRef = useRef(0);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (!enabled || !gitPath || !ctx?.listDirectoryFiles) {
|
|
22
|
+
setState(DISABLED);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const run = ++runRef.current;
|
|
26
|
+
const cancelled = () => run !== runRef.current;
|
|
27
|
+
const discover = async () => {
|
|
28
|
+
setState({ files: [], loading: true, error: null });
|
|
29
|
+
const dir = gitPath.substring(0, gitPath.lastIndexOf("/"));
|
|
30
|
+
if (!dir) {
|
|
31
|
+
setState({ files: [], loading: false, error: "Cannot derive project directory from gitPath" });
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const listOpts = { extensions, recursive, generateUrls };
|
|
35
|
+
const fileList = await ctx.listDirectoryFiles(dir, listOpts);
|
|
36
|
+
if (cancelled()) return;
|
|
37
|
+
const urlFiles = [];
|
|
38
|
+
const needResolve = [];
|
|
39
|
+
for (const entry of fileList) {
|
|
40
|
+
const relativePath = entry.git_path.startsWith(dir + "/") ? entry.git_path.substring(dir.length + 1) : entry.file_name;
|
|
41
|
+
if (entry.download_url) {
|
|
42
|
+
urlFiles.push({ name: relativePath, url: entry.download_url });
|
|
43
|
+
} else {
|
|
44
|
+
needResolve.push({ relativePath, resourceId: entry.resource_id, fileName: entry.file_name });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const resolved = await Promise.allSettled(
|
|
48
|
+
needResolve.map((nr) => ctx.resolveResource(nr.resourceId))
|
|
49
|
+
);
|
|
50
|
+
if (cancelled()) return;
|
|
51
|
+
const contentFiles = [];
|
|
52
|
+
for (let i = 0; i < resolved.length; i++) {
|
|
53
|
+
const r = resolved[i];
|
|
54
|
+
if (r.status === "fulfilled") {
|
|
55
|
+
contentFiles.push({ name: needResolve[i].relativePath, content: r.value.content ?? "" });
|
|
56
|
+
} else {
|
|
57
|
+
console.warn(`[useProjectFiles] Failed to load ${needResolve[i].fileName}:`, r.reason);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const files = [...urlFiles, ...contentFiles];
|
|
61
|
+
if (!cancelled()) {
|
|
62
|
+
setState({
|
|
63
|
+
files,
|
|
64
|
+
loading: false,
|
|
65
|
+
error: files.length === 0 ? "No design files found in project directory" : null
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
discover().catch((e) => {
|
|
70
|
+
if (!cancelled()) {
|
|
71
|
+
setState({
|
|
72
|
+
files: [],
|
|
73
|
+
loading: false,
|
|
74
|
+
error: e instanceof Error ? e.message : String(e)
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
return () => {
|
|
79
|
+
runRef.current++;
|
|
80
|
+
};
|
|
81
|
+
}, [gitPath, enabled, ctx, recursive, generateUrls, ...extensions, ...deps]);
|
|
82
|
+
return state;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export {
|
|
86
|
+
useProjectFiles
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=chunk-2SKA3F5U.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hooks/useProjectFiles.ts"],"sourcesContent":["import { useState, useEffect, useRef } from 'react'\nimport { useResourceContext } from '../contexts/ResourceContext.js'\nimport type { ListDirectoryFilesOptions } from '../types.js'\n\nexport interface ProjectFile {\n name: string\n url?: string\n content?: string\n}\n\nexport interface UseProjectFilesOptions {\n gitPath: string\n extensions: string[]\n enabled: boolean\n recursive?: boolean\n generateUrls?: boolean\n /** Extra deps that trigger re-discovery (e.g. file content for project files). */\n deps?: unknown[]\n}\n\nexport interface UseProjectFilesResult {\n files: ProjectFile[]\n loading: boolean\n error: string | null\n}\n\nconst DISABLED: UseProjectFilesResult = { files: [], loading: false, error: null }\n\n/**\n * Generic hook: discover and load all files matching given extensions\n * under the directory derived from `gitPath`.\n *\n * Works for any viewer that needs sibling-file discovery:\n * KiCad (.kicad_sch/.kicad_pcb), Gerber (.gbr/.drl), etc.\n */\nexport function useProjectFiles(opts: UseProjectFilesOptions): UseProjectFilesResult {\n const {\n gitPath,\n extensions,\n enabled,\n recursive = true,\n generateUrls = true,\n deps = [],\n } = opts\n const ctx = useResourceContext()\n\n const [state, setState] = useState<UseProjectFilesResult>(DISABLED)\n const runRef = useRef(0)\n\n useEffect(() => {\n if (!enabled || !gitPath || !ctx?.listDirectoryFiles) {\n setState(DISABLED)\n return\n }\n\n const run = ++runRef.current\n const cancelled = () => run !== runRef.current\n\n const discover = async () => {\n setState({ files: [], loading: true, error: null })\n\n const dir = gitPath.substring(0, gitPath.lastIndexOf('/'))\n if (!dir) {\n setState({ files: [], loading: false, error: 'Cannot derive project directory from gitPath' })\n return\n }\n\n const listOpts: ListDirectoryFilesOptions = { extensions, recursive, generateUrls }\n const fileList = await ctx.listDirectoryFiles!(dir, listOpts)\n if (cancelled()) return\n\n const urlFiles: ProjectFile[] = []\n const needResolve: { relativePath: string; resourceId: string; fileName: string }[] = []\n\n for (const entry of fileList) {\n const relativePath = entry.git_path.startsWith(dir + '/')\n ? entry.git_path.substring(dir.length + 1)\n : entry.file_name\n\n if (entry.download_url) {\n urlFiles.push({ name: relativePath, url: entry.download_url })\n } else {\n needResolve.push({ relativePath, resourceId: entry.resource_id, fileName: entry.file_name })\n }\n }\n\n const resolved = await Promise.allSettled(\n needResolve.map((nr) => ctx.resolveResource(nr.resourceId)),\n )\n if (cancelled()) return\n\n const contentFiles: ProjectFile[] = []\n for (let i = 0; i < resolved.length; i++) {\n const r = resolved[i]!\n if (r.status === 'fulfilled') {\n contentFiles.push({ name: needResolve[i]!.relativePath, content: r.value.content ?? '' })\n } else {\n console.warn(`[useProjectFiles] Failed to load ${needResolve[i]!.fileName}:`, r.reason)\n }\n }\n\n const files = [...urlFiles, ...contentFiles]\n\n if (!cancelled()) {\n setState({\n files,\n loading: false,\n error: files.length === 0 ? 'No design files found in project directory' : null,\n })\n }\n }\n\n discover().catch((e) => {\n if (!cancelled()) {\n setState({\n files: [],\n loading: false,\n error: e instanceof Error ? e.message : String(e),\n })\n }\n })\n\n return () => { runRef.current++ }\n }, [gitPath, enabled, ctx, recursive, generateUrls, ...extensions, ...deps])\n\n return state\n}\n"],"mappings":";;;;;AAAA,SAAS,UAAU,WAAW,cAAc;AA0B5C,IAAM,WAAkC,EAAE,OAAO,CAAC,GAAG,SAAS,OAAO,OAAO,KAAK;AAS1E,SAAS,gBAAgB,MAAqD;AACnF,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,OAAO,CAAC;AAAA,EACV,IAAI;AACJ,QAAM,MAAM,mBAAmB;AAE/B,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAgC,QAAQ;AAClE,QAAM,SAAS,OAAO,CAAC;AAEvB,YAAU,MAAM;AACd,QAAI,CAAC,WAAW,CAAC,WAAW,CAAC,KAAK,oBAAoB;AACpD,eAAS,QAAQ;AACjB;AAAA,IACF;AAEA,UAAM,MAAM,EAAE,OAAO;AACrB,UAAM,YAAY,MAAM,QAAQ,OAAO;AAEvC,UAAM,WAAW,YAAY;AAC3B,eAAS,EAAE,OAAO,CAAC,GAAG,SAAS,MAAM,OAAO,KAAK,CAAC;AAElD,YAAM,MAAM,QAAQ,UAAU,GAAG,QAAQ,YAAY,GAAG,CAAC;AACzD,UAAI,CAAC,KAAK;AACR,iBAAS,EAAE,OAAO,CAAC,GAAG,SAAS,OAAO,OAAO,+CAA+C,CAAC;AAC7F;AAAA,MACF;AAEA,YAAM,WAAsC,EAAE,YAAY,WAAW,aAAa;AAClF,YAAM,WAAW,MAAM,IAAI,mBAAoB,KAAK,QAAQ;AAC5D,UAAI,UAAU,EAAG;AAEjB,YAAM,WAA0B,CAAC;AACjC,YAAM,cAAgF,CAAC;AAEvF,iBAAW,SAAS,UAAU;AAC5B,cAAM,eAAe,MAAM,SAAS,WAAW,MAAM,GAAG,IACpD,MAAM,SAAS,UAAU,IAAI,SAAS,CAAC,IACvC,MAAM;AAEV,YAAI,MAAM,cAAc;AACtB,mBAAS,KAAK,EAAE,MAAM,cAAc,KAAK,MAAM,aAAa,CAAC;AAAA,QAC/D,OAAO;AACL,sBAAY,KAAK,EAAE,cAAc,YAAY,MAAM,aAAa,UAAU,MAAM,UAAU,CAAC;AAAA,QAC7F;AAAA,MACF;AAEA,YAAM,WAAW,MAAM,QAAQ;AAAA,QAC7B,YAAY,IAAI,CAAC,OAAO,IAAI,gBAAgB,GAAG,UAAU,CAAC;AAAA,MAC5D;AACA,UAAI,UAAU,EAAG;AAEjB,YAAM,eAA8B,CAAC;AACrC,eAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,cAAM,IAAI,SAAS,CAAC;AACpB,YAAI,EAAE,WAAW,aAAa;AAC5B,uBAAa,KAAK,EAAE,MAAM,YAAY,CAAC,EAAG,cAAc,SAAS,EAAE,MAAM,WAAW,GAAG,CAAC;AAAA,QAC1F,OAAO;AACL,kBAAQ,KAAK,oCAAoC,YAAY,CAAC,EAAG,QAAQ,KAAK,EAAE,MAAM;AAAA,QACxF;AAAA,MACF;AAEA,YAAM,QAAQ,CAAC,GAAG,UAAU,GAAG,YAAY;AAE3C,UAAI,CAAC,UAAU,GAAG;AAChB,iBAAS;AAAA,UACP;AAAA,UACA,SAAS;AAAA,UACT,OAAO,MAAM,WAAW,IAAI,+CAA+C;AAAA,QAC7E,CAAC;AAAA,MACH;AAAA,IACF;AAEA,aAAS,EAAE,MAAM,CAAC,MAAM;AACtB,UAAI,CAAC,UAAU,GAAG;AAChB,iBAAS;AAAA,UACP,OAAO,CAAC;AAAA,UACR,SAAS;AAAA,UACT,OAAO,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAAA,QAClD,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAED,WAAO,MAAM;AAAE,aAAO;AAAA,IAAU;AAAA,EAClC,GAAG,CAAC,SAAS,SAAS,KAAK,WAAW,cAAc,GAAG,YAAY,GAAG,IAAI,CAAC;AAE3E,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useXrefChips
|
|
3
|
+
} from "./chunk-56WRZM3R.js";
|
|
4
|
+
import {
|
|
5
|
+
useRevokeBlobUrl
|
|
6
|
+
} from "./chunk-VXJWGLZ7.js";
|
|
7
|
+
|
|
8
|
+
// src/components/ViewerCore/PdfCore.tsx
|
|
9
|
+
import "react";
|
|
10
|
+
import { jsx } from "react/jsx-runtime";
|
|
11
|
+
var PdfCore = ({ src, title, className }) => {
|
|
12
|
+
useRevokeBlobUrl(src);
|
|
13
|
+
return /* @__PURE__ */ jsx("div", { className, style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ jsx(
|
|
14
|
+
"iframe",
|
|
15
|
+
{
|
|
16
|
+
src,
|
|
17
|
+
title: title ?? "PDF",
|
|
18
|
+
style: { width: "100%", height: "100%", border: "none", minHeight: 600 }
|
|
19
|
+
}
|
|
20
|
+
) });
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// src/components/ViewerCore/TextCore.tsx
|
|
24
|
+
import { useMemo, useRef } from "react";
|
|
25
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
26
|
+
var TextCore = ({
|
|
27
|
+
content,
|
|
28
|
+
className,
|
|
29
|
+
onXrefClick,
|
|
30
|
+
onLinkClick,
|
|
31
|
+
lineNumbers = true,
|
|
32
|
+
wordWrap = false
|
|
33
|
+
}) => {
|
|
34
|
+
const containerRef = useRef(null);
|
|
35
|
+
const { processedContent } = useXrefChips(containerRef, content, onXrefClick, onLinkClick);
|
|
36
|
+
const lines = useMemo(() => processedContent.split("\n"), [processedContent]);
|
|
37
|
+
const preStyle = wordWrap ? { whiteSpace: "pre-wrap", wordBreak: "break-word" } : void 0;
|
|
38
|
+
return /* @__PURE__ */ jsx2(
|
|
39
|
+
"div",
|
|
40
|
+
{
|
|
41
|
+
className,
|
|
42
|
+
ref: containerRef,
|
|
43
|
+
"data-line-numbers": lineNumbers ? "true" : "false",
|
|
44
|
+
"data-word-wrap": wordWrap ? "true" : "false",
|
|
45
|
+
children: /* @__PURE__ */ jsx2("table", { className: "ycw-text-viewer-table", children: /* @__PURE__ */ jsx2("tbody", { children: lines.map((line, i) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
46
|
+
lineNumbers ? /* @__PURE__ */ jsx2("td", { className: "ycw-text-viewer-line-num", children: i + 1 }) : null,
|
|
47
|
+
/* @__PURE__ */ jsx2("td", { className: "ycw-text-viewer-line-content", children: /* @__PURE__ */ jsx2("pre", { style: preStyle, children: line || " " }) })
|
|
48
|
+
] }, i)) }) })
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// src/components/ViewerCore/CodeCore.tsx
|
|
54
|
+
import { useMemo as useMemo2, useRef as useRef2 } from "react";
|
|
55
|
+
import { Streamdown } from "streamdown";
|
|
56
|
+
import { code } from "@streamdown/code";
|
|
57
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
58
|
+
var plugins = { code };
|
|
59
|
+
var CodeCore = ({ content, language, className, onXrefClick, onLinkClick }) => {
|
|
60
|
+
const containerRef = useRef2(null);
|
|
61
|
+
const { processedContent } = useXrefChips(containerRef, content, onXrefClick, onLinkClick);
|
|
62
|
+
const fenced = useMemo2(
|
|
63
|
+
() => "```" + (language ?? "") + "\n" + processedContent + "\n```",
|
|
64
|
+
[processedContent, language]
|
|
65
|
+
);
|
|
66
|
+
return /* @__PURE__ */ jsx3("div", { className, ref: containerRef, children: /* @__PURE__ */ jsx3(Streamdown, { plugins, children: fenced }) });
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// src/components/ViewerCore/MarkdownCore.tsx
|
|
70
|
+
import { useRef as useRef3 } from "react";
|
|
71
|
+
import { Streamdown as Streamdown2 } from "streamdown";
|
|
72
|
+
import { code as code2 } from "@streamdown/code";
|
|
73
|
+
import { mermaid } from "@streamdown/mermaid";
|
|
74
|
+
import { createMathPlugin } from "@streamdown/math";
|
|
75
|
+
import { cjk } from "@streamdown/cjk";
|
|
76
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
77
|
+
var math = createMathPlugin({ singleDollarTextMath: true });
|
|
78
|
+
var defaultPlugins = { code: code2, mermaid, math, cjk };
|
|
79
|
+
var MarkdownCore = ({ content, className, plugins: extraPlugins, onXrefClick, onLinkClick }) => {
|
|
80
|
+
const containerRef = useRef3(null);
|
|
81
|
+
const { processedContent } = useXrefChips(containerRef, content, onXrefClick, onLinkClick);
|
|
82
|
+
const handleContainerClick = (e) => {
|
|
83
|
+
const target = e.target;
|
|
84
|
+
const anchor = target.closest("a");
|
|
85
|
+
if (anchor?.href) {
|
|
86
|
+
const href = anchor.getAttribute("href") ?? "";
|
|
87
|
+
if (href.startsWith("xref:") && onXrefClick) {
|
|
88
|
+
e.preventDefault();
|
|
89
|
+
onXrefClick({ ref: href.slice(5) });
|
|
90
|
+
} else if (onLinkClick) {
|
|
91
|
+
e.preventDefault();
|
|
92
|
+
onLinkClick(href);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
return /* @__PURE__ */ jsx4("div", { className, ref: containerRef, onClick: handleContainerClick, children: /* @__PURE__ */ jsx4(Streamdown2, { plugins: { ...defaultPlugins, ...extraPlugins }, children: processedContent }) });
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// src/components/ViewerCore/JsonCore.tsx
|
|
100
|
+
import { useMemo as useMemo3, useState, useCallback, useRef as useRef4 } from "react";
|
|
101
|
+
import { Fragment, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
102
|
+
var JsonNode = ({ label, value, depth, defaultExpanded }) => {
|
|
103
|
+
const [expanded, setExpanded] = useState(depth < defaultExpanded);
|
|
104
|
+
const toggle = useCallback(() => setExpanded((e) => !e), []);
|
|
105
|
+
if (value === null) {
|
|
106
|
+
return /* @__PURE__ */ jsxs2("div", { className: "ycw-json-leaf", style: { paddingLeft: depth * 16 }, children: [
|
|
107
|
+
label && /* @__PURE__ */ jsxs2("span", { className: "ycw-json-key", children: [
|
|
108
|
+
label,
|
|
109
|
+
": "
|
|
110
|
+
] }),
|
|
111
|
+
/* @__PURE__ */ jsx5("span", { className: "ycw-json-null", children: "null" })
|
|
112
|
+
] });
|
|
113
|
+
}
|
|
114
|
+
if (typeof value === "boolean") {
|
|
115
|
+
return /* @__PURE__ */ jsxs2("div", { className: "ycw-json-leaf", style: { paddingLeft: depth * 16 }, children: [
|
|
116
|
+
label && /* @__PURE__ */ jsxs2("span", { className: "ycw-json-key", children: [
|
|
117
|
+
label,
|
|
118
|
+
": "
|
|
119
|
+
] }),
|
|
120
|
+
/* @__PURE__ */ jsx5("span", { className: "ycw-json-bool", children: String(value) })
|
|
121
|
+
] });
|
|
122
|
+
}
|
|
123
|
+
if (typeof value === "number" || typeof value === "bigint") {
|
|
124
|
+
return /* @__PURE__ */ jsxs2("div", { className: "ycw-json-leaf", style: { paddingLeft: depth * 16 }, children: [
|
|
125
|
+
label && /* @__PURE__ */ jsxs2("span", { className: "ycw-json-key", children: [
|
|
126
|
+
label,
|
|
127
|
+
": "
|
|
128
|
+
] }),
|
|
129
|
+
/* @__PURE__ */ jsx5("span", { className: "ycw-json-number", children: String(value) })
|
|
130
|
+
] });
|
|
131
|
+
}
|
|
132
|
+
if (typeof value === "string") {
|
|
133
|
+
return /* @__PURE__ */ jsxs2("div", { className: "ycw-json-leaf", style: { paddingLeft: depth * 16 }, children: [
|
|
134
|
+
label && /* @__PURE__ */ jsxs2("span", { className: "ycw-json-key", children: [
|
|
135
|
+
label,
|
|
136
|
+
": "
|
|
137
|
+
] }),
|
|
138
|
+
/* @__PURE__ */ jsxs2("span", { className: "ycw-json-string", children: [
|
|
139
|
+
'"',
|
|
140
|
+
value,
|
|
141
|
+
'"'
|
|
142
|
+
] })
|
|
143
|
+
] });
|
|
144
|
+
}
|
|
145
|
+
if (Array.isArray(value)) {
|
|
146
|
+
return /* @__PURE__ */ jsxs2("div", { style: { paddingLeft: depth * 16 }, children: [
|
|
147
|
+
/* @__PURE__ */ jsx5("span", { className: "ycw-json-toggle", onClick: toggle, children: expanded ? "\u25BC" : "\u25B6" }),
|
|
148
|
+
label && /* @__PURE__ */ jsxs2("span", { className: "ycw-json-key", children: [
|
|
149
|
+
label,
|
|
150
|
+
": "
|
|
151
|
+
] }),
|
|
152
|
+
/* @__PURE__ */ jsx5("span", { className: "ycw-json-bracket", children: "[" }),
|
|
153
|
+
!expanded && /* @__PURE__ */ jsxs2("span", { className: "ycw-json-collapsed", children: [
|
|
154
|
+
" ",
|
|
155
|
+
value.length,
|
|
156
|
+
" items ]"
|
|
157
|
+
] }),
|
|
158
|
+
expanded && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
159
|
+
value.map((item, i) => /* @__PURE__ */ jsx5(JsonNode, { label: String(i), value: item, depth: depth + 1, defaultExpanded }, i)),
|
|
160
|
+
/* @__PURE__ */ jsx5("div", { style: { paddingLeft: depth * 16 }, children: /* @__PURE__ */ jsx5("span", { className: "ycw-json-bracket", children: "]" }) })
|
|
161
|
+
] })
|
|
162
|
+
] });
|
|
163
|
+
}
|
|
164
|
+
if (typeof value === "object") {
|
|
165
|
+
const entries = Object.entries(value);
|
|
166
|
+
return /* @__PURE__ */ jsxs2("div", { style: { paddingLeft: depth * 16 }, children: [
|
|
167
|
+
/* @__PURE__ */ jsx5("span", { className: "ycw-json-toggle", onClick: toggle, children: expanded ? "\u25BC" : "\u25B6" }),
|
|
168
|
+
label && /* @__PURE__ */ jsxs2("span", { className: "ycw-json-key", children: [
|
|
169
|
+
label,
|
|
170
|
+
": "
|
|
171
|
+
] }),
|
|
172
|
+
/* @__PURE__ */ jsx5("span", { className: "ycw-json-bracket", children: "{" }),
|
|
173
|
+
!expanded && /* @__PURE__ */ jsxs2("span", { className: "ycw-json-collapsed", children: [
|
|
174
|
+
" ",
|
|
175
|
+
entries.length,
|
|
176
|
+
" keys ",
|
|
177
|
+
"}"
|
|
178
|
+
] }),
|
|
179
|
+
expanded && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
180
|
+
entries.map(([k, v]) => /* @__PURE__ */ jsx5(JsonNode, { label: k, value: v, depth: depth + 1, defaultExpanded }, k)),
|
|
181
|
+
/* @__PURE__ */ jsx5("div", { style: { paddingLeft: depth * 16 }, children: /* @__PURE__ */ jsx5("span", { className: "ycw-json-bracket", children: "}" }) })
|
|
182
|
+
] })
|
|
183
|
+
] });
|
|
184
|
+
}
|
|
185
|
+
return null;
|
|
186
|
+
};
|
|
187
|
+
var JsonCore = ({ data, defaultExpanded = 2, className, onXrefClick, onLinkClick }) => {
|
|
188
|
+
const containerRef = useRef4(null);
|
|
189
|
+
const rawContent = typeof data === "string" ? data : JSON.stringify(data, null, 2);
|
|
190
|
+
const { processedContent } = useXrefChips(containerRef, rawContent, onXrefClick, onLinkClick);
|
|
191
|
+
const parsed = useMemo3(() => {
|
|
192
|
+
try {
|
|
193
|
+
return { ok: true, value: JSON.parse(processedContent) };
|
|
194
|
+
} catch {
|
|
195
|
+
return { ok: false, value: processedContent };
|
|
196
|
+
}
|
|
197
|
+
}, [processedContent]);
|
|
198
|
+
if (!parsed.ok) {
|
|
199
|
+
return /* @__PURE__ */ jsx5("div", { className, ref: containerRef, children: /* @__PURE__ */ jsx5("pre", { style: { margin: 0, whiteSpace: "pre-wrap", wordBreak: "break-word" }, children: parsed.value }) });
|
|
200
|
+
}
|
|
201
|
+
return /* @__PURE__ */ jsx5("div", { className, ref: containerRef, children: /* @__PURE__ */ jsx5(JsonNode, { label: null, value: parsed.value, depth: 0, defaultExpanded }) });
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
// src/components/ViewerCore/ImageCore.tsx
|
|
205
|
+
import { useState as useState2, useRef as useRef5, useCallback as useCallback2 } from "react";
|
|
206
|
+
import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
207
|
+
var MIN_SCALE = 0.1;
|
|
208
|
+
var ImageCore = ({
|
|
209
|
+
src,
|
|
210
|
+
alt,
|
|
211
|
+
className,
|
|
212
|
+
zoomInLabel = "+",
|
|
213
|
+
zoomOutLabel = "\u2212",
|
|
214
|
+
resetLabel = "Reset",
|
|
215
|
+
zoom = true,
|
|
216
|
+
maxScale = 10
|
|
217
|
+
}) => {
|
|
218
|
+
useRevokeBlobUrl(src);
|
|
219
|
+
const [scale, setScale] = useState2(1);
|
|
220
|
+
const [position, setPosition] = useState2({ x: 0, y: 0 });
|
|
221
|
+
const [isDragging, setIsDragging] = useState2(false);
|
|
222
|
+
const dragStart = useRef5({ x: 0, y: 0 });
|
|
223
|
+
const clampMax = Math.max(1, maxScale);
|
|
224
|
+
const handleWheel = useCallback2((e) => {
|
|
225
|
+
if (!zoom) return;
|
|
226
|
+
e.preventDefault();
|
|
227
|
+
const delta = e.deltaY > 0 ? 0.9 : 1.1;
|
|
228
|
+
setScale((prev) => Math.min(Math.max(prev * delta, MIN_SCALE), clampMax));
|
|
229
|
+
}, [zoom, clampMax]);
|
|
230
|
+
const handleMouseDown = useCallback2((e) => {
|
|
231
|
+
if (!zoom) return;
|
|
232
|
+
setIsDragging(true);
|
|
233
|
+
dragStart.current = { x: e.clientX - position.x, y: e.clientY - position.y };
|
|
234
|
+
}, [position, zoom]);
|
|
235
|
+
const handleMouseMove = useCallback2((e) => {
|
|
236
|
+
if (!isDragging) return;
|
|
237
|
+
setPosition({
|
|
238
|
+
x: e.clientX - dragStart.current.x,
|
|
239
|
+
y: e.clientY - dragStart.current.y
|
|
240
|
+
});
|
|
241
|
+
}, [isDragging]);
|
|
242
|
+
const handleMouseUp = useCallback2(() => setIsDragging(false), []);
|
|
243
|
+
const resetView = useCallback2(() => {
|
|
244
|
+
setScale(1);
|
|
245
|
+
setPosition({ x: 0, y: 0 });
|
|
246
|
+
}, []);
|
|
247
|
+
return /* @__PURE__ */ jsxs3(
|
|
248
|
+
"div",
|
|
249
|
+
{
|
|
250
|
+
className,
|
|
251
|
+
"data-zoom": zoom ? "true" : "false",
|
|
252
|
+
"data-max-scale": String(clampMax),
|
|
253
|
+
children: [
|
|
254
|
+
zoom ? /* @__PURE__ */ jsxs3("div", { className: "ycw-image-toolbar", children: [
|
|
255
|
+
/* @__PURE__ */ jsx6("button", { onClick: () => setScale((s) => Math.min(s * 1.2, clampMax)), title: zoomInLabel, children: zoomInLabel }),
|
|
256
|
+
/* @__PURE__ */ jsx6("button", { onClick: () => setScale((s) => Math.max(s * 0.8, MIN_SCALE)), title: zoomOutLabel, children: zoomOutLabel }),
|
|
257
|
+
/* @__PURE__ */ jsx6("button", { onClick: resetView, children: resetLabel }),
|
|
258
|
+
/* @__PURE__ */ jsxs3("span", { className: "ycw-image-scale", children: [
|
|
259
|
+
Math.round(scale * 100),
|
|
260
|
+
"%"
|
|
261
|
+
] })
|
|
262
|
+
] }) : null,
|
|
263
|
+
/* @__PURE__ */ jsx6(
|
|
264
|
+
"div",
|
|
265
|
+
{
|
|
266
|
+
className: "ycw-image-canvas",
|
|
267
|
+
onWheel: zoom ? handleWheel : void 0,
|
|
268
|
+
onMouseDown: zoom ? handleMouseDown : void 0,
|
|
269
|
+
onMouseMove: zoom ? handleMouseMove : void 0,
|
|
270
|
+
onMouseUp: zoom ? handleMouseUp : void 0,
|
|
271
|
+
onMouseLeave: zoom ? handleMouseUp : void 0,
|
|
272
|
+
style: { cursor: zoom ? isDragging ? "grabbing" : "grab" : "default" },
|
|
273
|
+
children: /* @__PURE__ */ jsx6(
|
|
274
|
+
"img",
|
|
275
|
+
{
|
|
276
|
+
src,
|
|
277
|
+
alt: alt ?? "",
|
|
278
|
+
style: zoom ? {
|
|
279
|
+
transform: `translate(${position.x}px, ${position.y}px) scale(${scale})`,
|
|
280
|
+
transformOrigin: "center center"
|
|
281
|
+
} : void 0,
|
|
282
|
+
draggable: false
|
|
283
|
+
}
|
|
284
|
+
)
|
|
285
|
+
}
|
|
286
|
+
)
|
|
287
|
+
]
|
|
288
|
+
}
|
|
289
|
+
);
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
// src/components/ViewerCore/VideoCore.tsx
|
|
293
|
+
import "react";
|
|
294
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
295
|
+
var VideoCore = ({ src, mimeType, className }) => {
|
|
296
|
+
useRevokeBlobUrl(src);
|
|
297
|
+
return /* @__PURE__ */ jsx7("div", { className, children: /* @__PURE__ */ jsx7("video", { src, controls: true, className: "ycw-video-element", children: mimeType && /* @__PURE__ */ jsx7("source", { src, type: mimeType }) }) });
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
// src/components/ViewerCore/AudioCore.tsx
|
|
301
|
+
import "react";
|
|
302
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
303
|
+
var AudioCore = ({ src, mimeType, className }) => {
|
|
304
|
+
useRevokeBlobUrl(src);
|
|
305
|
+
return /* @__PURE__ */ jsx8("div", { className, children: /* @__PURE__ */ jsx8("audio", { src, controls: true, className: "ycw-audio-element", children: mimeType && /* @__PURE__ */ jsx8("source", { src, type: mimeType }) }) });
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
export {
|
|
309
|
+
TextCore,
|
|
310
|
+
CodeCore,
|
|
311
|
+
MarkdownCore,
|
|
312
|
+
JsonCore,
|
|
313
|
+
ImageCore,
|
|
314
|
+
VideoCore,
|
|
315
|
+
AudioCore,
|
|
316
|
+
PdfCore
|
|
317
|
+
};
|
|
318
|
+
//# sourceMappingURL=chunk-2UC7YLVX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ViewerCore/PdfCore.tsx","../src/components/ViewerCore/TextCore.tsx","../src/components/ViewerCore/CodeCore.tsx","../src/components/ViewerCore/MarkdownCore.tsx","../src/components/ViewerCore/JsonCore.tsx","../src/components/ViewerCore/ImageCore.tsx","../src/components/ViewerCore/VideoCore.tsx","../src/components/ViewerCore/AudioCore.tsx"],"sourcesContent":["import React from 'react'\nimport { useRevokeBlobUrl } from './hooks/useRevokeBlobUrl.js'\n\nexport interface PdfCoreProps {\n src: string\n title?: string\n className?: string\n}\n\nexport const PdfCore: React.FC<PdfCoreProps> = ({ src, title, className }) => {\n useRevokeBlobUrl(src)\n return (\n <div className={className} style={{ width: '100%', height: '100%' }}>\n <iframe\n src={src}\n title={title ?? 'PDF'}\n style={{ width: '100%', height: '100%', border: 'none', minHeight: 600 }}\n />\n </div>\n )\n}\n","import React, { useMemo, useRef } from 'react'\nimport { useXrefChips } from './hooks/useXrefChips'\n\nexport interface TextCoreProps {\n content: string\n className?: string\n onXrefClick?: (xref: unknown) => void\n onLinkClick?: (url: string) => void\n /**\n * CWRF-013 Phase 0 PR #5 — when explicitly false, hide the left-column\n * line numbers (each line just renders the content cell). Default true\n * preserves the historical TextCore rendering.\n */\n lineNumbers?: boolean\n /**\n * CWRF-013 Phase 0 PR #5 — when true, render the line content with\n * `white-space: pre-wrap` so long lines wrap at the container edge\n * instead of overflowing horizontally. Default false preserves the\n * historical `pre` no-wrap behaviour.\n */\n wordWrap?: boolean\n}\n\nexport const TextCore: React.FC<TextCoreProps> = ({\n content,\n className,\n onXrefClick,\n onLinkClick,\n lineNumbers = true,\n wordWrap = false,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const { processedContent } = useXrefChips(containerRef, content, onXrefClick, onLinkClick)\n const lines = useMemo(() => processedContent.split('\\n'), [processedContent])\n\n const preStyle: React.CSSProperties | undefined = wordWrap\n ? { whiteSpace: 'pre-wrap', wordBreak: 'break-word' }\n : undefined\n\n return (\n <div\n className={className}\n ref={containerRef}\n data-line-numbers={lineNumbers ? 'true' : 'false'}\n data-word-wrap={wordWrap ? 'true' : 'false'}\n >\n <table className=\"ycw-text-viewer-table\">\n <tbody>\n {lines.map((line, i) => (\n <tr key={i}>\n {lineNumbers ? (\n <td className=\"ycw-text-viewer-line-num\">{i + 1}</td>\n ) : null}\n <td className=\"ycw-text-viewer-line-content\">\n <pre style={preStyle}>{line || ' '}</pre>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )\n}\n","import React, { useMemo, useRef } from 'react'\nimport { Streamdown } from 'streamdown'\nimport { code } from '@streamdown/code'\nimport { useXrefChips } from './hooks/useXrefChips'\n\nconst plugins = { code }\n\nexport interface CodeCoreProps {\n content: string\n language?: string\n className?: string\n onXrefClick?: (xref: unknown) => void\n onLinkClick?: (url: string) => void\n}\n\nexport const CodeCore: React.FC<CodeCoreProps> = ({ content, language, className, onXrefClick, onLinkClick }) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const { processedContent } = useXrefChips(containerRef, content, onXrefClick, onLinkClick)\n\n const fenced = useMemo(\n () => '```' + (language ?? '') + '\\n' + processedContent + '\\n```',\n [processedContent, language],\n )\n\n return (\n <div className={className} ref={containerRef}>\n <Streamdown plugins={plugins}>{fenced}</Streamdown>\n </div>\n )\n}\n","import React, { useRef } from 'react'\nimport { Streamdown } from 'streamdown'\nimport { code } from '@streamdown/code'\nimport { mermaid } from '@streamdown/mermaid'\nimport { createMathPlugin } from '@streamdown/math'\nimport { cjk } from '@streamdown/cjk'\nimport { useXrefChips } from './hooks/useXrefChips'\n\nconst math = createMathPlugin({ singleDollarTextMath: true })\nconst defaultPlugins = { code, mermaid, math, cjk }\n\nexport interface MarkdownCoreProps {\n content: string\n className?: string\n plugins?: Record<string, unknown>\n onXrefClick?: (xref: unknown) => void\n onLinkClick?: (url: string) => void\n}\n\nexport const MarkdownCore: React.FC<MarkdownCoreProps> = ({ content, className, plugins: extraPlugins, onXrefClick, onLinkClick }) => {\n const containerRef = useRef<HTMLDivElement>(null)\n\n const { processedContent } = useXrefChips(containerRef, content, onXrefClick, onLinkClick)\n\n const handleContainerClick = (e: React.MouseEvent) => {\n const target = e.target as HTMLElement\n const anchor = target.closest('a')\n if (anchor?.href) {\n const href = anchor.getAttribute('href') ?? ''\n if (href.startsWith('xref:') && onXrefClick) {\n e.preventDefault()\n onXrefClick({ ref: href.slice(5) })\n } else if (onLinkClick) {\n e.preventDefault()\n onLinkClick(href)\n }\n }\n }\n\n return (\n <div className={className} ref={containerRef} onClick={handleContainerClick}>\n <Streamdown plugins={{ ...defaultPlugins, ...extraPlugins }}>{processedContent}</Streamdown>\n </div>\n )\n}\n","import React, { useMemo, useState, useCallback, useRef } from 'react'\nimport { useXrefChips } from './hooks/useXrefChips'\n\nexport interface JsonCoreProps {\n data: string | object\n defaultExpanded?: number\n className?: string\n onXrefClick?: (xref: unknown) => void\n onLinkClick?: (url: string) => void\n}\n\ninterface JsonNodeProps {\n label: string | null\n value: unknown\n depth: number\n defaultExpanded: number\n}\n\nconst JsonNode: React.FC<JsonNodeProps> = ({ label, value, depth, defaultExpanded }) => {\n const [expanded, setExpanded] = useState(depth < defaultExpanded)\n\n const toggle = useCallback(() => setExpanded(e => !e), [])\n\n if (value === null) {\n return <div className=\"ycw-json-leaf\" style={{ paddingLeft: depth * 16 }}>\n {label && <span className=\"ycw-json-key\">{label}: </span>}\n <span className=\"ycw-json-null\">null</span>\n </div>\n }\n if (typeof value === 'boolean') {\n return <div className=\"ycw-json-leaf\" style={{ paddingLeft: depth * 16 }}>\n {label && <span className=\"ycw-json-key\">{label}: </span>}\n <span className=\"ycw-json-bool\">{String(value)}</span>\n </div>\n }\n if (typeof value === 'number' || typeof value === 'bigint') {\n return <div className=\"ycw-json-leaf\" style={{ paddingLeft: depth * 16 }}>\n {label && <span className=\"ycw-json-key\">{label}: </span>}\n <span className=\"ycw-json-number\">{String(value)}</span>\n </div>\n }\n if (typeof value === 'string') {\n return <div className=\"ycw-json-leaf\" style={{ paddingLeft: depth * 16 }}>\n {label && <span className=\"ycw-json-key\">{label}: </span>}\n <span className=\"ycw-json-string\">\"{value}\"</span>\n </div>\n }\n if (Array.isArray(value)) {\n return <div style={{ paddingLeft: depth * 16 }}>\n <span className=\"ycw-json-toggle\" onClick={toggle}>{expanded ? '▼' : '▶'}</span>\n {label && <span className=\"ycw-json-key\">{label}: </span>}\n <span className=\"ycw-json-bracket\">[</span>\n {!expanded && <span className=\"ycw-json-collapsed\"> {value.length} items ]</span>}\n {expanded && <>\n {value.map((item, i) => (\n <JsonNode key={i} label={String(i)} value={item} depth={depth + 1} defaultExpanded={defaultExpanded} />\n ))}\n <div style={{ paddingLeft: depth * 16 }}><span className=\"ycw-json-bracket\">]</span></div>\n </>}\n </div>\n }\n if (typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>)\n return <div style={{ paddingLeft: depth * 16 }}>\n <span className=\"ycw-json-toggle\" onClick={toggle}>{expanded ? '▼' : '▶'}</span>\n {label && <span className=\"ycw-json-key\">{label}: </span>}\n <span className=\"ycw-json-bracket\">{'{'}</span>\n {!expanded && <span className=\"ycw-json-collapsed\"> {entries.length} keys {'}'}</span>}\n {expanded && <>\n {entries.map(([k, v]) => (\n <JsonNode key={k} label={k} value={v} depth={depth + 1} defaultExpanded={defaultExpanded} />\n ))}\n <div style={{ paddingLeft: depth * 16 }}><span className=\"ycw-json-bracket\">{'}'}</span></div>\n </>}\n </div>\n }\n return null\n}\n\nexport const JsonCore: React.FC<JsonCoreProps> = ({ data, defaultExpanded = 2, className, onXrefClick, onLinkClick }) => {\n const containerRef = useRef<HTMLDivElement>(null)\n\n const rawContent = typeof data === 'string' ? data : JSON.stringify(data, null, 2)\n const { processedContent } = useXrefChips(containerRef, rawContent, onXrefClick, onLinkClick)\n\n const parsed = useMemo(() => {\n try {\n return { ok: true as const, value: JSON.parse(processedContent) }\n } catch {\n return { ok: false as const, value: processedContent }\n }\n }, [processedContent])\n\n if (!parsed.ok) {\n return (\n <div className={className} ref={containerRef}>\n <pre style={{ margin: 0, whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>{parsed.value as string}</pre>\n </div>\n )\n }\n\n return (\n <div className={className} ref={containerRef}>\n <JsonNode label={null} value={parsed.value} depth={0} defaultExpanded={defaultExpanded} />\n </div>\n )\n}\n","import React, { useState, useRef, useCallback } from 'react'\nimport { useRevokeBlobUrl } from './hooks/useRevokeBlobUrl.js'\n\nexport interface ImageCoreProps {\n src: string\n alt?: string\n className?: string\n zoomInLabel?: string\n zoomOutLabel?: string\n resetLabel?: string\n /**\n * CWRF-013 Phase 0 PR #5 — when false, disable the interactive zoom /\n * pan affordances: no toolbar, no wheel zoom, no drag pan. The image\n * renders at natural scale with cursor=default. Default true preserves\n * the historical pan-zoom interactive behaviour.\n */\n zoom?: boolean\n /**\n * CWRF-013 Phase 0 PR #5 — cap the maximum zoom factor (applied to both\n * wheel zoom-in and the toolbar zoom-in button). Default 10 matches the\n * pre-Phase 0 hardcoded limit.\n */\n maxScale?: number\n}\n\nconst MIN_SCALE = 0.1\n\nexport const ImageCore: React.FC<ImageCoreProps> = ({\n src, alt, className,\n zoomInLabel = '+',\n zoomOutLabel = '−',\n resetLabel = 'Reset',\n zoom = true,\n maxScale = 10,\n}) => {\n useRevokeBlobUrl(src)\n\n const [scale, setScale] = useState(1)\n const [position, setPosition] = useState({ x: 0, y: 0 })\n const [isDragging, setIsDragging] = useState(false)\n const dragStart = useRef({ x: 0, y: 0 })\n\n const clampMax = Math.max(1, maxScale)\n\n const handleWheel = useCallback((e: React.WheelEvent) => {\n if (!zoom) return\n e.preventDefault()\n const delta = e.deltaY > 0 ? 0.9 : 1.1\n setScale(prev => Math.min(Math.max(prev * delta, MIN_SCALE), clampMax))\n }, [zoom, clampMax])\n\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n if (!zoom) return\n setIsDragging(true)\n dragStart.current = { x: e.clientX - position.x, y: e.clientY - position.y }\n }, [position, zoom])\n\n const handleMouseMove = useCallback((e: React.MouseEvent) => {\n if (!isDragging) return\n setPosition({\n x: e.clientX - dragStart.current.x,\n y: e.clientY - dragStart.current.y,\n })\n }, [isDragging])\n\n const handleMouseUp = useCallback(() => setIsDragging(false), [])\n\n const resetView = useCallback(() => {\n setScale(1)\n setPosition({ x: 0, y: 0 })\n }, [])\n\n return (\n <div\n className={className}\n data-zoom={zoom ? 'true' : 'false'}\n data-max-scale={String(clampMax)}\n >\n {zoom ? (\n <div className=\"ycw-image-toolbar\">\n <button onClick={() => setScale(s => Math.min(s * 1.2, clampMax))} title={zoomInLabel}>{zoomInLabel}</button>\n <button onClick={() => setScale(s => Math.max(s * 0.8, MIN_SCALE))} title={zoomOutLabel}>{zoomOutLabel}</button>\n <button onClick={resetView}>{resetLabel}</button>\n <span className=\"ycw-image-scale\">{Math.round(scale * 100)}%</span>\n </div>\n ) : null}\n <div\n className=\"ycw-image-canvas\"\n onWheel={zoom ? handleWheel : undefined}\n onMouseDown={zoom ? handleMouseDown : undefined}\n onMouseMove={zoom ? handleMouseMove : undefined}\n onMouseUp={zoom ? handleMouseUp : undefined}\n onMouseLeave={zoom ? handleMouseUp : undefined}\n style={{ cursor: zoom ? (isDragging ? 'grabbing' : 'grab') : 'default' }}\n >\n <img\n src={src}\n alt={alt ?? ''}\n style={\n zoom\n ? {\n transform: `translate(${position.x}px, ${position.y}px) scale(${scale})`,\n transformOrigin: 'center center',\n }\n : undefined\n }\n draggable={false}\n />\n </div>\n </div>\n )\n}\n","import React from 'react'\nimport { useRevokeBlobUrl } from './hooks/useRevokeBlobUrl.js'\n\nexport interface VideoCoreProps {\n src: string\n mimeType?: string\n className?: string\n}\n\nexport const VideoCore: React.FC<VideoCoreProps> = ({ src, mimeType, className }) => {\n useRevokeBlobUrl(src)\n\n return (\n <div className={className}>\n <video src={src} controls className=\"ycw-video-element\">\n {mimeType && <source src={src} type={mimeType} />}\n </video>\n </div>\n )\n}\n","import React from 'react'\nimport { useRevokeBlobUrl } from './hooks/useRevokeBlobUrl.js'\n\nexport interface AudioCoreProps {\n src: string\n mimeType?: string\n className?: string\n}\n\nexport const AudioCore: React.FC<AudioCoreProps> = ({ src, mimeType, className }) => {\n useRevokeBlobUrl(src)\n\n return (\n <div className={className}>\n <audio src={src} controls className=\"ycw-audio-element\">\n {mimeType && <source src={src} type={mimeType} />}\n </audio>\n </div>\n )\n}\n"],"mappings":";;;;;;;;AAAA,OAAkB;AAaZ;AAJC,IAAM,UAAkC,CAAC,EAAE,KAAK,OAAO,UAAU,MAAM;AAC5E,mBAAiB,GAAG;AACpB,SACE,oBAAC,SAAI,WAAsB,OAAO,EAAE,OAAO,QAAQ,QAAQ,OAAO,GAChE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO,SAAS;AAAA,MAChB,OAAO,EAAE,OAAO,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,WAAW,IAAI;AAAA;AAAA,EACzE,GACF;AAEJ;;;ACpBA,SAAgB,SAAS,cAAc;AAiD3B,SAEI,OAAAA,MAFJ;AA1BL,IAAM,WAAoC,CAAC;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,WAAW;AACb,MAAM;AACJ,QAAM,eAAe,OAAuB,IAAI;AAChD,QAAM,EAAE,iBAAiB,IAAI,aAAa,cAAc,SAAS,aAAa,WAAW;AACzF,QAAM,QAAQ,QAAQ,MAAM,iBAAiB,MAAM,IAAI,GAAG,CAAC,gBAAgB,CAAC;AAE5E,QAAM,WAA4C,WAC9C,EAAE,YAAY,YAAY,WAAW,aAAa,IAClD;AAEJ,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,KAAK;AAAA,MACL,qBAAmB,cAAc,SAAS;AAAA,MAC1C,kBAAgB,WAAW,SAAS;AAAA,MAEpC,0BAAAA,KAAC,WAAM,WAAU,yBACf,0BAAAA,KAAC,WACE,gBAAM,IAAI,CAAC,MAAM,MAChB,qBAAC,QACE;AAAA,sBACC,gBAAAA,KAAC,QAAG,WAAU,4BAA4B,cAAI,GAAE,IAC9C;AAAA,QACJ,gBAAAA,KAAC,QAAG,WAAU,gCACZ,0BAAAA,KAAC,SAAI,OAAO,UAAW,kBAAQ,KAAI,GACrC;AAAA,WANO,CAOT,CACD,GACH,GACF;AAAA;AAAA,EACF;AAEJ;;;AC9DA,SAAgB,WAAAC,UAAS,UAAAC,eAAc;AACvC,SAAS,kBAAkB;AAC3B,SAAS,YAAY;AAwBf,gBAAAC,YAAA;AArBN,IAAM,UAAU,EAAE,KAAK;AAUhB,IAAM,WAAoC,CAAC,EAAE,SAAS,UAAU,WAAW,aAAa,YAAY,MAAM;AAC/G,QAAM,eAAeC,QAAuB,IAAI;AAChD,QAAM,EAAE,iBAAiB,IAAI,aAAa,cAAc,SAAS,aAAa,WAAW;AAEzF,QAAM,SAASC;AAAA,IACb,MAAM,SAAS,YAAY,MAAM,OAAO,mBAAmB;AAAA,IAC3D,CAAC,kBAAkB,QAAQ;AAAA,EAC7B;AAEA,SACE,gBAAAF,KAAC,SAAI,WAAsB,KAAK,cAC9B,0BAAAA,KAAC,cAAW,SAAmB,kBAAO,GACxC;AAEJ;;;AC7BA,SAAgB,UAAAG,eAAc;AAC9B,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,QAAAC,aAAY;AACrB,SAAS,eAAe;AACxB,SAAS,wBAAwB;AACjC,SAAS,WAAW;AAoCd,gBAAAC,YAAA;AAjCN,IAAM,OAAO,iBAAiB,EAAE,sBAAsB,KAAK,CAAC;AAC5D,IAAM,iBAAiB,EAAE,MAAAC,OAAM,SAAS,MAAM,IAAI;AAU3C,IAAM,eAA4C,CAAC,EAAE,SAAS,WAAW,SAAS,cAAc,aAAa,YAAY,MAAM;AACpI,QAAM,eAAeC,QAAuB,IAAI;AAEhD,QAAM,EAAE,iBAAiB,IAAI,aAAa,cAAc,SAAS,aAAa,WAAW;AAEzF,QAAM,uBAAuB,CAAC,MAAwB;AACpD,UAAM,SAAS,EAAE;AACjB,UAAM,SAAS,OAAO,QAAQ,GAAG;AACjC,QAAI,QAAQ,MAAM;AAChB,YAAM,OAAO,OAAO,aAAa,MAAM,KAAK;AAC5C,UAAI,KAAK,WAAW,OAAO,KAAK,aAAa;AAC3C,UAAE,eAAe;AACjB,oBAAY,EAAE,KAAK,KAAK,MAAM,CAAC,EAAE,CAAC;AAAA,MACpC,WAAW,aAAa;AACtB,UAAE,eAAe;AACjB,oBAAY,IAAI;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAEA,SACE,gBAAAF,KAAC,SAAI,WAAsB,KAAK,cAAc,SAAS,sBACrD,0BAAAA,KAACG,aAAA,EAAW,SAAS,EAAE,GAAG,gBAAgB,GAAG,aAAa,GAAI,4BAAiB,GACjF;AAEJ;;;AC5CA,SAAgB,WAAAC,UAAS,UAAU,aAAa,UAAAC,eAAc;AAyB9C,SA4BG,UA3Bb,OAAAC,MADU,QAAAC,aAAA;AAPhB,IAAM,WAAoC,CAAC,EAAE,OAAO,OAAO,OAAO,gBAAgB,MAAM;AACtF,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,QAAQ,eAAe;AAEhE,QAAM,SAAS,YAAY,MAAM,YAAY,OAAK,CAAC,CAAC,GAAG,CAAC,CAAC;AAEzD,MAAI,UAAU,MAAM;AAClB,WAAO,gBAAAA,MAAC,SAAI,WAAU,iBAAgB,OAAO,EAAE,aAAa,QAAQ,GAAG,GACpE;AAAA,eAAS,gBAAAA,MAAC,UAAK,WAAU,gBAAgB;AAAA;AAAA,QAAM;AAAA,SAAE;AAAA,MAClD,gBAAAD,KAAC,UAAK,WAAU,iBAAgB,kBAAI;AAAA,OACtC;AAAA,EACF;AACA,MAAI,OAAO,UAAU,WAAW;AAC9B,WAAO,gBAAAC,MAAC,SAAI,WAAU,iBAAgB,OAAO,EAAE,aAAa,QAAQ,GAAG,GACpE;AAAA,eAAS,gBAAAA,MAAC,UAAK,WAAU,gBAAgB;AAAA;AAAA,QAAM;AAAA,SAAE;AAAA,MAClD,gBAAAD,KAAC,UAAK,WAAU,iBAAiB,iBAAO,KAAK,GAAE;AAAA,OACjD;AAAA,EACF;AACA,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAU;AAC1D,WAAO,gBAAAC,MAAC,SAAI,WAAU,iBAAgB,OAAO,EAAE,aAAa,QAAQ,GAAG,GACpE;AAAA,eAAS,gBAAAA,MAAC,UAAK,WAAU,gBAAgB;AAAA;AAAA,QAAM;AAAA,SAAE;AAAA,MAClD,gBAAAD,KAAC,UAAK,WAAU,mBAAmB,iBAAO,KAAK,GAAE;AAAA,OACnD;AAAA,EACF;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,gBAAAC,MAAC,SAAI,WAAU,iBAAgB,OAAO,EAAE,aAAa,QAAQ,GAAG,GACpE;AAAA,eAAS,gBAAAA,MAAC,UAAK,WAAU,gBAAgB;AAAA;AAAA,QAAM;AAAA,SAAE;AAAA,MAClD,gBAAAA,MAAC,UAAK,WAAU,mBAAkB;AAAA;AAAA,QAAE;AAAA,QAAM;AAAA,SAAC;AAAA,OAC7C;AAAA,EACF;AACA,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,gBAAAA,MAAC,SAAI,OAAO,EAAE,aAAa,QAAQ,GAAG,GAC3C;AAAA,sBAAAD,KAAC,UAAK,WAAU,mBAAkB,SAAS,QAAS,qBAAW,WAAM,UAAI;AAAA,MACxE,SAAS,gBAAAC,MAAC,UAAK,WAAU,gBAAgB;AAAA;AAAA,QAAM;AAAA,SAAE;AAAA,MAClD,gBAAAD,KAAC,UAAK,WAAU,oBAAmB,eAAC;AAAA,MACnC,CAAC,YAAY,gBAAAC,MAAC,UAAK,WAAU,sBAAqB;AAAA;AAAA,QAAE,MAAM;AAAA,QAAO;AAAA,SAAQ;AAAA,MACzE,YAAY,gBAAAA,MAAA,YACV;AAAA,cAAM,IAAI,CAAC,MAAM,MAChB,gBAAAD,KAAC,YAAiB,OAAO,OAAO,CAAC,GAAG,OAAO,MAAM,OAAO,QAAQ,GAAG,mBAApD,CAAsF,CACtG;AAAA,QACD,gBAAAA,KAAC,SAAI,OAAO,EAAE,aAAa,QAAQ,GAAG,GAAG,0BAAAA,KAAC,UAAK,WAAU,oBAAmB,eAAC,GAAO;AAAA,SACtF;AAAA,OACF;AAAA,EACF;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,UAAU,OAAO,QAAQ,KAAgC;AAC/D,WAAO,gBAAAC,MAAC,SAAI,OAAO,EAAE,aAAa,QAAQ,GAAG,GAC3C;AAAA,sBAAAD,KAAC,UAAK,WAAU,mBAAkB,SAAS,QAAS,qBAAW,WAAM,UAAI;AAAA,MACxE,SAAS,gBAAAC,MAAC,UAAK,WAAU,gBAAgB;AAAA;AAAA,QAAM;AAAA,SAAE;AAAA,MAClD,gBAAAD,KAAC,UAAK,WAAU,oBAAoB,eAAI;AAAA,MACvC,CAAC,YAAY,gBAAAC,MAAC,UAAK,WAAU,sBAAqB;AAAA;AAAA,QAAE,QAAQ;AAAA,QAAO;AAAA,QAAO;AAAA,SAAI;AAAA,MAC9E,YAAY,gBAAAA,MAAA,YACV;AAAA,gBAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,MACjB,gBAAAD,KAAC,YAAiB,OAAO,GAAG,OAAO,GAAG,OAAO,QAAQ,GAAG,mBAAzC,CAA2E,CAC3F;AAAA,QACD,gBAAAA,KAAC,SAAI,OAAO,EAAE,aAAa,QAAQ,GAAG,GAAG,0BAAAA,KAAC,UAAK,WAAU,oBAAoB,eAAI,GAAO;AAAA,SAC1F;AAAA,OACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,IAAM,WAAoC,CAAC,EAAE,MAAM,kBAAkB,GAAG,WAAW,aAAa,YAAY,MAAM;AACvH,QAAM,eAAeE,QAAuB,IAAI;AAEhD,QAAM,aAAa,OAAO,SAAS,WAAW,OAAO,KAAK,UAAU,MAAM,MAAM,CAAC;AACjF,QAAM,EAAE,iBAAiB,IAAI,aAAa,cAAc,YAAY,aAAa,WAAW;AAE5F,QAAM,SAASC,SAAQ,MAAM;AAC3B,QAAI;AACF,aAAO,EAAE,IAAI,MAAe,OAAO,KAAK,MAAM,gBAAgB,EAAE;AAAA,IAClE,QAAQ;AACN,aAAO,EAAE,IAAI,OAAgB,OAAO,iBAAiB;AAAA,IACvD;AAAA,EACF,GAAG,CAAC,gBAAgB,CAAC;AAErB,MAAI,CAAC,OAAO,IAAI;AACd,WACE,gBAAAH,KAAC,SAAI,WAAsB,KAAK,cAC9B,0BAAAA,KAAC,SAAI,OAAO,EAAE,QAAQ,GAAG,YAAY,YAAY,WAAW,aAAa,GAAI,iBAAO,OAAgB,GACtG;AAAA,EAEJ;AAEA,SACE,gBAAAA,KAAC,SAAI,WAAsB,KAAK,cAC9B,0BAAAA,KAAC,YAAS,OAAO,MAAM,OAAO,OAAO,OAAO,OAAO,GAAG,iBAAkC,GAC1F;AAEJ;;;AC1GA,SAAgB,YAAAI,WAAU,UAAAC,SAAQ,eAAAC,oBAAmB;AAgF3C,gBAAAC,MAGA,QAAAC,aAHA;AAvDV,IAAM,YAAY;AAEX,IAAM,YAAsC,CAAC;AAAA,EAClD;AAAA,EAAK;AAAA,EAAK;AAAA,EACV,cAAc;AAAA,EACd,eAAe;AAAA,EACf,aAAa;AAAA,EACb,OAAO;AAAA,EACP,WAAW;AACb,MAAM;AACJ,mBAAiB,GAAG;AAEpB,QAAM,CAAC,OAAO,QAAQ,IAAIC,UAAS,CAAC;AACpC,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAS,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;AACvD,QAAM,CAAC,YAAY,aAAa,IAAIA,UAAS,KAAK;AAClD,QAAM,YAAYC,QAAO,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;AAEvC,QAAM,WAAW,KAAK,IAAI,GAAG,QAAQ;AAErC,QAAM,cAAcC,aAAY,CAAC,MAAwB;AACvD,QAAI,CAAC,KAAM;AACX,MAAE,eAAe;AACjB,UAAM,QAAQ,EAAE,SAAS,IAAI,MAAM;AACnC,aAAS,UAAQ,KAAK,IAAI,KAAK,IAAI,OAAO,OAAO,SAAS,GAAG,QAAQ,CAAC;AAAA,EACxE,GAAG,CAAC,MAAM,QAAQ,CAAC;AAEnB,QAAM,kBAAkBA,aAAY,CAAC,MAAwB;AAC3D,QAAI,CAAC,KAAM;AACX,kBAAc,IAAI;AAClB,cAAU,UAAU,EAAE,GAAG,EAAE,UAAU,SAAS,GAAG,GAAG,EAAE,UAAU,SAAS,EAAE;AAAA,EAC7E,GAAG,CAAC,UAAU,IAAI,CAAC;AAEnB,QAAM,kBAAkBA,aAAY,CAAC,MAAwB;AAC3D,QAAI,CAAC,WAAY;AACjB,gBAAY;AAAA,MACV,GAAG,EAAE,UAAU,UAAU,QAAQ;AAAA,MACjC,GAAG,EAAE,UAAU,UAAU,QAAQ;AAAA,IACnC,CAAC;AAAA,EACH,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,gBAAgBA,aAAY,MAAM,cAAc,KAAK,GAAG,CAAC,CAAC;AAEhE,QAAM,YAAYA,aAAY,MAAM;AAClC,aAAS,CAAC;AACV,gBAAY,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;AAAA,EAC5B,GAAG,CAAC,CAAC;AAEL,SACE,gBAAAH;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,aAAW,OAAO,SAAS;AAAA,MAC3B,kBAAgB,OAAO,QAAQ;AAAA,MAE9B;AAAA,eACC,gBAAAA,MAAC,SAAI,WAAU,qBACb;AAAA,0BAAAD,KAAC,YAAO,SAAS,MAAM,SAAS,OAAK,KAAK,IAAI,IAAI,KAAK,QAAQ,CAAC,GAAG,OAAO,aAAc,uBAAY;AAAA,UACpG,gBAAAA,KAAC,YAAO,SAAS,MAAM,SAAS,OAAK,KAAK,IAAI,IAAI,KAAK,SAAS,CAAC,GAAG,OAAO,cAAe,wBAAa;AAAA,UACvG,gBAAAA,KAAC,YAAO,SAAS,WAAY,sBAAW;AAAA,UACxC,gBAAAC,MAAC,UAAK,WAAU,mBAAmB;AAAA,iBAAK,MAAM,QAAQ,GAAG;AAAA,YAAE;AAAA,aAAC;AAAA,WAC9D,IACE;AAAA,QACJ,gBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,SAAS,OAAO,cAAc;AAAA,YAC9B,aAAa,OAAO,kBAAkB;AAAA,YACtC,aAAa,OAAO,kBAAkB;AAAA,YACtC,WAAW,OAAO,gBAAgB;AAAA,YAClC,cAAc,OAAO,gBAAgB;AAAA,YACrC,OAAO,EAAE,QAAQ,OAAQ,aAAa,aAAa,SAAU,UAAU;AAAA,YAEvE,0BAAAA;AAAA,cAAC;AAAA;AAAA,gBACC;AAAA,gBACA,KAAK,OAAO;AAAA,gBACZ,OACE,OACI;AAAA,kBACE,WAAW,aAAa,SAAS,CAAC,OAAO,SAAS,CAAC,aAAa,KAAK;AAAA,kBACrE,iBAAiB;AAAA,gBACnB,IACA;AAAA,gBAEN,WAAW;AAAA;AAAA,YACb;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EACF;AAEJ;;;AC/GA,OAAkB;AAeG,gBAAAK,YAAA;AANd,IAAM,YAAsC,CAAC,EAAE,KAAK,UAAU,UAAU,MAAM;AACnF,mBAAiB,GAAG;AAEpB,SACE,gBAAAA,KAAC,SAAI,WACH,0BAAAA,KAAC,WAAM,KAAU,UAAQ,MAAC,WAAU,qBACjC,sBAAY,gBAAAA,KAAC,YAAO,KAAU,MAAM,UAAU,GACjD,GACF;AAEJ;;;ACnBA,OAAkB;AAeG,gBAAAC,YAAA;AANd,IAAM,YAAsC,CAAC,EAAE,KAAK,UAAU,UAAU,MAAM;AACnF,mBAAiB,GAAG;AAEpB,SACE,gBAAAA,KAAC,SAAI,WACH,0BAAAA,KAAC,WAAM,KAAU,UAAQ,MAAC,WAAU,qBACjC,sBAAY,gBAAAA,KAAC,YAAO,KAAU,MAAM,UAAU,GACjD,GACF;AAEJ;","names":["jsx","useMemo","useRef","jsx","useRef","useMemo","useRef","Streamdown","code","jsx","code","useRef","Streamdown","useMemo","useRef","jsx","jsxs","useRef","useMemo","useState","useRef","useCallback","jsx","jsxs","useState","useRef","useCallback","jsx","jsx"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// src/hooks/useInteractionDispatch.ts
|
|
2
|
+
import { createContext, useContext, useCallback } from "react";
|
|
3
|
+
var InteractionContext = createContext(null);
|
|
4
|
+
function useInteractionDispatch() {
|
|
5
|
+
const dispatch = useContext(InteractionContext);
|
|
6
|
+
const emitInteraction = useCallback(
|
|
7
|
+
(type, target, metadata) => {
|
|
8
|
+
dispatch?.({
|
|
9
|
+
type,
|
|
10
|
+
target,
|
|
11
|
+
metadata,
|
|
12
|
+
timestamp: Date.now()
|
|
13
|
+
});
|
|
14
|
+
},
|
|
15
|
+
[dispatch]
|
|
16
|
+
);
|
|
17
|
+
return emitInteraction;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
InteractionContext,
|
|
22
|
+
useInteractionDispatch
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=chunk-3R6T3LBR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hooks/useInteractionDispatch.ts"],"sourcesContent":["import { createContext, useContext, useCallback } from 'react'\nimport type { InteractionEventType, ChatWidgetInteractionEvent } from '../types'\n\ntype DispatchFn = (event: ChatWidgetInteractionEvent) => void\n\nexport const InteractionContext = createContext<DispatchFn | null>(null)\n\nexport function useInteractionDispatch() {\n const dispatch = useContext(InteractionContext)\n\n const emitInteraction = useCallback(\n (type: InteractionEventType, target: string, metadata?: Record<string, unknown>) => {\n dispatch?.({\n type,\n target,\n metadata,\n timestamp: Date.now(),\n })\n },\n [dispatch],\n )\n\n return emitInteraction\n}\n"],"mappings":";AAAA,SAAS,eAAe,YAAY,mBAAmB;AAKhD,IAAM,qBAAqB,cAAiC,IAAI;AAEhE,SAAS,yBAAyB;AACvC,QAAM,WAAW,WAAW,kBAAkB;AAE9C,QAAM,kBAAkB;AAAA,IACtB,CAAC,MAA4B,QAAgB,aAAuC;AAClF,iBAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA,WAAW,KAAK,IAAI;AAAA,MACtB,CAAC;AAAA,IACH;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,SAAO;AACT;","names":[]}
|