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 +4 -2
- package/dist/index.esm.js +20 -43
- package/dist/index.esm.js.map +2 -2
- package/dist/index.global.js +12 -12
- package/dist/index.global.js.map +3 -3
- package/llms.txt +2 -1
- package/package.json +1 -1
- package/src/blocks.js +28 -11
- package/src/records.js +4 -21
- package/src/steps.js +2 -20
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
|
|
912
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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 })),
|