claude-artifact-framework 0.19.1 → 0.19.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.
package/README.md CHANGED
@@ -908,8 +908,10 @@ keys must be unique across steps.
908
908
  `{ description, input, run(input, ctx) }`.
909
909
 
910
910
  **Formats** (`format:` on output/chart/compute items): `money`, `percent`,
911
- `number`, `date`. `percent` expects 0–100 (pass `ratio * 100`, not the raw
912
- ratio). `big: true` renders an item at hero size AND promotes its block to
911
+ `number`, `date`, `text` (explicit no-op). Anything else throws, contained
912
+ to the block. `percent` expects 0–100 (pass `ratio * 100`, not the raw
913
+ ratio); a computed `NaN`/`Infinity` renders as "—", never as "NaN".
914
+ `big: true` renders an item at hero size AND promotes its block to
913
915
  the screen's one feature surface (accent-tinted card) — reserve it for the
914
916
  ONE number that is the screen's main result (a total, a final score), not
915
917
  for every stat; more than one hero per screen means no hero at all.
package/dist/index.esm.js CHANGED
@@ -625,6 +625,7 @@ function ChatLayout({ spec, ctx }) {
625
625
  var FIELD_TYPES = ["text", "textarea", "number", "money", "percent", "check", "date", "select", "file"];
626
626
  function formatValue(value, format) {
627
627
  if (value === null || value === void 0 || value === "") return "\u2014";
628
+ if (typeof value === "number" && !Number.isFinite(value)) return "\u2014";
628
629
  const n = Number(value);
629
630
  switch (format) {
630
631
  case "money":
@@ -635,8 +636,15 @@ function formatValue(value, format) {
635
636
  return Number.isFinite(n) ? n.toLocaleString(void 0, { maximumFractionDigits: 2 }) : String(value);
636
637
  case "date":
637
638
  return value instanceof Date ? value.toLocaleDateString() : String(value);
638
- default:
639
+ case "text":
640
+ // observed natural usage (round 21) — an explicit no-op
641
+ case void 0:
642
+ case null:
639
643
  return String(value);
644
+ default:
645
+ throw new Error(
646
+ `claude-artifact-framework: unknown format "${format}". Valid formats: money, percent, number, date, text.`
647
+ );
640
648
  }
641
649
  }
642
650
  function validateField(field, value) {
@@ -756,16 +764,12 @@ function FieldsBlock({ spec, ctx }) {
756
764
  )
757
765
  );
758
766
  }
759
- function OutputBlock({ spec, ctx }) {
760
- const items = typeof spec.output === "function" ? spec.output(ctx.data) : spec.output || [];
761
- if (!items.length) {
762
- return createElement("div", { className: "caf-block caf-empty" }, spec.empty || "Nothing to show yet.");
763
- }
767
+ function StatGrid({ items, title }) {
764
768
  const hero = items.some((it) => it && it.big);
765
769
  return createElement(
766
770
  "div",
767
771
  { className: hero ? "caf-block caf-output caf-block-feature" : "caf-block caf-output" },
768
- spec.title ? createElement("h2", { className: "caf-block-title" }, spec.title) : null,
772
+ title ? createElement("h2", { className: "caf-block-title" }, title) : null,
769
773
  createElement(
770
774
  "div",
771
775
  { className: "caf-output-grid" },
@@ -781,6 +785,13 @@ function OutputBlock({ spec, ctx }) {
781
785
  )
782
786
  );
783
787
  }
788
+ function OutputBlock({ spec, ctx }) {
789
+ const items = typeof spec.output === "function" ? spec.output(ctx.data) : spec.output || [];
790
+ if (!items.length) {
791
+ return createElement("div", { className: "caf-block caf-empty" }, spec.empty || "Nothing to show yet.");
792
+ }
793
+ return createElement(StatGrid, { items, title: spec.title });
794
+ }
784
795
  function BannerBlock({ spec }) {
785
796
  const b = typeof spec.banner === "string" ? { title: spec.banner } : spec.banner || {};
786
797
  const background = b.image ? `linear-gradient(rgba(0,0,0,0.35), rgba(0,0,0,0.35)), url(${JSON.stringify(b.image)}) center / cover` : `linear-gradient(135deg, color-mix(in srgb, var(--caf-accent) 82%, #000), var(--caf-accent) 55%, color-mix(in srgb, var(--caf-accent) 72%, #fff))`;
@@ -1100,23 +1111,7 @@ function Summary({ spec, records }) {
1100
1111
  if (!spec.summary) return null;
1101
1112
  const items = spec.summary(records) || [];
1102
1113
  if (!items.length) return null;
1103
- const hero = items.some((it) => it && it.big);
1104
- return createElement(
1105
- "div",
1106
- { className: hero ? "caf-block caf-output caf-block-feature" : "caf-block caf-output" },
1107
- createElement(
1108
- "div",
1109
- { className: "caf-output-grid" },
1110
- items.map(
1111
- (item, i) => createElement(
1112
- "div",
1113
- { key: item.label || i, className: item.big ? "caf-stat caf-stat-big" : "caf-stat" },
1114
- createElement("span", { className: "caf-stat-label" }, item.label),
1115
- createElement("span", { className: "caf-stat-value" }, formatValue(item.value, item.format))
1116
- )
1117
- )
1118
- )
1119
- );
1114
+ return createElement(StatGrid, { items });
1120
1115
  }
1121
1116
  function ListScreen({ spec, ctx }) {
1122
1117
  const label = spec.label || "item";
@@ -1372,25 +1367,7 @@ function ResultScreen({ step, ctx }) {
1372
1367
  return createElement(
1373
1368
  "div",
1374
1369
  { className: "caf-steps-result" },
1375
- createElement(
1376
- "div",
1377
- // Same rule as OutputBlock: the hero (big) result gets the feature card.
1378
- { className: items.some((it) => it && it.big) ? "caf-block caf-output caf-block-feature" : "caf-block caf-output" },
1379
- step.title ? createElement("h2", { className: "caf-block-title" }, step.title) : null,
1380
- createElement(
1381
- "div",
1382
- { className: "caf-output-grid" },
1383
- items.map(
1384
- (item, i) => createElement(
1385
- "div",
1386
- { key: item.label ?? i, className: item.big ? "caf-stat caf-stat-big" : "caf-stat" },
1387
- createElement("span", { className: "caf-stat-label" }, item.label),
1388
- createElement("span", { className: "caf-stat-value" }, formatValue(item.value, item.format)),
1389
- item.hint ? createElement("small", { className: "caf-hint" }, item.hint) : null
1390
- )
1391
- )
1392
- )
1393
- ),
1370
+ createElement(StatGrid, { items, title: step.title }),
1394
1371
  // A result can end on more than stats: any declared blocks (charts,
1395
1372
  // text, lists) render under the grid with full block services.
1396
1373
  (step.blocks || []).map((b, i) => createElement(Block2, { key: "rb" + i, block: b, ctx })),