@braincrew-lab/langchain-canvas 0.1.14 → 0.2.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.
@@ -1,5 +1,5 @@
1
- import { useArtifactPatch } from './chunk-TERWLUW3.js';
2
- import './chunk-KKLWKR5G.js';
1
+ import { useArtifactPatch } from './chunk-UL5F66PN.js';
2
+ import './chunk-S54GJDSJ.js';
3
3
  import { useState, useRef, useMemo, useEffect } from 'react';
4
4
  import * as echarts from 'echarts/core';
5
5
  import { BarChart, LineChart, PieChart } from 'echarts/charts';
@@ -124,6 +124,23 @@ function ChartRenderer({ artifact }) {
124
124
  /* @__PURE__ */ jsx(EChart, { option, height: editing ? 260 : 340, onInst: (i) => instRef.current = i })
125
125
  ] });
126
126
  }
127
+ function NumberCell({ value, onCommit }) {
128
+ const [draft, setDraft] = useState(null);
129
+ const shown = draft ?? String(Number(value ?? 0));
130
+ return /* @__PURE__ */ jsx(
131
+ "input",
132
+ {
133
+ type: "number",
134
+ value: shown,
135
+ onChange: (e) => {
136
+ setDraft(e.target.value);
137
+ const n = Number(e.target.value);
138
+ if (e.target.value !== "" && Number.isFinite(n)) onCommit(n);
139
+ },
140
+ onBlur: () => setDraft(null)
141
+ }
142
+ );
143
+ }
127
144
  function DataGrid({
128
145
  rows,
129
146
  xKey,
@@ -141,14 +158,7 @@ function DataGrid({
141
158
  ] }) }),
142
159
  /* @__PURE__ */ jsx("tbody", { children: rows.map((row, i) => /* @__PURE__ */ jsxs("tr", { children: [
143
160
  /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("input", { value: String(row[xKey] ?? ""), onChange: (e) => onCell(i, xKey, e.target.value) }) }),
144
- series.map((s) => /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(
145
- "input",
146
- {
147
- type: "number",
148
- value: Number(row[s.key] ?? 0),
149
- onChange: (e) => onCell(i, s.key, e.target.value === "" ? 0 : Number(e.target.value))
150
- }
151
- ) }, s.key)),
161
+ series.map((s) => /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(NumberCell, { value: row[s.key], onCommit: (n) => onCell(i, s.key, n) }) }, s.key)),
152
162
  /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("button", { className: "cv-chart__row-del", onClick: () => onRemoveRow(i), disabled: rows.length <= 1, title: "Remove row", children: "\xD7" }) })
153
163
  ] }, i)) })
154
164
  ] }),
@@ -1,5 +1,5 @@
1
- import { useArtifactPatch } from './chunk-TERWLUW3.js';
2
- import './chunk-KKLWKR5G.js';
1
+ import { useArtifactPatch } from './chunk-UL5F66PN.js';
2
+ import './chunk-S54GJDSJ.js';
3
3
  import { useState, useRef } from 'react';
4
4
  import ReactMarkdown from 'react-markdown';
5
5
  import remarkGfm from 'remark-gfm';
@@ -0,0 +1,97 @@
1
+ import { useState, useEffect, useMemo } from 'react';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+
4
+ // src/components/renderers/PdfRenderer.tsx
5
+ function dataUrlToBlob(url) {
6
+ const m = /^data:[^,]*?(;base64)?,(.*)$/s.exec(url);
7
+ if (!m) return null;
8
+ try {
9
+ if (m[1]) {
10
+ const bin = atob(m[2]);
11
+ const bytes = new Uint8Array(bin.length);
12
+ for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
13
+ return new Blob([bytes], { type: "application/pdf" });
14
+ }
15
+ return new Blob([decodeURIComponent(m[2])], { type: "application/pdf" });
16
+ } catch {
17
+ return null;
18
+ }
19
+ }
20
+ function PdfRenderer({ artifact }) {
21
+ const src = artifact.data.src;
22
+ const isData = typeof src === "string" && src.startsWith("data:");
23
+ const [blobUrl, setBlobUrl] = useState(null);
24
+ const [broken, setBroken] = useState(false);
25
+ useEffect(() => {
26
+ setBroken(false);
27
+ if (!isData) {
28
+ setBlobUrl(null);
29
+ return;
30
+ }
31
+ const blob = dataUrlToBlob(src);
32
+ if (!blob) {
33
+ setBroken(true);
34
+ setBlobUrl(null);
35
+ return;
36
+ }
37
+ const url = URL.createObjectURL(blob);
38
+ setBlobUrl(url);
39
+ return () => URL.revokeObjectURL(url);
40
+ }, [src, isData]);
41
+ const viewUrl = isData ? blobUrl : src;
42
+ const filename = useMemo(
43
+ () => artifact.data.filename || `${artifact.title || "document"}.pdf`,
44
+ [artifact.data.filename, artifact.title]
45
+ );
46
+ const [zoom, setZoom] = useState("fit");
47
+ const zoomOut = () => setZoom((z) => Math.max(50, (z === "fit" ? 100 : z) - 25));
48
+ const zoomIn = () => setZoom((z) => Math.min(300, (z === "fit" ? 100 : z) + 25));
49
+ const frameSrc = viewUrl ? `${viewUrl}#toolbar=0&navpanes=0&zoom=${zoom === "fit" ? "page-width" : zoom}` : null;
50
+ const download = () => {
51
+ if (!viewUrl) return;
52
+ const a = document.createElement("a");
53
+ a.href = viewUrl;
54
+ a.download = filename;
55
+ a.click();
56
+ };
57
+ if (!src || broken) {
58
+ return /* @__PURE__ */ jsx("div", { className: "cv-pdf cv-pdf--empty", children: "Waiting for PDF\u2026" });
59
+ }
60
+ if (!viewUrl) {
61
+ return /* @__PURE__ */ jsx("div", { className: "cv-pdf cv-pdf--empty", children: "Loading PDF\u2026" });
62
+ }
63
+ return /* @__PURE__ */ jsxs("div", { className: "cv-pdf-panel", children: [
64
+ /* @__PURE__ */ jsxs("div", { className: "cv-pdf-tools", children: [
65
+ /* @__PURE__ */ jsx("span", { className: "cv-pdf-tools__name", title: filename, children: filename }),
66
+ /* @__PURE__ */ jsx("span", { className: "cv-pdf-tools__spacer" }),
67
+ /* @__PURE__ */ jsxs("span", { className: "cv-pdf-tools__zoom", children: [
68
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: zoomOut, title: "Zoom out", children: "\u2212" }),
69
+ /* @__PURE__ */ jsx(
70
+ "button",
71
+ {
72
+ type: "button",
73
+ className: "cv-pdf-tools__zoom-label",
74
+ onClick: () => setZoom("fit"),
75
+ title: "Fit to width",
76
+ children: zoom === "fit" ? "Fit" : `${zoom}%`
77
+ }
78
+ ),
79
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: zoomIn, title: "Zoom in", children: "\uFF0B" })
80
+ ] }),
81
+ /* @__PURE__ */ jsx("span", { className: "cv-pdf-tools__sep" }),
82
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: download, title: "Download PDF", children: "\u2913 Download" }),
83
+ /* @__PURE__ */ jsx(
84
+ "button",
85
+ {
86
+ type: "button",
87
+ onClick: () => window.open(viewUrl, "_blank", "noopener"),
88
+ title: "Open in a new tab",
89
+ children: "\u2197 Open"
90
+ }
91
+ )
92
+ ] }),
93
+ /* @__PURE__ */ jsx("div", { className: "cv-pdf", children: /* @__PURE__ */ jsx("iframe", { className: "cv-pdf__frame", src: frameSrc, title: filename }, frameSrc) })
94
+ ] });
95
+ }
96
+
97
+ export { PdfRenderer };