@braincrew-lab/langchain-canvas 0.6.2 → 0.7.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.
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { deckPage, pageAspect, DEFAULT_SLIDE_PAGE_IN, resolveElements, fontScaleFor } from './chunk-
|
|
1
|
+
import { deckPage, pageAspect, DEFAULT_SLIDE_PAGE_IN, resolveElements, fontScaleFor } from './chunk-MZ5WQWTS.js';
|
|
2
2
|
import { useAssetUrl } from './chunk-HCF2DXCR.js';
|
|
3
3
|
import './chunk-7T5DRR3F.js';
|
|
4
4
|
import { useArtifactPatch } from './chunk-N5JW2BKI.js';
|
|
@@ -329,7 +329,7 @@ function SlidesRenderer({ artifact }) {
|
|
|
329
329
|
};
|
|
330
330
|
const duplicateSlide = () => {
|
|
331
331
|
const next = [...slides];
|
|
332
|
-
next.splice(at + 1, 0, { ...slide, elements: resolveElements(slide).map((e) => ({ ...e })) });
|
|
332
|
+
next.splice(at + 1, 0, { ...slide, elements: resolveElements(slide, page).map((e) => ({ ...e })) });
|
|
333
333
|
setSlides(next);
|
|
334
334
|
setIndex(at + 1);
|
|
335
335
|
};
|
|
@@ -354,7 +354,7 @@ function SlidesRenderer({ artifact }) {
|
|
|
354
354
|
setSlides(next);
|
|
355
355
|
setIndex(to);
|
|
356
356
|
};
|
|
357
|
-
const addElement = (el) => update({ elements: [...resolveElements(slide), { ...el, id: newElementId() }] });
|
|
357
|
+
const addElement = (el) => update({ elements: [...resolveElements(slide, page), { ...el, id: newElementId() }] });
|
|
358
358
|
const addTextEl = () => addElement({ type: "text", x: 12, y: 16, w: 45, h: 16, text: "Text", fontSize: 24 });
|
|
359
359
|
const addImageEl = (file) => {
|
|
360
360
|
if (!file) return;
|
|
@@ -392,7 +392,7 @@ function SlidesRenderer({ artifact }) {
|
|
|
392
392
|
onDragEnd: () => setDragIndex(null),
|
|
393
393
|
children: /* @__PURE__ */ jsxs("button", { className: "cv-deck__thumb", onClick: () => setIndex(i), children: [
|
|
394
394
|
/* @__PURE__ */ jsx("span", { className: "cv-deck__thumb-n", children: i + 1 }),
|
|
395
|
-
/* @__PURE__ */ jsx("div", { className: "cv-deck__thumb-slide", style: { aspectRatio: aspect, ...s.background ? { background: s.background } : {} }, children: /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: `${s.padding ?? 0}%` }, children: resolveElements(s).map(
|
|
395
|
+
/* @__PURE__ */ jsx("div", { className: "cv-deck__thumb-slide", style: { aspectRatio: aspect, ...s.background ? { background: s.background } : {} }, children: /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: `${s.padding ?? 0}%` }, children: resolveElements(s, page).map(
|
|
396
396
|
(el) => el.type === "text" ? /* @__PURE__ */ jsx(
|
|
397
397
|
"span",
|
|
398
398
|
{
|
|
@@ -476,7 +476,7 @@ function SlidesRenderer({ artifact }) {
|
|
|
476
476
|
/* @__PURE__ */ jsx("button", { onClick: duplicateSlide, title: "Duplicate slide", children: "\u29C9" }),
|
|
477
477
|
/* @__PURE__ */ jsx("button", { onClick: deleteSlide, title: "Delete slide", disabled: slides.length === 1, children: "\u{1F5D1}" })
|
|
478
478
|
] }),
|
|
479
|
-
/* @__PURE__ */ jsx("div", { className: "cv-slide cv-slide--blank", ref: editBox.ref, style: { aspectRatio: aspect, ...slideStyle }, children: /* @__PURE__ */ jsx(FreeSlide, { elements: resolveElements(slide), onChange: (elements) => update({ elements }), padding: slide.padding, fontScale: editBox.scale }) }),
|
|
479
|
+
/* @__PURE__ */ jsx("div", { className: "cv-slide cv-slide--blank", ref: editBox.ref, style: { aspectRatio: aspect, ...slideStyle }, children: /* @__PURE__ */ jsx(FreeSlide, { elements: resolveElements(slide, page), onChange: (elements) => update({ elements }), padding: slide.padding, fontScale: editBox.scale }) }),
|
|
480
480
|
/* @__PURE__ */ jsxs("div", { className: "cv-deck__nav cv-chrome", children: [
|
|
481
481
|
/* @__PURE__ */ jsx("button", { disabled: at === 0, onClick: () => setIndex(at - 1), "aria-label": "Previous slide", children: "\u2039" }),
|
|
482
482
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
@@ -497,7 +497,7 @@ function SlidesRenderer({ artifact }) {
|
|
|
497
497
|
)
|
|
498
498
|
] }),
|
|
499
499
|
presenting && /* @__PURE__ */ jsxs("div", { className: "cv-present", onClick: () => setIndex(Math.min(at + 1, slides.length - 1)), children: [
|
|
500
|
-
/* @__PURE__ */ jsx("div", { ref: presentBox.ref, className: "cv-present__slide cv-present__fade cv-slide cv-slide--blank", style: { aspectRatio: aspect, ...slideStyle }, children: /* @__PURE__ */ jsx("div", { className: "cv-free", style: slide.padding ? { inset: `${slide.padding}%` } : void 0, children: resolveElements(slide).map(
|
|
500
|
+
/* @__PURE__ */ jsx("div", { ref: presentBox.ref, className: "cv-present__slide cv-present__fade cv-slide cv-slide--blank", style: { aspectRatio: aspect, ...slideStyle }, children: /* @__PURE__ */ jsx("div", { className: "cv-free", style: slide.padding ? { inset: `${slide.padding}%` } : void 0, children: resolveElements(slide, page).map(
|
|
501
501
|
(el) => el.type === "text" ? /* @__PURE__ */ jsx("div", { className: "cv-free__el", style: { left: `${el.x}%`, top: `${el.y}%`, width: `${el.w}%`, height: `${el.h}%` }, children: /* @__PURE__ */ jsx("div", { className: "cv-free__text", style: { fontSize: (el.fontSize ?? 24) * presentBox.scale, fontWeight: el.bold ? 700 : 400, color: el.color, textAlign: el.align ?? "left", whiteSpace: "pre-wrap" }, children: el.text }) }, el.id) : el.type === "shape" ? /* @__PURE__ */ jsx("div", { className: "cv-free__el", style: { left: `${el.x}%`, top: `${el.y}%`, width: `${el.w}%`, height: `${el.h}%`, color: slide.textColor }, children: /* @__PURE__ */ jsx("div", { style: shapeStyle(el) }) }, el.id) : /* @__PURE__ */ jsx("div", { className: "cv-free__el", style: { left: `${el.x}%`, top: `${el.y}%`, width: `${el.w}%`, height: `${el.h}%` }, children: /* @__PURE__ */ jsx("img", { className: "cv-free__img", src: assetUrl(el.src), alt: "" }) }, el.id)
|
|
502
502
|
) }) }, at),
|
|
503
503
|
slide.notes ? /* @__PURE__ */ jsx("div", { className: "cv-present__notes", onClick: (e) => e.stopPropagation(), children: slide.notes }) : null,
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
// src/client/slidePage.ts
|
|
2
|
+
var DEFAULT_SLIDE_PAGE_IN = { widthIn: 10, heightIn: 5.625 };
|
|
3
|
+
var PAGE_DPI = 96;
|
|
4
|
+
function deckPage(data) {
|
|
5
|
+
const page = data.page;
|
|
6
|
+
if (!page) return DEFAULT_SLIDE_PAGE_IN;
|
|
7
|
+
const { widthIn, heightIn } = page;
|
|
8
|
+
if (!Number.isFinite(widthIn) || !Number.isFinite(heightIn) || widthIn <= 0 || heightIn <= 0) {
|
|
9
|
+
return DEFAULT_SLIDE_PAGE_IN;
|
|
10
|
+
}
|
|
11
|
+
return { widthIn, heightIn };
|
|
12
|
+
}
|
|
13
|
+
function pageAspect(page) {
|
|
14
|
+
return `${page.widthIn} / ${page.heightIn}`;
|
|
15
|
+
}
|
|
16
|
+
function fontScaleFor(boxWidthPx, page) {
|
|
17
|
+
if (!Number.isFinite(boxWidthPx) || boxWidthPx <= 0) return 1;
|
|
18
|
+
return boxWidthPx / (page.widthIn * PAGE_DPI);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// src/client/slideElements.ts
|
|
22
|
+
var FONT_DISPLAY = 48;
|
|
23
|
+
var FONT_TITLE = 38;
|
|
24
|
+
var BODY_RAMP = [30, 24, 19];
|
|
25
|
+
var TITLE_RAMP = [FONT_TITLE, 30, 24];
|
|
26
|
+
var DISPLAY_RAMP = [FONT_DISPLAY, FONT_TITLE, 30];
|
|
27
|
+
var LINE_HEIGHT = 1.35;
|
|
28
|
+
var GAP_MIN = 0.35;
|
|
29
|
+
var GAP_MAX = 3;
|
|
30
|
+
var BODY_TOP = 28;
|
|
31
|
+
var BODY_BOTTOM = 88;
|
|
32
|
+
var BODY_LEFT = 8;
|
|
33
|
+
var BODY_WIDTH = 84;
|
|
34
|
+
var TITLE_TOP = 7;
|
|
35
|
+
var TITLE_LEFT = 6;
|
|
36
|
+
var TITLE_WIDTH = 88;
|
|
37
|
+
var TITLE_BOTTOM = 46;
|
|
38
|
+
var SUBTITLE_BUDGET = 12;
|
|
39
|
+
var COVER_TOP = 6;
|
|
40
|
+
var COVER_BOTTOM = 94;
|
|
41
|
+
var COVER_TITLE_SHARE = 0.66;
|
|
42
|
+
var COVER_SUBTITLE_SHARE = 0.22;
|
|
43
|
+
var COLUMN_WIDTH = 42;
|
|
44
|
+
var COLUMN_RIGHT_LEFT = 52;
|
|
45
|
+
var BULLET = "\u2022 ";
|
|
46
|
+
var WIDE_CHAR_FLOOR = 11903;
|
|
47
|
+
function pagePx(page) {
|
|
48
|
+
const fallback = [DEFAULT_SLIDE_PAGE_IN.widthIn * PAGE_DPI, DEFAULT_SLIDE_PAGE_IN.heightIn * PAGE_DPI];
|
|
49
|
+
if (!page) return fallback;
|
|
50
|
+
const { widthIn, heightIn } = page;
|
|
51
|
+
if (!(widthIn > 0 && heightIn > 0)) return fallback;
|
|
52
|
+
return [widthIn * PAGE_DPI, heightIn * PAGE_DPI];
|
|
53
|
+
}
|
|
54
|
+
function displayWidth(text) {
|
|
55
|
+
let width = 0;
|
|
56
|
+
for (const ch of text) width += (ch.codePointAt(0) ?? 0) > WIDE_CHAR_FLOOR ? 2 : 1;
|
|
57
|
+
return width;
|
|
58
|
+
}
|
|
59
|
+
function linePercent(fontPx, pageHeightPx) {
|
|
60
|
+
return fontPx * LINE_HEIGHT / pageHeightPx * 100;
|
|
61
|
+
}
|
|
62
|
+
function lineCount(text, widthPercent, fontPx, pageWidthPx) {
|
|
63
|
+
if (!text) return 1;
|
|
64
|
+
const perLine = widthPercent / 100 * pageWidthPx / (fontPx / 2);
|
|
65
|
+
if (perLine < 1) return 1;
|
|
66
|
+
return Math.max(1, Math.ceil(displayWidth(text) / perLine));
|
|
67
|
+
}
|
|
68
|
+
function fit(texts, width, band, [pageW, pageH]) {
|
|
69
|
+
let size = BODY_RAMP[BODY_RAMP.length - 1];
|
|
70
|
+
let counts = [];
|
|
71
|
+
for (const candidate of BODY_RAMP) {
|
|
72
|
+
size = candidate;
|
|
73
|
+
counts = texts.map((t) => lineCount(t, width, candidate, pageW));
|
|
74
|
+
const line = linePercent(candidate, pageH);
|
|
75
|
+
const ink = counts.reduce((a, b) => a + b, 0) * line;
|
|
76
|
+
const floorGap = GAP_MIN * line * Math.max(0, texts.length - 1);
|
|
77
|
+
if (ink + floorGap <= band) return [candidate, counts];
|
|
78
|
+
}
|
|
79
|
+
return [size, counts];
|
|
80
|
+
}
|
|
81
|
+
function headline(text, width, budget, [pageW, pageH], ramp) {
|
|
82
|
+
let size = ramp[ramp.length - 1];
|
|
83
|
+
let height = 0;
|
|
84
|
+
for (const candidate of ramp) {
|
|
85
|
+
size = candidate;
|
|
86
|
+
height = lineCount(text, width, candidate, pageW) * linePercent(candidate, pageH);
|
|
87
|
+
if (height <= budget) return [candidate, height];
|
|
88
|
+
}
|
|
89
|
+
return [size, Math.min(height, budget)];
|
|
90
|
+
}
|
|
91
|
+
function place(counts, size, o) {
|
|
92
|
+
const n = counts.length;
|
|
93
|
+
if (n === 0) return [];
|
|
94
|
+
const band = o.bottom - o.top;
|
|
95
|
+
const line = linePercent(size, o.pageHeightPx);
|
|
96
|
+
const ink = counts.reduce((a, b) => a + b, 0) * line;
|
|
97
|
+
if (ink > band) {
|
|
98
|
+
const pitch = band / n;
|
|
99
|
+
return counts.map((_, i) => ({ x: o.left, y: o.top + i * pitch, w: o.width, h: pitch, fontSize: size }));
|
|
100
|
+
}
|
|
101
|
+
const gap = n > 1 ? Math.min(Math.max((band - ink) / (n - 1), 0), GAP_MAX * line) : 0;
|
|
102
|
+
const boxes = [];
|
|
103
|
+
let y = o.top + Math.max(band - (ink + gap * (n - 1)), 0) / 2;
|
|
104
|
+
for (const count of counts) {
|
|
105
|
+
const h = count * line;
|
|
106
|
+
boxes.push({ x: o.left, y, w: o.width, h, fontSize: size });
|
|
107
|
+
y += h + gap;
|
|
108
|
+
}
|
|
109
|
+
return boxes;
|
|
110
|
+
}
|
|
111
|
+
function bullets(texts, o) {
|
|
112
|
+
if (!texts.length) return [];
|
|
113
|
+
const lines = texts.map((t) => BULLET + t);
|
|
114
|
+
const [size, counts] = o.size === void 0 ? fit(lines, o.width, o.bottom - o.top, o.pagePx) : [o.size, lines.map((t) => lineCount(t, o.width, o.size, o.pagePx[0]))];
|
|
115
|
+
return place(counts, size, { top: o.top, bottom: o.bottom, left: o.left, width: o.width, pageHeightPx: o.pagePx[1] });
|
|
116
|
+
}
|
|
117
|
+
function toElements(s, page) {
|
|
118
|
+
const px = pagePx(page);
|
|
119
|
+
const [pageW, pageH] = px;
|
|
120
|
+
const layout = s.layout ?? "content";
|
|
121
|
+
const els = [];
|
|
122
|
+
const push = (id, e) => els.push({ color: s.textColor, ...e, id });
|
|
123
|
+
if (layout === "title" || layout === "section") {
|
|
124
|
+
const budget = COVER_BOTTOM - COVER_TOP;
|
|
125
|
+
const [titleSize, titleH] = s.title ? headline(s.title, TITLE_WIDTH, budget * COVER_TITLE_SHARE, px, DISPLAY_RAMP) : [FONT_DISPLAY, 0];
|
|
126
|
+
const [subSize, subH] = s.subtitle ? headline(s.subtitle, TITLE_WIDTH, budget * COVER_SUBTITLE_SHARE, px, BODY_RAMP) : [BODY_RAMP[0], 0];
|
|
127
|
+
const spacer = titleH && subH ? linePercent(subSize, pageH) : 0;
|
|
128
|
+
let y = Math.max(COVER_TOP, (100 - (titleH + spacer + subH)) / 2);
|
|
129
|
+
if (s.title) {
|
|
130
|
+
push("title", { type: "text", x: TITLE_LEFT, y, w: TITLE_WIDTH, h: titleH, text: s.title, fontSize: titleSize, bold: true, align: "center" });
|
|
131
|
+
y += titleH + spacer;
|
|
132
|
+
}
|
|
133
|
+
if (s.subtitle) {
|
|
134
|
+
push("subtitle", { type: "text", x: TITLE_LEFT, y, w: TITLE_WIDTH, h: subH, text: s.subtitle, fontSize: subSize, align: "center" });
|
|
135
|
+
}
|
|
136
|
+
return els;
|
|
137
|
+
}
|
|
138
|
+
let bodyTop = BODY_TOP;
|
|
139
|
+
if (s.title) {
|
|
140
|
+
const [size, h] = headline(s.title, TITLE_WIDTH, TITLE_BOTTOM - TITLE_TOP, px, TITLE_RAMP);
|
|
141
|
+
push("title", { type: "text", x: TITLE_LEFT, y: TITLE_TOP, w: TITLE_WIDTH, h, text: s.title, fontSize: size, bold: true });
|
|
142
|
+
bodyTop = Math.max(bodyTop, TITLE_TOP + h + linePercent(size, pageH) * 0.9);
|
|
143
|
+
}
|
|
144
|
+
if (layout === "image") {
|
|
145
|
+
if (s.image) els.push({ id: "img", type: "image", x: 14, y: bodyTop, w: 72, h: Math.max(BODY_BOTTOM - bodyTop, 0), src: s.image });
|
|
146
|
+
return els;
|
|
147
|
+
}
|
|
148
|
+
if (s.subtitle) {
|
|
149
|
+
const [size, h] = headline(s.subtitle, TITLE_WIDTH, SUBTITLE_BUDGET, px, BODY_RAMP);
|
|
150
|
+
push("subtitle", { type: "text", x: TITLE_LEFT, y: bodyTop, w: TITLE_WIDTH, h, text: s.subtitle, fontSize: size });
|
|
151
|
+
bodyTop = bodyTop + h + linePercent(size, pageH) * 0.9;
|
|
152
|
+
}
|
|
153
|
+
if (layout === "two-column") {
|
|
154
|
+
const band = BODY_BOTTOM - bodyTop;
|
|
155
|
+
const left = s.bullets ?? [];
|
|
156
|
+
const right = s.bullets2 ?? [];
|
|
157
|
+
const size = Math.min(
|
|
158
|
+
fit(left.map((t) => BULLET + t), COLUMN_WIDTH, band, px)[0],
|
|
159
|
+
fit(right.map((t) => BULLET + t), COLUMN_WIDTH, band, px)[0]
|
|
160
|
+
);
|
|
161
|
+
for (const [prefix, texts2, x] of [["bul", left, BODY_LEFT - 2], ["bul2", right, COLUMN_RIGHT_LEFT]]) {
|
|
162
|
+
bullets(texts2, { top: bodyTop, bottom: BODY_BOTTOM, left: x, width: COLUMN_WIDTH, pagePx: px, size }).forEach(
|
|
163
|
+
(b, i) => push(`${prefix}_${i}`, { type: "text", x: b.x, y: b.y, w: b.w, h: b.h, text: BULLET + texts2[i], fontSize: b.fontSize })
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
return els;
|
|
167
|
+
}
|
|
168
|
+
const texts = s.bullets ?? [];
|
|
169
|
+
bullets(texts, { top: bodyTop, bottom: BODY_BOTTOM, left: BODY_LEFT, width: BODY_WIDTH, pagePx: px }).forEach(
|
|
170
|
+
(b, i) => push(`bul_${i}`, { type: "text", x: b.x, y: b.y, w: b.w, h: b.h, text: BULLET + texts[i], fontSize: b.fontSize })
|
|
171
|
+
);
|
|
172
|
+
return els;
|
|
173
|
+
}
|
|
174
|
+
var resolveElements = (s, page) => s.elements?.length ? s.elements : toElements(s, page);
|
|
175
|
+
|
|
176
|
+
export { DEFAULT_SLIDE_PAGE_IN, deckPage, fontScaleFor, pageAspect, resolveElements };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { projectSheetIntoRows, mergeRowsIntoSheet } from './chunk-IFNRLN4Y.js';
|
|
3
3
|
import { loadOptional } from './chunk-YZZSJJMQ.js';
|
|
4
|
-
import { deckPage, resolveElements } from './chunk-
|
|
4
|
+
import { deckPage, resolveElements } from './chunk-MZ5WQWTS.js';
|
|
5
5
|
export { useAssetUrl } from './chunk-HCF2DXCR.js';
|
|
6
6
|
import { inlineArtifactAssets, inlineHtmlAssets } from './chunk-7T5DRR3F.js';
|
|
7
7
|
export { ASSET_REFERENCE_PREFIXES, fetchAssetDataUri, inlineArtifactAssets, inlineHtmlAssets, isAssetReference, normalizeAssetReference, resolveAssetUrl } from './chunk-7T5DRR3F.js';
|
|
@@ -2258,7 +2258,7 @@ function HtmlRenderer({ artifact: artifact2 }) {
|
|
|
2258
2258
|
var ChartRenderer = lazy(() => import('./ChartRenderer-TBTWNPV7.js').then((m) => ({ default: m.ChartRenderer })));
|
|
2259
2259
|
var DocumentRenderer = lazy(() => import('./DocumentRenderer-ER5TSNA6.js').then((m) => ({ default: m.DocumentRenderer })));
|
|
2260
2260
|
var TableRenderer = lazy(() => import('./TableRenderer-YTOF2ZIC.js').then((m) => ({ default: m.TableRenderer })));
|
|
2261
|
-
var SlidesRenderer = lazy(() => import('./SlidesRenderer-
|
|
2261
|
+
var SlidesRenderer = lazy(() => import('./SlidesRenderer-AHE5ANBZ.js').then((m) => ({ default: m.SlidesRenderer })));
|
|
2262
2262
|
var FileRenderer = lazy(() => import('./FileRenderer-2CDJYZ7I.js').then((m) => ({ default: m.FileRenderer })));
|
|
2263
2263
|
var builtinRenderers = {
|
|
2264
2264
|
html: HtmlRenderer,
|
|
@@ -2423,7 +2423,7 @@ async function slidesToPptx(data, _title) {
|
|
|
2423
2423
|
const tc = slide.textColor ? slide.textColor.replace("#", "") : void 0;
|
|
2424
2424
|
const pad = (slide.padding ?? 0) / 100;
|
|
2425
2425
|
const inset = (v) => pad + v / 100 * (1 - 2 * pad);
|
|
2426
|
-
for (const el of resolveElements(slide)) {
|
|
2426
|
+
for (const el of resolveElements(slide, { widthIn: W, heightIn: H })) {
|
|
2427
2427
|
const box = { x: inset(el.x) * W, y: inset(el.y) * H, w: el.w / 100 * (1 - 2 * pad) * W, h: el.h / 100 * (1 - 2 * pad) * H };
|
|
2428
2428
|
if (el.type === "text") {
|
|
2429
2429
|
const color = el.color ? el.color.replace("#", "") : tc;
|
|
@@ -2451,7 +2451,7 @@ function slidesToPrintHtml(data, title) {
|
|
|
2451
2451
|
const pages = slides2.map((slide) => {
|
|
2452
2452
|
const bg = slide.background ?? "#ffffff";
|
|
2453
2453
|
const fg = slide.textColor ?? "#1f2328";
|
|
2454
|
-
const els = resolveElements(slide).map((el) => {
|
|
2454
|
+
const els = resolveElements(slide, page).map((el) => {
|
|
2455
2455
|
const box = `left:${el.x}%;top:${el.y}%;width:${el.w}%;height:${el.h}%`;
|
|
2456
2456
|
if (el.type === "text") {
|
|
2457
2457
|
const style = `${box};font-size:${(el.fontSize ?? 24) / 7.2}vw;font-weight:${el.bold ? 700 : 400};color:${escapeAttr(el.color ?? fg)};text-align:${escapeAttr(el.align ?? "left")};white-space:pre-wrap`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@braincrew-lab/langchain-canvas",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "A live canvas for LangChain agents — stream documents, charts, and rich artifacts into a React panel.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Brain Crew (https://github.com/braincrew-lab)",
|
package/dist/chunk-SE6AP3A7.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
// src/client/slideElements.ts
|
|
2
|
-
function toElements(s) {
|
|
3
|
-
const layout = s.layout ?? "content";
|
|
4
|
-
const els = [];
|
|
5
|
-
const push = (id, e) => els.push({ color: s.textColor, ...e, id });
|
|
6
|
-
if (layout === "title" || layout === "section") {
|
|
7
|
-
if (s.title) push("title", { type: "text", x: 10, y: 34, w: 80, h: 18, text: s.title, fontSize: layout === "title" ? 54 : 40, bold: true, align: "center" });
|
|
8
|
-
if (s.subtitle) push("subtitle", { type: "text", x: 10, y: 58, w: 80, h: 8, text: s.subtitle, fontSize: 24, align: "center" });
|
|
9
|
-
} else if (layout === "image") {
|
|
10
|
-
if (s.title) push("title", { type: "text", x: 6, y: 6, w: 88, h: 10, text: s.title, fontSize: 28, bold: true });
|
|
11
|
-
if (s.image) els.push({ id: "img", type: "image", x: 14, y: 20, w: 72, h: 66, src: s.image });
|
|
12
|
-
} else if (layout === "two-column") {
|
|
13
|
-
if (s.title) push("title", { type: "text", x: 6, y: 6, w: 88, h: 10, text: s.title, fontSize: 28, bold: true });
|
|
14
|
-
(s.bullets ?? []).forEach((b, i) => push(`bul_${i}`, { type: "text", x: 6, y: 24 + i * 8, w: 42, h: 7, text: `\u2022 ${b}`, fontSize: 18 }));
|
|
15
|
-
(s.bullets2 ?? []).forEach((b, i) => push(`bul2_${i}`, { type: "text", x: 52, y: 24 + i * 8, w: 42, h: 7, text: `\u2022 ${b}`, fontSize: 18 }));
|
|
16
|
-
} else {
|
|
17
|
-
if (s.title) push("title", { type: "text", x: 6, y: 8, w: 88, h: 10, text: s.title, fontSize: 32, bold: true });
|
|
18
|
-
(s.bullets ?? []).forEach((b, i) => push(`bul_${i}`, { type: "text", x: 8, y: 28 + i * 9, w: 84, h: 8, text: `\u2022 ${b}`, fontSize: 20 }));
|
|
19
|
-
}
|
|
20
|
-
return els;
|
|
21
|
-
}
|
|
22
|
-
var resolveElements = (s) => s.elements?.length ? s.elements : toElements(s);
|
|
23
|
-
|
|
24
|
-
// src/client/slidePage.ts
|
|
25
|
-
var DEFAULT_SLIDE_PAGE_IN = { widthIn: 10, heightIn: 5.625 };
|
|
26
|
-
var PAGE_DPI = 96;
|
|
27
|
-
function deckPage(data) {
|
|
28
|
-
const page = data.page;
|
|
29
|
-
if (!page) return DEFAULT_SLIDE_PAGE_IN;
|
|
30
|
-
const { widthIn, heightIn } = page;
|
|
31
|
-
if (!Number.isFinite(widthIn) || !Number.isFinite(heightIn) || widthIn <= 0 || heightIn <= 0) {
|
|
32
|
-
return DEFAULT_SLIDE_PAGE_IN;
|
|
33
|
-
}
|
|
34
|
-
return { widthIn, heightIn };
|
|
35
|
-
}
|
|
36
|
-
function pageAspect(page) {
|
|
37
|
-
return `${page.widthIn} / ${page.heightIn}`;
|
|
38
|
-
}
|
|
39
|
-
function fontScaleFor(boxWidthPx, page) {
|
|
40
|
-
if (!Number.isFinite(boxWidthPx) || boxWidthPx <= 0) return 1;
|
|
41
|
-
return boxWidthPx / (page.widthIn * PAGE_DPI);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export { DEFAULT_SLIDE_PAGE_IN, deckPage, fontScaleFor, pageAspect, resolveElements };
|