@braincrew-lab/langchain-canvas 0.7.0 → 0.7.2

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-GXCUFFEL.js';
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';
@@ -22,6 +22,8 @@ function fontScaleFor(boxWidthPx, page) {
22
22
  var FONT_DISPLAY = 48;
23
23
  var FONT_TITLE = 38;
24
24
  var BODY_RAMP = [30, 24, 19];
25
+ var TITLE_RAMP = [FONT_TITLE, 30, 24];
26
+ var DISPLAY_RAMP = [FONT_DISPLAY, FONT_TITLE, 30];
25
27
  var LINE_HEIGHT = 1.35;
26
28
  var GAP_MIN = 0.35;
27
29
  var GAP_MAX = 3;
@@ -32,6 +34,12 @@ var BODY_WIDTH = 84;
32
34
  var TITLE_TOP = 7;
33
35
  var TITLE_LEFT = 6;
34
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;
35
43
  var COLUMN_WIDTH = 42;
36
44
  var COLUMN_RIGHT_LEFT = 52;
37
45
  var BULLET = "\u2022 ";
@@ -70,6 +78,16 @@ function fit(texts, width, band, [pageW, pageH]) {
70
78
  }
71
79
  return [size, counts];
72
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
+ }
73
91
  function place(counts, size, o) {
74
92
  const n = counts.length;
75
93
  if (n === 0) return [];
@@ -103,33 +121,34 @@ function toElements(s, page) {
103
121
  const els = [];
104
122
  const push = (id, e) => els.push({ color: s.textColor, ...e, id });
105
123
  if (layout === "title" || layout === "section") {
106
- const titleH = s.title ? lineCount(s.title, TITLE_WIDTH, FONT_DISPLAY, pageW) * linePercent(FONT_DISPLAY, pageH) : 0;
107
- const subH = s.subtitle ? lineCount(s.subtitle, TITLE_WIDTH, BODY_RAMP[0], pageW) * linePercent(BODY_RAMP[0], pageH) : 0;
108
- const spacer = titleH && subH ? linePercent(BODY_RAMP[0], pageH) : 0;
109
- let y = (100 - (titleH + spacer + subH)) / 2;
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);
110
129
  if (s.title) {
111
- push("title", { type: "text", x: TITLE_LEFT, y, w: TITLE_WIDTH, h: titleH, text: s.title, fontSize: FONT_DISPLAY, bold: true, align: "center" });
130
+ push("title", { type: "text", x: TITLE_LEFT, y, w: TITLE_WIDTH, h: titleH, text: s.title, fontSize: titleSize, bold: true, align: "center" });
112
131
  y += titleH + spacer;
113
132
  }
114
133
  if (s.subtitle) {
115
- push("subtitle", { type: "text", x: TITLE_LEFT, y, w: TITLE_WIDTH, h: subH, text: s.subtitle, fontSize: BODY_RAMP[0], align: "center" });
134
+ push("subtitle", { type: "text", x: TITLE_LEFT, y, w: TITLE_WIDTH, h: subH, text: s.subtitle, fontSize: subSize, align: "center" });
116
135
  }
117
136
  return els;
118
137
  }
119
138
  let bodyTop = BODY_TOP;
120
139
  if (s.title) {
121
- const h = lineCount(s.title, TITLE_WIDTH, FONT_TITLE, pageW) * linePercent(FONT_TITLE, pageH);
122
- push("title", { type: "text", x: TITLE_LEFT, y: TITLE_TOP, w: TITLE_WIDTH, h, text: s.title, fontSize: FONT_TITLE, bold: true });
123
- bodyTop = Math.max(bodyTop, TITLE_TOP + h + linePercent(FONT_TITLE, pageH) * 0.9);
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);
124
143
  }
125
144
  if (layout === "image") {
126
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 });
127
146
  return els;
128
147
  }
129
148
  if (s.subtitle) {
130
- const h = lineCount(s.subtitle, TITLE_WIDTH, BODY_RAMP[0], pageW) * linePercent(BODY_RAMP[0], pageH);
131
- push("subtitle", { type: "text", x: TITLE_LEFT, y: bodyTop, w: TITLE_WIDTH, h, text: s.subtitle, fontSize: BODY_RAMP[0] });
132
- bodyTop = bodyTop + h + linePercent(BODY_RAMP[0], pageH) * 0.9;
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;
133
152
  }
134
153
  if (layout === "two-column") {
135
154
  const band = BODY_BOTTOM - bodyTop;
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-GXCUFFEL.js';
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-YLO3NLEY.js').then((m) => ({ default: m.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,
@@ -2310,6 +2310,7 @@ var dataExporters = {
2310
2310
  { label: "PowerPoint", extension: "pptx", mime: MIME.pptx, build: (a) => slidesToPptx(a.data, a.title) }
2311
2311
  ]
2312
2312
  };
2313
+ var PRINT_COLOR_CSS = "*{-webkit-print-color-adjust:exact;print-color-adjust:exact}";
2313
2314
  function toStandaloneHtml(title, renderedHtml) {
2314
2315
  return `<!doctype html>
2315
2316
  <html lang="en">
@@ -2317,7 +2318,8 @@ function toStandaloneHtml(title, renderedHtml) {
2317
2318
  <meta charset="utf-8" />
2318
2319
  <meta name="viewport" content="width=device-width, initial-scale=1" />
2319
2320
  <title>${escapeHtml(title)}</title>
2320
- <style>${EXPORT_CSS}</style>
2321
+ <style>${EXPORT_CSS}
2322
+ ${PRINT_COLOR_CSS}</style>
2321
2323
  </head>
2322
2324
  <body>
2323
2325
  <main class="export">
@@ -2472,6 +2474,7 @@ function slidesToPrintHtml(data, title) {
2472
2474
  return `<!doctype html><html><head><meta charset="utf-8"><title>${escapeXml(title)}</title><style>
2473
2475
  @page { size: ${pw}px ${ph}px; margin: 0; }
2474
2476
  * { margin: 0; box-sizing: border-box; }
2477
+ ${PRINT_COLOR_CSS}
2475
2478
  body { font-family: Inter, Arial, sans-serif; }
2476
2479
  .slide { position: relative; width: ${pw}px; height: ${ph}px; overflow: hidden; page-break-after: always; }
2477
2480
  .el { position: absolute; overflow: hidden; line-height: 1.25; }
@@ -2481,7 +2484,7 @@ function slidesToPrintHtml(data, title) {
2481
2484
  function htmlSlideToPrintHtml(html, ratio) {
2482
2485
  const w = ratio === "4:3" ? 960 : 1280;
2483
2486
  const h = 720;
2484
- const style = `<style>@page{size:${w}px ${h}px;margin:0}html,body{margin:0!important;padding:0!important;background:#fff}.slide-container{width:${w}px!important;height:${h}px!important;box-shadow:none!important;border-radius:0!important;overflow:hidden!important;page-break-after:avoid}</style>`;
2487
+ const style = `<style>@page{size:${w}px ${h}px;margin:0}${PRINT_COLOR_CSS}html,body{margin:0!important;padding:0!important;background:#fff}.slide-container{width:${w}px!important;height:${h}px!important;box-shadow:none!important;border-radius:0!important;overflow:hidden!important;page-break-after:avoid}</style>`;
2485
2488
  const i = html.toLowerCase().lastIndexOf("</head>");
2486
2489
  return i === -1 ? style + html : html.slice(0, i) + style + html.slice(i);
2487
2490
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@braincrew-lab/langchain-canvas",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
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)",