@pipelex/mthds-form 0.30.0 → 0.31.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.
- package/dist/brand/index.d.ts +9 -257
- package/dist/brand/index.js +9 -645
- package/dist/brand/index.js.map +1 -1
- package/dist/{chunk-ZX52CQJ4.js → chunk-2UCH4AAO.js} +3 -3
- package/dist/{chunk-ZX52CQJ4.js.map → chunk-2UCH4AAO.js.map} +1 -1
- package/dist/{chunk-JCFALTTY.js → chunk-ENK5QTUK.js} +116 -28
- package/dist/chunk-ENK5QTUK.js.map +1 -0
- package/dist/{chunk-ZB4RYUKV.js → chunk-HVWE3TTC.js} +3 -3
- package/dist/{chunk-ZB4RYUKV.js.map → chunk-HVWE3TTC.js.map} +1 -1
- package/dist/chunk-UZNRJWN5.js +721 -0
- package/dist/chunk-UZNRJWN5.js.map +1 -0
- package/dist/{chunk-IBBAJXIO.js → chunk-XVGAQ4RK.js} +4 -4
- package/dist/{chunk-IBBAJXIO.js.map → chunk-XVGAQ4RK.js.map} +1 -1
- package/dist/core/derive.js +2 -2
- package/dist/core/gate.js +3 -3
- package/dist/core/index.js +12 -12
- package/dist/core/values.js +3 -3
- package/dist/generative/index.d.ts +474 -79
- package/dist/generative/index.js +1195 -480
- package/dist/generative/index.js.map +1 -1
- package/dist/layout-design.mthds +133 -6
- package/dist/react/index.d.ts +18 -3
- package/dist/react/index.js +7 -7
- package/dist/styles-BoXPBjF4.d.ts +258 -0
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/dist/chunk-JCFALTTY.js.map +0 -1
- package/dist/chunk-QFX332LE.js +0 -22
- package/dist/chunk-QFX332LE.js.map +0 -1
- package/dist/manifest-DUeAWeqa.d.ts +0 -17
package/dist/generative/index.js
CHANGED
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { cn, headingClass, checkedAccentClass, focusOutlineClass, actionShadowClass, panelSurfaceClass, panelRaisedShadowClass, linkTextClass, selectedBorderClass, selectedFillClass, fieldControlClass, ResultRoot, ResultField, FieldRenderer, enumLabeler, useFieldPresentation, ToggleGroup, ToggleGroupItem, selectedFillStrongClass, Switch, Select, SelectTrigger, SelectValue, SelectContent, SelectItem,
|
|
2
|
+
import { cn, headingClass, checkedAccentClass, focusOutlineClass, actionShadowClass, panelSurfaceClass, panelRaisedShadowClass, linkTextClass, selectedBorderClass, selectedFillClass, fieldControlClass, useResolveUrl, panelFlatShadowClass, ResultRoot, ResultField, FieldRenderer, enumLabeler, useFieldPresentation, ToggleGroup, ToggleGroupItem, selectedFillStrongClass, Switch, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, isThenable } from '../chunk-ENK5QTUK.js';
|
|
3
|
+
import '../chunk-2UCH4AAO.js';
|
|
3
4
|
import '../chunk-4VAO6BDE.js';
|
|
4
5
|
export { seedInputs } from '../chunk-VH5CDQDR.js';
|
|
5
6
|
import '../chunk-L23R3JNQ.js';
|
|
6
7
|
import '../chunk-56WECFBD.js';
|
|
7
|
-
import '../chunk-ZX52CQJ4.js';
|
|
8
|
-
import '../chunk-GHVVULHY.js';
|
|
9
|
-
import { isNativeValueNode, readDateContent, formatDateContent, isNativeHtmlNode, isNativeDateNode, isNativeCompositeNode } from '../chunk-QQK6Y55E.js';
|
|
10
|
-
export { brandManifestSchema } from '../chunk-QFX332LE.js';
|
|
11
|
-
import '../chunk-ZB4RYUKV.js';
|
|
12
|
-
import '../chunk-FABY3DEY.js';
|
|
13
|
-
import '../chunk-XCO6GTEC.js';
|
|
14
8
|
import '../chunk-E6BIXJ6C.js';
|
|
15
9
|
import '../chunk-XO5OENNF.js';
|
|
10
|
+
import '../chunk-GHVVULHY.js';
|
|
11
|
+
import { readImageContent, viewableUrl, readDateContent, isNativeValueNode, formatDateContent, isNativeHtmlNode, isNativeDateNode, isNativeCompositeNode } from '../chunk-QQK6Y55E.js';
|
|
12
|
+
import { APP_STYLES } from '../chunk-UZNRJWN5.js';
|
|
13
|
+
export { brandManifestSchema } from '../chunk-UZNRJWN5.js';
|
|
14
|
+
import '../chunk-HVWE3TTC.js';
|
|
16
15
|
import '../chunk-OD3VYXUY.js';
|
|
17
16
|
import '../chunk-WYH56SOZ.js';
|
|
18
17
|
import { hasOwnProp } from '../chunk-V3OV2XQT.js';
|
|
18
|
+
import '../chunk-FABY3DEY.js';
|
|
19
|
+
import '../chunk-XCO6GTEC.js';
|
|
19
20
|
import '../chunk-GKV77RAS.js';
|
|
20
21
|
import { defineSchema, defineCatalog, validateSpec, compileSpecStream } from '@json-render/core';
|
|
22
|
+
export { createStateStore } from '@json-render/core';
|
|
21
23
|
import { z } from 'zod';
|
|
22
|
-
import * as
|
|
24
|
+
import * as React4 from 'react';
|
|
23
25
|
import { defineRegistry, useStateValue, useStateStore, useBoundProp, useFieldValidation, useRepeatScope, JSONUIProvider, Renderer } from '@json-render/react';
|
|
24
26
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
25
|
-
import { Send, Pencil, Zap, Lightbulb, Truck, Package, Briefcase, Bookmark, Flag, Shield, Info, AlertCircle, CheckCircle2, ListChecks, Layers, Tag, Phone, Mail, Paperclip, Upload, FileText, BarChart3, TrendingUp, Hash, Percent, Receipt, Coins, Banknote, Wallet, Gift, Ticket, Image, Camera, Music, Coffee, Utensils, Star, Heart, Accessibility, Baby, User, Users, Hourglass,
|
|
27
|
+
import { Clock, ArrowRight, Send, Pencil, Zap, Lightbulb, Truck, Package, Briefcase, Bookmark, Flag, Shield, Info, AlertCircle, CheckCircle2, ListChecks, Layers, Tag, Phone, Mail, Paperclip, Upload, FileText, BarChart3, TrendingUp, Hash, Percent, Receipt, Coins, Banknote, Wallet, Gift, Ticket, Image, Camera, Music, Coffee, Utensils, Star, Heart, Accessibility, Baby, User, Users, Hourglass, Calendar, Moon, Sun, Leaf, Mountain, Globe, Landmark, Building2, Home, Hotel, Ship, Car, Train, Plane, Route, MapPin, Map as Map$1, Compass, Rocket, Sparkles, ChevronDown } from 'lucide-react';
|
|
26
28
|
import * as TabsPrimitive from '@radix-ui/react-tabs';
|
|
27
29
|
|
|
28
30
|
var generativeSchema = defineSchema(
|
|
@@ -497,10 +499,13 @@ var components = {
|
|
|
497
499
|
// ── The escape hatches and the bound equivalents (ours) ────────────────
|
|
498
500
|
MthdsField: {
|
|
499
501
|
props: z.object({
|
|
500
|
-
path: z.string()
|
|
502
|
+
path: z.string(),
|
|
503
|
+
// The page words the label and the line under it, as it words every other control.
|
|
504
|
+
label: z.string().nullable(),
|
|
505
|
+
hint: z.string().nullable()
|
|
501
506
|
}),
|
|
502
507
|
slots: [],
|
|
503
|
-
description: `The kernel's own control for ONE input, bound two-way at "path" (a /inputs path from the brief). Use it for every path the brief marks as delegated - a file, a date, a list, a structure you would rather not lay out - and for any scalar you would rather not style. It renders
|
|
508
|
+
description: `The kernel's own control for ONE input, bound two-way at "path" (a /inputs path from the brief). Use it for every path the brief marks as delegated - a file, a date, a list, a structure you would rather not lay out - and for any scalar you would rather not style. It renders the descriptor's label and description unless the page words them: "label" replaces the label, "hint" the line under it. Inside a repeat, "path" is the item's field name relative to the item ("lines"), never an $item expression.`,
|
|
504
509
|
example: { path: "/inputs/source" }
|
|
505
510
|
},
|
|
506
511
|
MthdsResult: {
|
|
@@ -515,11 +520,18 @@ var components = {
|
|
|
515
520
|
DataTable: {
|
|
516
521
|
props: z.object({
|
|
517
522
|
rows: z.any(),
|
|
518
|
-
|
|
523
|
+
// A column says how its cells read, from the kind the brief states.
|
|
524
|
+
columns: z.array(
|
|
525
|
+
z.object({
|
|
526
|
+
path: z.string(),
|
|
527
|
+
label: z.string(),
|
|
528
|
+
format: z.enum(["text", "date", "number"]).nullable().optional()
|
|
529
|
+
})
|
|
530
|
+
),
|
|
519
531
|
caption: z.string().nullable()
|
|
520
532
|
}),
|
|
521
533
|
slots: [],
|
|
522
|
-
description: 'A table over a list of structures. "rows" MUST be { "$state": "/path/to/the/list" } (never inline rows); each column names a field of one item by its relative path ("label", "unit_price")
|
|
534
|
+
description: 'A table over a list of structures. "rows" MUST be { "$state": "/path/to/the/list" } (never inline rows); each column names a field of one item by its relative path ("label", "unit_price"), the header to show for it, and how its cells read: "date" for a date path (written "9 Mar 2025"), "number" for a number path (digits grouped), "text" otherwise.',
|
|
523
535
|
example: {
|
|
524
536
|
rows: { $state: "/result/lines" },
|
|
525
537
|
columns: [
|
|
@@ -549,6 +561,134 @@ var actions = {
|
|
|
549
561
|
defineCatalog(generativeSchema, { components, actions });
|
|
550
562
|
var generativeComponents = components;
|
|
551
563
|
var generativeActions = actions;
|
|
564
|
+
var FRAMES = ["page", "composer", "result"];
|
|
565
|
+
var COMPOSER_COMPONENTS = ["Composer", "FieldGroup"];
|
|
566
|
+
var RESULT_COMPONENTS = [
|
|
567
|
+
"ResultHeader",
|
|
568
|
+
"ProportionBar",
|
|
569
|
+
"Swatches",
|
|
570
|
+
"Picture",
|
|
571
|
+
"Fact",
|
|
572
|
+
"Detail",
|
|
573
|
+
"DateText",
|
|
574
|
+
"TextList"
|
|
575
|
+
];
|
|
576
|
+
var FRAME_COMPONENTS = [...COMPOSER_COMPONENTS, ...RESULT_COMPONENTS];
|
|
577
|
+
var frameComponents = {
|
|
578
|
+
Composer: {
|
|
579
|
+
props: z.object({
|
|
580
|
+
headline: z.string(),
|
|
581
|
+
lede: z.string().nullable(),
|
|
582
|
+
runLabel: z.string(),
|
|
583
|
+
columns: z.enum(["1", "2"]).nullable(),
|
|
584
|
+
notes: z.array(z.string()).nullable()
|
|
585
|
+
}),
|
|
586
|
+
slots: ["default"],
|
|
587
|
+
events: ["press"],
|
|
588
|
+
description: `The composer: the page's headline (rendered as the h1) and one muted line under it, then a single raised panel holding its children - the inputs - in one column, or two columns side by side when "columns" is "2", and at the panel's foot the host's action row: how long a run takes, as the host knows it, and the one button that runs the method, worded by "runLabel". The action row stays on screen while a long panel scrolls. It is the control that runs the method: bind on.press to validateForm then run. "notes" are a few short lines set under the panel, each after a check mark, in two columns: what one run gives back, in a person's words.`,
|
|
589
|
+
example: {
|
|
590
|
+
headline: "A day-by-day plan for your trip",
|
|
591
|
+
lede: "Tell us who is going, where and when.",
|
|
592
|
+
runLabel: "Plan my trip",
|
|
593
|
+
columns: "2"
|
|
594
|
+
}
|
|
595
|
+
},
|
|
596
|
+
FieldGroup: {
|
|
597
|
+
props: z.object({ title: z.string().nullable() }),
|
|
598
|
+
slots: ["default"],
|
|
599
|
+
description: "A quiet group of inputs inside a panel: an optional small h2 title, then its children stacked with even spacing. No box, no rule: the panel around it is the surface.",
|
|
600
|
+
example: { title: "Where and when" }
|
|
601
|
+
},
|
|
602
|
+
ResultHeader: {
|
|
603
|
+
props: z.object({
|
|
604
|
+
eyebrow: z.string().nullable(),
|
|
605
|
+
title: z.string(),
|
|
606
|
+
subtitle: z.string().nullable()
|
|
607
|
+
}),
|
|
608
|
+
slots: [],
|
|
609
|
+
description: `The result's heading: a small eyebrow in the accent colour, the title (rendered as the h1) and one muted line under it, with the host's actions on the result (download, share) at the right. Text props may be read from the state with { "$state" } or { "$template" }.`,
|
|
610
|
+
example: {
|
|
611
|
+
eyebrow: "Your plan",
|
|
612
|
+
title: { $state: "/result/title" },
|
|
613
|
+
subtitle: { $template: "${/result/currency} ${/result/estimated_total} estimated" }
|
|
614
|
+
}
|
|
615
|
+
},
|
|
616
|
+
ProportionBar: {
|
|
617
|
+
props: z.object({
|
|
618
|
+
label: z.string(),
|
|
619
|
+
total: z.number().nullable(),
|
|
620
|
+
of: z.number().nullable(),
|
|
621
|
+
unit: z.string().nullable(),
|
|
622
|
+
items: z.array(z.any()).nullable(),
|
|
623
|
+
labelKey: z.string(),
|
|
624
|
+
valueKey: z.string()
|
|
625
|
+
}),
|
|
626
|
+
slots: [],
|
|
627
|
+
description: 'A labelled total over its parts, in a raised panel: the label and the total in large figures ("of" a ceiling when there is one), then one bar split in proportion to each part, and a legend naming each part with its amount. "items" is { "$state": ... } on a list of structures; "labelKey" and "valueKey" name the member of one item that labels it and the number that sizes it. "unit" is a currency or unit the state carries, read with { "$state" }.',
|
|
628
|
+
example: {
|
|
629
|
+
label: "Estimated cost",
|
|
630
|
+
total: { $state: "/result/estimated_total" },
|
|
631
|
+
unit: { $state: "/result/currency" },
|
|
632
|
+
items: { $state: "/result/costs" },
|
|
633
|
+
labelKey: "category",
|
|
634
|
+
valueKey: "amount"
|
|
635
|
+
}
|
|
636
|
+
},
|
|
637
|
+
Swatches: {
|
|
638
|
+
props: z.object({ colors: z.array(z.string()) }),
|
|
639
|
+
slots: [],
|
|
640
|
+
description: 'A row of colour swatches, each a small tile filled with the colour and its value written under it in mono. "colors" is a list of colour values, each read from a text path ({ "$state" }, or { "$item" } inside a repeat).',
|
|
641
|
+
example: { colors: [{ $item: "colors/primary" }, { $item: "colors/accent" }] }
|
|
642
|
+
},
|
|
643
|
+
Picture: {
|
|
644
|
+
props: z.object({
|
|
645
|
+
path: z.string(),
|
|
646
|
+
alt: z.string().nullable(),
|
|
647
|
+
aspect: z.enum(["16:9", "4:3", "1:1", "auto"]).nullable()
|
|
648
|
+
}),
|
|
649
|
+
slots: [],
|
|
650
|
+
description: 'A picture the run produced, shown whole and edge to edge in its column with a hairline border, cropped to "aspect" when one is set. "path" is an image path of the brief, literally ("/result/cover"), or relative to the item inside a repeat ("" for the item itself, when the repeat is over a list of images).',
|
|
651
|
+
example: { path: "/result/cover", alt: "The cover", aspect: "16:9" }
|
|
652
|
+
},
|
|
653
|
+
Fact: {
|
|
654
|
+
props: z.object({
|
|
655
|
+
label: z.string(),
|
|
656
|
+
value: z.any(),
|
|
657
|
+
detail: z.string().nullable()
|
|
658
|
+
}),
|
|
659
|
+
slots: [],
|
|
660
|
+
description: 'One fact as a small boxed tile: a muted label, the value under it, and an optional muted detail. Several in a Grid make a band of facts. "value" is a scalar read with { "$state" } or { "$template" }.',
|
|
661
|
+
example: { label: "Order number", value: { $state: "/result/number" } }
|
|
662
|
+
},
|
|
663
|
+
DateText: {
|
|
664
|
+
props: z.object({
|
|
665
|
+
value: z.string().nullable(),
|
|
666
|
+
style: z.enum(["long", "short", "weekday"]).nullable(),
|
|
667
|
+
tone: z.enum(["default", "muted", "accent"]).nullable()
|
|
668
|
+
}),
|
|
669
|
+
slots: [],
|
|
670
|
+
description: 'A date written in words: "long" is "Wednesday 14 April 2027", "short" is "14 Apr 2027", "weekday" is "Wed 14 April". "value" is a date path read with { "$state" } or { "$item" }; "tone" colours it muted or in the accent colour, as an eyebrow over a title.',
|
|
671
|
+
example: { value: { $item: "day" }, style: "weekday", tone: "accent" }
|
|
672
|
+
},
|
|
673
|
+
TextList: {
|
|
674
|
+
props: z.object({
|
|
675
|
+
items: z.array(z.string()).nullable(),
|
|
676
|
+
marker: z.enum(["bullet", "number", "check"]).nullable()
|
|
677
|
+
}),
|
|
678
|
+
slots: [],
|
|
679
|
+
description: 'A list of short texts as one list, each entry a line with a small marker before it: a dot, its number or a check. "items" reads a list of text path with { "$state" }, or { "$item" } inside a repeat - the whole list at once, so it needs no repeat of its own.',
|
|
680
|
+
example: { items: { $state: "/result/notes" }, marker: "bullet" }
|
|
681
|
+
},
|
|
682
|
+
Detail: {
|
|
683
|
+
props: z.object({
|
|
684
|
+
label: z.string(),
|
|
685
|
+
value: z.any()
|
|
686
|
+
}),
|
|
687
|
+
slots: [],
|
|
688
|
+
description: 'A labelled line of text: the label muted in a narrow column at the left, the value wrapping beside it, a hairline under the line. Several in a column read as a list of details. "value" is a scalar read with { "$state" }, { "$item" } or { "$template" }; the line hides itself while the value is empty.',
|
|
689
|
+
example: { label: "Morning", value: { $item: "morning" } }
|
|
690
|
+
}
|
|
691
|
+
};
|
|
552
692
|
|
|
553
693
|
// src/generative/catalog.ts
|
|
554
694
|
var PRODUCT_COMPONENTS = [
|
|
@@ -644,11 +784,14 @@ var COMPONENT_RENDERINGS = {
|
|
|
644
784
|
Split: { children: { count: 2, roles: "left, right" } },
|
|
645
785
|
Workspace: { children: { count: 2, roles: "work, rail" } },
|
|
646
786
|
Tabs: { panels: { prop: "tabs", noun: "tab" } },
|
|
647
|
-
Steps: { panels: { prop: "steps", noun: "step" } }
|
|
787
|
+
Steps: { panels: { prop: "steps", noun: "step" } },
|
|
788
|
+
Composer: { heading: { level: 1 }, once: "the composer" },
|
|
789
|
+
ResultHeader: { heading: { level: 1 }, once: "the result's header" },
|
|
790
|
+
FieldGroup: { heading: { level: 2, when: "title" } }
|
|
648
791
|
};
|
|
649
792
|
var catalog = Object.assign(
|
|
650
793
|
defineCatalog(generativeSchema, {
|
|
651
|
-
components: { ...generativeComponents, ...product },
|
|
794
|
+
components: { ...generativeComponents, ...product, ...frameComponents },
|
|
652
795
|
actions: generativeActions
|
|
653
796
|
}),
|
|
654
797
|
{ renders: COMPONENT_RENDERINGS }
|
|
@@ -658,6 +801,60 @@ var COMPONENT_NAMES = [
|
|
|
658
801
|
...CUSTOM_COMPONENTS,
|
|
659
802
|
...PRODUCT_COMPONENTS
|
|
660
803
|
];
|
|
804
|
+
var FRAME_EXCLUDED = {
|
|
805
|
+
page: [...FRAME_COMPONENTS],
|
|
806
|
+
composer: [
|
|
807
|
+
"AppBar",
|
|
808
|
+
"Footer",
|
|
809
|
+
"Workspace",
|
|
810
|
+
"Rail",
|
|
811
|
+
"Cta",
|
|
812
|
+
"Button",
|
|
813
|
+
"Hero",
|
|
814
|
+
"SummaryRow",
|
|
815
|
+
"MthdsResult",
|
|
816
|
+
"DataTable",
|
|
817
|
+
"Metric",
|
|
818
|
+
"Progress",
|
|
819
|
+
// `TextList` stays: a composer may list short texts too, such as what a
|
|
820
|
+
// run gives back.
|
|
821
|
+
...RESULT_COMPONENTS.filter((name) => name !== "TextList")
|
|
822
|
+
],
|
|
823
|
+
result: [
|
|
824
|
+
"AppBar",
|
|
825
|
+
"Footer",
|
|
826
|
+
"Workspace",
|
|
827
|
+
"Rail",
|
|
828
|
+
"Cta",
|
|
829
|
+
"Button",
|
|
830
|
+
"Hero",
|
|
831
|
+
"MthdsField",
|
|
832
|
+
"Input",
|
|
833
|
+
"Textarea",
|
|
834
|
+
"Select",
|
|
835
|
+
"Radio",
|
|
836
|
+
"Checkbox",
|
|
837
|
+
"Switch",
|
|
838
|
+
"Segmented",
|
|
839
|
+
"NumberInput",
|
|
840
|
+
"Steps",
|
|
841
|
+
...COMPOSER_COMPONENTS
|
|
842
|
+
]
|
|
843
|
+
};
|
|
844
|
+
function componentNamesFor(frame) {
|
|
845
|
+
const excluded = new Set(FRAME_EXCLUDED[frame]);
|
|
846
|
+
const own = frame === "page" ? [] : [...FRAME_COMPONENTS];
|
|
847
|
+
return [...COMPONENT_NAMES, ...own].filter((name) => !excluded.has(name));
|
|
848
|
+
}
|
|
849
|
+
function frameCatalog(frame) {
|
|
850
|
+
return {
|
|
851
|
+
componentNames: componentNamesFor(frame),
|
|
852
|
+
actionNames: catalog.actionNames,
|
|
853
|
+
data: catalog.data,
|
|
854
|
+
schema: catalog.schema,
|
|
855
|
+
renders: COMPONENT_RENDERINGS
|
|
856
|
+
};
|
|
857
|
+
}
|
|
661
858
|
|
|
662
859
|
// src/generative/props-signature.ts
|
|
663
860
|
function definitionOf(schema) {
|
|
@@ -704,9 +901,9 @@ function propsSignature(schema) {
|
|
|
704
901
|
|
|
705
902
|
// src/generative/designer-catalog.ts
|
|
706
903
|
var DESIGNER_CATALOG_CONCEPT = "generative.Catalog";
|
|
707
|
-
function designerCatalog() {
|
|
904
|
+
function designerCatalog({ frame = "page" } = {}) {
|
|
708
905
|
const definitions = catalog.data.components;
|
|
709
|
-
const components3 =
|
|
906
|
+
const components3 = componentNamesFor(frame).map((name) => {
|
|
710
907
|
const definition = definitions[name];
|
|
711
908
|
if (!definition) throw new Error(`the catalog defines no component named '${name}'`);
|
|
712
909
|
const slots = definition.slots ?? [];
|
|
@@ -735,7 +932,12 @@ function designerCatalog() {
|
|
|
735
932
|
}
|
|
736
933
|
|
|
737
934
|
// src/generative/prompt-hash.ts
|
|
738
|
-
var PROMPT_HASH = "
|
|
935
|
+
var PROMPT_HASH = "30cf9bc059f6";
|
|
936
|
+
function promptHashSubject(method) {
|
|
937
|
+
const catalogs = FRAMES.map((frame) => designerCatalog({ frame }));
|
|
938
|
+
return `${method}
|
|
939
|
+
${JSON.stringify(catalogs)}`;
|
|
940
|
+
}
|
|
739
941
|
|
|
740
942
|
// src/generative/paths.ts
|
|
741
943
|
var INPUTS_ROOT = "/inputs";
|
|
@@ -822,169 +1024,351 @@ function repeatListPathOf(spec, key, parents = parentMapOf(spec)) {
|
|
|
822
1024
|
return outer !== void 0 && typeof item === "string" ? joinPath(outer, item) : void 0;
|
|
823
1025
|
}
|
|
824
1026
|
|
|
825
|
-
// src/generative/
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
function isDelegatedInput(field) {
|
|
829
|
-
return field.kind === "document" || field.kind === "image" || field.kind === "date" || field.kind === "list" || field.kind === "unknown" || field.kind === "enum" && field.options.includes("");
|
|
1027
|
+
// src/generative/layout-fits.ts
|
|
1028
|
+
function isUnder(root, path) {
|
|
1029
|
+
return path === root || path.startsWith(`${root}/`);
|
|
830
1030
|
}
|
|
831
|
-
function
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
return field
|
|
1031
|
+
function itemPathResolver(spec, key, parents) {
|
|
1032
|
+
let base;
|
|
1033
|
+
let resolvedBase = false;
|
|
1034
|
+
return (field) => {
|
|
1035
|
+
if (!resolvedBase) {
|
|
1036
|
+
base = repeatBasePathOf(spec, key, parents);
|
|
1037
|
+
resolvedBase = true;
|
|
1038
|
+
}
|
|
1039
|
+
if (base === void 0) return void 0;
|
|
1040
|
+
const under = field.startsWith("/") ? field.slice(1) : field;
|
|
1041
|
+
return under === "" ? base : `${base}/${under}`;
|
|
1042
|
+
};
|
|
835
1043
|
}
|
|
836
|
-
function
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
case "prose":
|
|
844
|
-
return "prose (markdown)";
|
|
845
|
-
case "number":
|
|
846
|
-
return field.integer ? "integer" : "number";
|
|
847
|
-
case "boolean":
|
|
848
|
-
return "boolean";
|
|
849
|
-
case "enum":
|
|
850
|
-
return `choice of ${field.options.map((option) => JSON.stringify(option)).join(" | ")}`;
|
|
851
|
-
case "date":
|
|
852
|
-
return field.datetime ? "date with time" : "date";
|
|
853
|
-
case "document":
|
|
854
|
-
return "document (a file)";
|
|
855
|
-
case "image":
|
|
856
|
-
return "image (a file)";
|
|
857
|
-
case "object":
|
|
858
|
-
return `structure${field.conceptRef ? ` ${field.conceptRef}` : ""}`;
|
|
859
|
-
case "list":
|
|
860
|
-
return `list of ${kindLabel(field.item)}`;
|
|
861
|
-
case "unknown":
|
|
862
|
-
return "unknown";
|
|
863
|
-
default:
|
|
864
|
-
return field;
|
|
865
|
-
}
|
|
1044
|
+
function interpolatedPaths(template, itemPath) {
|
|
1045
|
+
return [...template.matchAll(/\$\{([^}]+)\}/g)].flatMap((match) => {
|
|
1046
|
+
const raw = match[1];
|
|
1047
|
+
if (raw === void 0) return [];
|
|
1048
|
+
if (raw.startsWith("/")) return [raw];
|
|
1049
|
+
return [itemPath(raw) ?? `/${raw}`];
|
|
1050
|
+
});
|
|
866
1051
|
}
|
|
867
|
-
function
|
|
868
|
-
const
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
1052
|
+
function mentionedPaths(spec, parents) {
|
|
1053
|
+
const found = { bound: [], read: [], adrift: [] };
|
|
1054
|
+
for (const [key, element] of Object.entries(spec.elements)) {
|
|
1055
|
+
const itemPath = itemPathResolver(spec, key, parents);
|
|
1056
|
+
const walk = (value) => {
|
|
1057
|
+
if (Array.isArray(value)) {
|
|
1058
|
+
value.forEach(walk);
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
1061
|
+
if (typeof value !== "object" || value === null) return;
|
|
1062
|
+
const record = value;
|
|
1063
|
+
if (typeof record.$bindState === "string") found.bound.push(record.$bindState);
|
|
1064
|
+
if (typeof record.$state === "string") found.read.push(record.$state);
|
|
1065
|
+
if (typeof record.$template === "string") {
|
|
1066
|
+
found.read.push(...interpolatedPaths(record.$template, itemPath));
|
|
1067
|
+
}
|
|
1068
|
+
if (typeof record.$bindItem === "string") {
|
|
1069
|
+
const path = itemPath(record.$bindItem);
|
|
1070
|
+
if (path === void 0) found.adrift.push(key);
|
|
1071
|
+
else found.bound.push(path);
|
|
1072
|
+
}
|
|
1073
|
+
if (typeof record.$item === "string") {
|
|
1074
|
+
const path = itemPath(record.$item);
|
|
1075
|
+
if (path === void 0) found.adrift.push(key);
|
|
1076
|
+
else found.read.push(path);
|
|
1077
|
+
}
|
|
1078
|
+
Object.values(record).forEach(walk);
|
|
1079
|
+
};
|
|
1080
|
+
walk(element.props);
|
|
1081
|
+
walk(element.visible);
|
|
890
1082
|
}
|
|
891
|
-
return
|
|
1083
|
+
return found;
|
|
892
1084
|
}
|
|
893
|
-
function
|
|
894
|
-
const
|
|
895
|
-
return
|
|
896
|
-
depth,
|
|
897
|
-
path,
|
|
898
|
-
kind: kindLabel(field),
|
|
899
|
-
name: field.name,
|
|
900
|
-
title: field.title && field.title !== field.name ? field.title : void 0,
|
|
901
|
-
description: field.description,
|
|
902
|
-
required: side === "input" ? field.required : void 0,
|
|
903
|
-
gating: side === "input" && field.gating ? true : void 0,
|
|
904
|
-
notes: notes.length > 0 ? notes : void 0,
|
|
905
|
-
default: seeded || field.defaultValue === void 0 ? void 0 : JSON.stringify(field.defaultValue),
|
|
906
|
-
delegated: side === "input" ? isDelegatedInput(field) : isDelegatedResult(field),
|
|
907
|
-
relative: relative ? true : void 0
|
|
908
|
-
};
|
|
1085
|
+
function staleReads(read, root, resolves) {
|
|
1086
|
+
const under = read.filter((path) => isUnder(root, path));
|
|
1087
|
+
return [...new Set(under)].filter((path) => !resolves(path));
|
|
909
1088
|
}
|
|
910
|
-
function
|
|
911
|
-
const
|
|
912
|
-
entries.
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
if (field.kind === "list" && side === "result") {
|
|
921
|
-
const item = field.item;
|
|
922
|
-
entry.item_kind = kindLabel(item);
|
|
923
|
-
entry.item_description = item.description;
|
|
924
|
-
if (item.kind === "object" && !isDelegatedResult(item)) {
|
|
925
|
-
entry.item_laid_out = true;
|
|
926
|
-
for (const child of item.fields) {
|
|
927
|
-
describeRelative(child, child.name, depth + 2, entries);
|
|
928
|
-
}
|
|
1089
|
+
function staleRepeats(spec, parents, root, resolves, side) {
|
|
1090
|
+
const problems = [];
|
|
1091
|
+
for (const [key, element] of Object.entries(spec.elements)) {
|
|
1092
|
+
if (!element.repeat) continue;
|
|
1093
|
+
const listPath = repeatListPathOf(spec, key, parents);
|
|
1094
|
+
if (listPath === void 0 || !isUnder(root, listPath)) continue;
|
|
1095
|
+
if (!resolves(listPath)) {
|
|
1096
|
+
problems.push(`${key}: repeats over ${listPath}, which no ${side} has`);
|
|
929
1097
|
}
|
|
930
1098
|
}
|
|
1099
|
+
return problems;
|
|
931
1100
|
}
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
1101
|
+
var NOT_A_VALUE = {
|
|
1102
|
+
object: { what: "a structure", instead: "a structure is shown through its members" },
|
|
1103
|
+
list: { what: "a list", instead: "a list is laid out as a repeat or a DataTable" },
|
|
1104
|
+
document: { what: "a file", instead: "a file is delegated to the kernel's own control" },
|
|
1105
|
+
image: { what: "a file", instead: "a file is delegated to the kernel's own control" }
|
|
1106
|
+
};
|
|
1107
|
+
var NOT_VALUES = {
|
|
1108
|
+
object: "structures",
|
|
1109
|
+
list: "lists",
|
|
1110
|
+
document: "files",
|
|
1111
|
+
image: "files"
|
|
1112
|
+
};
|
|
1113
|
+
var listPropsCache;
|
|
1114
|
+
function listProps() {
|
|
1115
|
+
if (listPropsCache) return listPropsCache;
|
|
1116
|
+
const found = /* @__PURE__ */ new Map([
|
|
1117
|
+
["DataTable", /* @__PURE__ */ new Map([["rows", "anything"]])]
|
|
1118
|
+
]);
|
|
1119
|
+
const components3 = catalog.data.components;
|
|
1120
|
+
for (const [type, definition] of Object.entries(components3)) {
|
|
1121
|
+
const shape = definition.props?.shape;
|
|
1122
|
+
for (const [prop, schema] of Object.entries(shape ?? {})) {
|
|
1123
|
+
const items = listItemsOf(schema);
|
|
1124
|
+
if (items === void 0) continue;
|
|
1125
|
+
if (!found.has(type)) found.set(type, /* @__PURE__ */ new Map());
|
|
1126
|
+
found.get(type).set(prop, items);
|
|
939
1127
|
}
|
|
940
1128
|
}
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
1129
|
+
listPropsCache = found;
|
|
1130
|
+
return found;
|
|
1131
|
+
}
|
|
1132
|
+
var VALUE_SCHEMAS = /* @__PURE__ */ new Set(["string", "number", "boolean", "enum", "literal"]);
|
|
1133
|
+
function unwrapped(schema) {
|
|
1134
|
+
let current = schema;
|
|
1135
|
+
for (let depth = 0; depth < 8; depth += 1) {
|
|
1136
|
+
const def = current.def;
|
|
1137
|
+
if (!def) return void 0;
|
|
1138
|
+
if (def.innerType === void 0) return def;
|
|
1139
|
+
current = def.innerType;
|
|
1140
|
+
}
|
|
1141
|
+
return void 0;
|
|
1142
|
+
}
|
|
1143
|
+
function listItemsOf(schema) {
|
|
1144
|
+
const def = unwrapped(schema);
|
|
1145
|
+
if (def?.type !== "array") return void 0;
|
|
1146
|
+
const element = unwrapped(def.element);
|
|
1147
|
+
return element?.type !== void 0 && VALUE_SCHEMAS.has(element.type) ? "values" : "anything";
|
|
1148
|
+
}
|
|
1149
|
+
function nonScalarReads(spec, parents, root, fieldAt) {
|
|
1150
|
+
const problems = [];
|
|
1151
|
+
const lists = listProps();
|
|
1152
|
+
for (const [key, element] of Object.entries(spec.elements)) {
|
|
1153
|
+
const itemPath = itemPathResolver(spec, key, parents);
|
|
1154
|
+
const listy = lists.get(element.type);
|
|
1155
|
+
const check = (prop, path) => {
|
|
1156
|
+
if (!isUnder(root, path)) return;
|
|
1157
|
+
const field = fieldAt(path);
|
|
1158
|
+
if (!field) return;
|
|
1159
|
+
const wrong = hasOwnProp(NOT_A_VALUE, field.kind) ? NOT_A_VALUE[field.kind] : void 0;
|
|
1160
|
+
if (!wrong) return;
|
|
1161
|
+
problems.push(
|
|
1162
|
+
`${key}: ${prop} shows ${path}, which is ${wrong.what} and not a value; a prop that shows a value takes a scalar path, and ${wrong.instead}`
|
|
1163
|
+
);
|
|
1164
|
+
};
|
|
1165
|
+
const checkList = (prop, path, items) => {
|
|
1166
|
+
if (!isUnder(root, path)) return;
|
|
1167
|
+
const field = fieldAt(path);
|
|
1168
|
+
if (!field || field.kind === "unknown") return;
|
|
1169
|
+
if (field.kind !== "list") {
|
|
1170
|
+
const what = hasOwnProp(NOT_A_VALUE, field.kind) ? NOT_A_VALUE[field.kind].what : "a value";
|
|
1171
|
+
problems.push(
|
|
1172
|
+
`${key}: ${prop} takes a list, and ${path} is ${what}; a prop that takes a list reads a list path`
|
|
1173
|
+
);
|
|
1174
|
+
return;
|
|
1175
|
+
}
|
|
1176
|
+
if (items !== "values") return;
|
|
1177
|
+
const of = hasOwnProp(NOT_VALUES, field.item.kind) ? NOT_VALUES[field.item.kind] : void 0;
|
|
1178
|
+
if (!of) return;
|
|
1179
|
+
problems.push(
|
|
1180
|
+
`${key}: ${prop} takes a list of values, and ${path} is a list of ${of}; a list of ${of} is laid out as a repeat or a DataTable`
|
|
1181
|
+
);
|
|
1182
|
+
};
|
|
1183
|
+
const checkShares = (path) => {
|
|
1184
|
+
if (element.type !== "ProportionBar" || !isUnder(root, path)) return;
|
|
1185
|
+
const field = fieldAt(path);
|
|
1186
|
+
if (field?.kind !== "list") return;
|
|
1187
|
+
if (field.item.kind !== "object") {
|
|
1188
|
+
problems.push(
|
|
1189
|
+
`${key}: ProportionBar reads ${path}, a list of ${field.item.kind} values; its parts are structures, each with a label member and a number member`
|
|
1190
|
+
);
|
|
1191
|
+
return;
|
|
1192
|
+
}
|
|
1193
|
+
const members = field.item.fields;
|
|
1194
|
+
const { labelKey, valueKey } = element.props ?? {};
|
|
1195
|
+
const member = (name) => typeof name === "string" ? members.find((m) => m.name === name) : void 0;
|
|
1196
|
+
if (!member(labelKey)) {
|
|
1197
|
+
problems.push(
|
|
1198
|
+
`${key}: ProportionBar's labelKey ${JSON.stringify(labelKey)} is no member of ${path}'s items`
|
|
1199
|
+
);
|
|
1200
|
+
}
|
|
1201
|
+
const value = member(valueKey);
|
|
1202
|
+
if (!value) {
|
|
1203
|
+
problems.push(
|
|
1204
|
+
`${key}: ProportionBar's valueKey ${JSON.stringify(valueKey)} is no member of ${path}'s items`
|
|
1205
|
+
);
|
|
1206
|
+
} else if (value.kind !== "number") {
|
|
1207
|
+
problems.push(
|
|
1208
|
+
`${key}: ProportionBar's valueKey ${JSON.stringify(valueKey)} holds a ${value.kind}, not a number`
|
|
1209
|
+
);
|
|
1210
|
+
}
|
|
1211
|
+
};
|
|
1212
|
+
const walk = (prop, value) => {
|
|
1213
|
+
if (Array.isArray(value)) {
|
|
1214
|
+
value.forEach((entry) => walk(prop, entry));
|
|
1215
|
+
return;
|
|
1216
|
+
}
|
|
1217
|
+
if (typeof value !== "object" || value === null) return;
|
|
1218
|
+
const record = value;
|
|
1219
|
+
if (typeof record.$state === "string") check(prop, record.$state);
|
|
1220
|
+
if (typeof record.$item === "string") {
|
|
1221
|
+
const path = itemPath(record.$item);
|
|
1222
|
+
if (path !== void 0) check(prop, path);
|
|
1223
|
+
}
|
|
1224
|
+
if (typeof record.$template === "string") {
|
|
1225
|
+
for (const path of interpolatedPaths(record.$template, itemPath)) check(prop, path);
|
|
1226
|
+
}
|
|
1227
|
+
for (const [name, entry] of Object.entries(record)) {
|
|
1228
|
+
if (name !== "$cond") walk(prop, entry);
|
|
1229
|
+
}
|
|
1230
|
+
};
|
|
1231
|
+
for (const [prop, value] of Object.entries(element.props ?? {})) {
|
|
1232
|
+
const items = listy?.get(prop);
|
|
1233
|
+
if (items === void 0 || Array.isArray(value)) {
|
|
1234
|
+
walk(prop, value);
|
|
1235
|
+
continue;
|
|
1236
|
+
}
|
|
1237
|
+
if (typeof value !== "object" || value === null) continue;
|
|
1238
|
+
const record = value;
|
|
1239
|
+
const listPath = typeof record.$state === "string" ? record.$state : typeof record.$item === "string" ? itemPath(record.$item) : void 0;
|
|
1240
|
+
if (listPath !== void 0) {
|
|
1241
|
+
checkList(prop, listPath, items);
|
|
1242
|
+
if (prop === "items") checkShares(listPath);
|
|
949
1243
|
}
|
|
950
1244
|
}
|
|
951
1245
|
}
|
|
1246
|
+
return problems;
|
|
952
1247
|
}
|
|
953
|
-
function
|
|
954
|
-
const
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
description: subject.description,
|
|
960
|
-
name: subject.name,
|
|
961
|
-
paths,
|
|
962
|
-
run_control: RUN_COMPONENT
|
|
963
|
-
};
|
|
964
|
-
}
|
|
965
|
-
function resultBrief(subject, field, state) {
|
|
966
|
-
const paths = [];
|
|
967
|
-
if (field.kind === "object" && !isDelegatedResult(field)) {
|
|
968
|
-
paths.push({
|
|
969
|
-
depth: 0,
|
|
970
|
-
path: RESULT_ROOT,
|
|
971
|
-
kind: kindLabel(field),
|
|
972
|
-
description: field.description,
|
|
973
|
-
delegated: false
|
|
974
|
-
});
|
|
975
|
-
for (const child of field.fields) {
|
|
976
|
-
describe(child, joinPath(RESULT_ROOT, child.name), 1, "result", paths);
|
|
1248
|
+
function boundProblems(bound, inputs) {
|
|
1249
|
+
const problems = [];
|
|
1250
|
+
const underInputs = bound.filter((path) => isUnder(INPUTS_ROOT, path));
|
|
1251
|
+
if (!inputs) {
|
|
1252
|
+
if (underInputs.length > 0) {
|
|
1253
|
+
problems.push(`a result page binds ${underInputs.join(", ")}; a result page writes nothing`);
|
|
977
1254
|
}
|
|
978
1255
|
} else {
|
|
979
|
-
|
|
1256
|
+
for (const path of underInputs) {
|
|
1257
|
+
if (!inputFieldAtPath(inputs, path)) {
|
|
1258
|
+
problems.push(`${path} is bound, and no input has it`);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
980
1261
|
}
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1262
|
+
for (const path of bound) {
|
|
1263
|
+
if (isUnder(RESULT_ROOT, path)) {
|
|
1264
|
+
problems.push(
|
|
1265
|
+
`${path} is bound; a layout may not write into ${RESULT_ROOT}, which the run fills`
|
|
1266
|
+
);
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
return problems;
|
|
1270
|
+
}
|
|
1271
|
+
function repeatPaths(spec) {
|
|
1272
|
+
const found = [];
|
|
1273
|
+
for (const element of Object.values(spec.elements)) {
|
|
1274
|
+
const statePath = element.repeat?.statePath;
|
|
1275
|
+
if (typeof statePath === "string") found.push(statePath);
|
|
1276
|
+
}
|
|
1277
|
+
return found;
|
|
1278
|
+
}
|
|
1279
|
+
function isOffered(path, offered) {
|
|
1280
|
+
if (offered.bound.has(path) || offered.repeated.has(path)) return true;
|
|
1281
|
+
return offered.delegated.some((at) => path === at || path.startsWith(`${at}/`));
|
|
1282
|
+
}
|
|
1283
|
+
function uncoveredUnder(field, path, offered) {
|
|
1284
|
+
if (isOffered(path, offered)) return [];
|
|
1285
|
+
if (field.kind === "object") {
|
|
1286
|
+
return field.fields.filter((child) => child.required).flatMap((child) => uncoveredUnder(child, joinPath(path, child.name), offered));
|
|
1287
|
+
}
|
|
1288
|
+
return [path];
|
|
1289
|
+
}
|
|
1290
|
+
function layoutProblems(descriptor, spec) {
|
|
1291
|
+
try {
|
|
1292
|
+
return collectLayoutProblems(descriptor, spec);
|
|
1293
|
+
} catch (error) {
|
|
1294
|
+
return [`the layout is not a well-formed spec: ${String(error)}`];
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
function collectLayoutProblems(descriptor, spec) {
|
|
1298
|
+
const problems = [];
|
|
1299
|
+
const delegated = [];
|
|
1300
|
+
const parents = parentMapOf(spec);
|
|
1301
|
+
for (const [key, element] of Object.entries(spec.elements)) {
|
|
1302
|
+
const written = element.props?.path;
|
|
1303
|
+
const path = typeof written === "string" ? absoluteHatchPath(spec, key, written, parents) : void 0;
|
|
1304
|
+
if (element.type === "MthdsField") {
|
|
1305
|
+
if (!path || !inputFieldAtPath(descriptor.inputs ?? [], path)) {
|
|
1306
|
+
problems.push(`${key}: MthdsField delegates ${String(written)}, which no input has`);
|
|
1307
|
+
} else {
|
|
1308
|
+
delegated.push(path);
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
if (element.type === "MthdsResult") {
|
|
1312
|
+
if (!path || !descriptor.result || !resultFieldAtPath(descriptor.result, path)) {
|
|
1313
|
+
problems.push(`${key}: MthdsResult delegates ${String(written)}, which no result has`);
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
const [onlyKey] = element.children?.length === 1 ? element.children : [];
|
|
1317
|
+
const only = onlyKey === void 0 ? void 0 : spec.elements[onlyKey];
|
|
1318
|
+
if (element.type === "Grid" && element.repeat === void 0 && only?.repeat !== void 0) {
|
|
1319
|
+
problems.push(
|
|
1320
|
+
`${key}: Grid's only child ${onlyKey} carries the repeat, so every item lands in one cell; put the repeat on ${key} itself, with the item's element as its child`
|
|
1321
|
+
);
|
|
1322
|
+
}
|
|
1323
|
+
if (element.type === "Picture") {
|
|
1324
|
+
const shown = written === "" ? repeatBasePathOf(spec, key, parents) : path ?? void 0;
|
|
1325
|
+
const field = shown && descriptor.result ? resultFieldAtPath(descriptor.result, shown) : void 0;
|
|
1326
|
+
if (!field) {
|
|
1327
|
+
problems.push(`${key}: Picture shows ${JSON.stringify(written)}, which no result has`);
|
|
1328
|
+
} else if (field.kind !== "image") {
|
|
1329
|
+
problems.push(`${key}: Picture shows ${shown}, which holds a ${field.kind}, not an image`);
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
const { bound, read, adrift } = mentionedPaths(spec, parents);
|
|
1334
|
+
for (const key of new Set(adrift)) {
|
|
1335
|
+
problems.push(`${key}: reads the current item, and no repeat above it has one`);
|
|
1336
|
+
}
|
|
1337
|
+
problems.push(...boundProblems(bound, descriptor.inputs));
|
|
1338
|
+
if (!descriptor.inputs) {
|
|
1339
|
+
const result = descriptor.result;
|
|
1340
|
+
const fieldAt2 = (path) => result ? resultFieldAtPath(result, path) : void 0;
|
|
1341
|
+
const resolves2 = (path) => fieldAt2(path) !== void 0;
|
|
1342
|
+
problems.push(...staleRepeats(spec, parents, RESULT_ROOT, resolves2, "result"));
|
|
1343
|
+
for (const path of staleReads(read, RESULT_ROOT, resolves2)) {
|
|
1344
|
+
problems.push(`${path} is read, and no result has it`);
|
|
1345
|
+
}
|
|
1346
|
+
problems.push(...nonScalarReads(spec, parents, RESULT_ROOT, fieldAt2));
|
|
1347
|
+
return problems;
|
|
1348
|
+
}
|
|
1349
|
+
const inputs = descriptor.inputs;
|
|
1350
|
+
const fieldAt = (path) => inputFieldAtPath(inputs, path);
|
|
1351
|
+
const resolves = (path) => fieldAt(path) !== void 0;
|
|
1352
|
+
problems.push(...staleRepeats(spec, parents, INPUTS_ROOT, resolves, "input"));
|
|
1353
|
+
for (const path of staleReads(read, INPUTS_ROOT, resolves)) {
|
|
1354
|
+
problems.push(`${path} is read, and no input has it`);
|
|
1355
|
+
}
|
|
1356
|
+
problems.push(...nonScalarReads(spec, parents, INPUTS_ROOT, fieldAt));
|
|
1357
|
+
const offered = {
|
|
1358
|
+
bound: new Set(bound),
|
|
1359
|
+
repeated: new Set(repeatPaths(spec)),
|
|
1360
|
+
delegated
|
|
987
1361
|
};
|
|
1362
|
+
for (const field of inputs) {
|
|
1363
|
+
if (!field.required) continue;
|
|
1364
|
+
for (const path of uncoveredUnder(field, joinPath(INPUTS_ROOT, field.name), offered)) {
|
|
1365
|
+
problems.push(`${path} is required, and the layout offers nowhere to enter it`);
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
return problems;
|
|
1369
|
+
}
|
|
1370
|
+
function layoutFits(descriptor, spec) {
|
|
1371
|
+
return layoutProblems(descriptor, spec).length === 0;
|
|
988
1372
|
}
|
|
989
1373
|
var EXPRESSION_KEYS = [
|
|
990
1374
|
"$state",
|
|
@@ -1000,6 +1384,14 @@ var HATCHES = /* @__PURE__ */ new Set(["MthdsField", "MthdsResult"]);
|
|
|
1000
1384
|
function isExpression(value) {
|
|
1001
1385
|
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.keys(value).some((key) => EXPRESSION_KEYS.includes(key));
|
|
1002
1386
|
}
|
|
1387
|
+
function valueAt(value, path) {
|
|
1388
|
+
let at = value;
|
|
1389
|
+
for (const step of path) {
|
|
1390
|
+
if (typeof at !== "object" || at === null) return void 0;
|
|
1391
|
+
at = at[step];
|
|
1392
|
+
}
|
|
1393
|
+
return at;
|
|
1394
|
+
}
|
|
1003
1395
|
function isClosedVocabulary(schema) {
|
|
1004
1396
|
let current = schema;
|
|
1005
1397
|
for (let depth = 0; depth < 8; depth += 1) {
|
|
@@ -1066,7 +1458,7 @@ function deepestChain(spec) {
|
|
|
1066
1458
|
}
|
|
1067
1459
|
return deepest;
|
|
1068
1460
|
}
|
|
1069
|
-
function validateAgainstCatalog(spec, catalog2 =
|
|
1461
|
+
function validateAgainstCatalog(spec, catalog2 = frameCatalog("page")) {
|
|
1070
1462
|
try {
|
|
1071
1463
|
return checkAgainstCatalog(spec, catalog2);
|
|
1072
1464
|
} catch (error) {
|
|
@@ -1153,10 +1545,13 @@ function checkAgainstCatalog(spec, catalog2) {
|
|
|
1153
1545
|
continue;
|
|
1154
1546
|
}
|
|
1155
1547
|
const parsed = propSchema.safeParse(value);
|
|
1156
|
-
|
|
1548
|
+
const issues = parsed.success ? [] : parsed.error.issues.filter(
|
|
1549
|
+
(issue) => !issue.path.some((_, n) => isExpression(valueAt(value, issue.path.slice(0, n + 1))))
|
|
1550
|
+
);
|
|
1551
|
+
if (issues.length > 0) {
|
|
1157
1552
|
problems.push({
|
|
1158
1553
|
elementKey: key,
|
|
1159
|
-
message: `${element.type}.${name}: ${
|
|
1554
|
+
message: `${element.type}.${name}: ${issues.map((issue) => issue.message).join("; ")}`
|
|
1160
1555
|
});
|
|
1161
1556
|
}
|
|
1162
1557
|
}
|
|
@@ -1195,7 +1590,7 @@ function checkAgainstCatalog(spec, catalog2) {
|
|
|
1195
1590
|
});
|
|
1196
1591
|
}
|
|
1197
1592
|
}
|
|
1198
|
-
const
|
|
1593
|
+
const present3 = (value) => value !== void 0 && value !== null && value !== "";
|
|
1199
1594
|
const levels = [];
|
|
1200
1595
|
const onlyOnce = /* @__PURE__ */ new Map();
|
|
1201
1596
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -1212,7 +1607,7 @@ function checkAgainstCatalog(spec, catalog2) {
|
|
|
1212
1607
|
if (match) levels.push({ key, type: "Heading", level: Number(match[1]) });
|
|
1213
1608
|
} else if (rendering?.heading) {
|
|
1214
1609
|
const rendered = rendering.heading;
|
|
1215
|
-
const has = rendered.when === void 0 ||
|
|
1610
|
+
const has = rendered.when === void 0 || present3(props[rendered.when]);
|
|
1216
1611
|
if (has) levels.push({ key, type: element.type, level: rendered.level });
|
|
1217
1612
|
}
|
|
1218
1613
|
if (rendering?.once !== void 0) {
|
|
@@ -1409,306 +1804,224 @@ function formatProblems(problems) {
|
|
|
1409
1804
|
).join("\n");
|
|
1410
1805
|
}
|
|
1411
1806
|
|
|
1412
|
-
// src/generative/
|
|
1413
|
-
function
|
|
1414
|
-
return
|
|
1415
|
-
}
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
return [itemPath(raw) ?? `/${raw}`];
|
|
1807
|
+
// src/generative/designer-run.ts
|
|
1808
|
+
function seedLine(seed) {
|
|
1809
|
+
return `CREATIVE SEED (derive your direction from it; never reveal it): ${seed}`;
|
|
1810
|
+
}
|
|
1811
|
+
var REPAIR_ATTEMPTS = 2;
|
|
1812
|
+
function layoutCheckProblems(spec, { frame, descriptor }) {
|
|
1813
|
+
const verdict = validateAgainstCatalog(spec, frameCatalog(frame));
|
|
1814
|
+
const invalid = verdict.ok ? [] : formatProblems(verdict.problems).split("\n");
|
|
1815
|
+
const runless = frame !== "result" && descriptor.inputs && !bindsRun(spec) ? ["the layout has no control that runs the method: bind `run` under a control's `on`"] : [];
|
|
1816
|
+
return [...invalid, ...runless, ...layoutProblems(descriptor, spec)];
|
|
1817
|
+
}
|
|
1818
|
+
function bindsRun(spec) {
|
|
1819
|
+
const isRun = (binding) => typeof binding === "object" && binding !== null && binding.action === "run";
|
|
1820
|
+
const elements = spec.elements;
|
|
1821
|
+
if (typeof elements !== "object" || elements === null) return false;
|
|
1822
|
+
return Object.values(elements).some((element) => {
|
|
1823
|
+
if (typeof element !== "object" || element === null) return false;
|
|
1824
|
+
const on = element.on;
|
|
1825
|
+
if (typeof on !== "object" || on === null) return false;
|
|
1826
|
+
return Object.values(on).some(
|
|
1827
|
+
(binding) => Array.isArray(binding) ? binding.some(isRun) : isRun(binding)
|
|
1828
|
+
);
|
|
1435
1829
|
});
|
|
1436
1830
|
}
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
return;
|
|
1445
|
-
}
|
|
1446
|
-
if (typeof value !== "object" || value === null) return;
|
|
1447
|
-
const record = value;
|
|
1448
|
-
if (typeof record.$bindState === "string") found.bound.push(record.$bindState);
|
|
1449
|
-
if (typeof record.$state === "string") found.read.push(record.$state);
|
|
1450
|
-
if (typeof record.$template === "string") {
|
|
1451
|
-
found.read.push(...interpolatedPaths(record.$template, itemPath));
|
|
1452
|
-
}
|
|
1453
|
-
if (typeof record.$bindItem === "string") {
|
|
1454
|
-
const path = itemPath(record.$bindItem);
|
|
1455
|
-
if (path === void 0) found.adrift.push(key);
|
|
1456
|
-
else found.bound.push(path);
|
|
1457
|
-
}
|
|
1458
|
-
if (typeof record.$item === "string") {
|
|
1459
|
-
const path = itemPath(record.$item);
|
|
1460
|
-
if (path === void 0) found.adrift.push(key);
|
|
1461
|
-
else found.read.push(path);
|
|
1462
|
-
}
|
|
1463
|
-
Object.values(record).forEach(walk);
|
|
1464
|
-
};
|
|
1465
|
-
walk(element.props);
|
|
1466
|
-
walk(element.visible);
|
|
1467
|
-
}
|
|
1468
|
-
return found;
|
|
1831
|
+
|
|
1832
|
+
// src/generative/brief.ts
|
|
1833
|
+
var DESIGNER_BRIEF_CONCEPT = "generative.Brief";
|
|
1834
|
+
var RUN_COMPONENT = "Cta";
|
|
1835
|
+
var COMPOSER_RUN_COMPONENT = "Composer";
|
|
1836
|
+
function isDelegatedInput(field) {
|
|
1837
|
+
return field.kind === "document" || field.kind === "image" || field.kind === "date" || field.kind === "list" || field.kind === "unknown" || field.kind === "enum" && field.options.includes("");
|
|
1469
1838
|
}
|
|
1470
|
-
function
|
|
1471
|
-
|
|
1472
|
-
|
|
1839
|
+
function isDelegatedResult(field, frame = "page") {
|
|
1840
|
+
if (isNativeValueNode(field)) return true;
|
|
1841
|
+
if (frame === "result" && (field.kind === "image" || field.kind === "date" && !field.datetime))
|
|
1842
|
+
return false;
|
|
1843
|
+
if (field.kind === "list" && isNativeValueNode(field.item)) return true;
|
|
1844
|
+
return field.kind === "document" || field.kind === "image" || field.kind === "date" || field.kind === "prose" || field.kind === "unknown";
|
|
1473
1845
|
}
|
|
1474
|
-
function
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1846
|
+
function kindLabel(field) {
|
|
1847
|
+
if (isNativeHtmlNode(field)) return "markup (native.Html)";
|
|
1848
|
+
if (isNativeDateNode(field)) return "date (native.Date)";
|
|
1849
|
+
if (isNativeCompositeNode(field)) return "composite (native.Composite)";
|
|
1850
|
+
switch (field.kind) {
|
|
1851
|
+
case "text":
|
|
1852
|
+
return "text";
|
|
1853
|
+
case "prose":
|
|
1854
|
+
return "prose (markdown)";
|
|
1855
|
+
case "number":
|
|
1856
|
+
return field.integer ? "integer" : "number";
|
|
1857
|
+
case "boolean":
|
|
1858
|
+
return "boolean";
|
|
1859
|
+
case "enum":
|
|
1860
|
+
return `choice of ${field.options.map((option) => JSON.stringify(option)).join(" | ")}`;
|
|
1861
|
+
case "date":
|
|
1862
|
+
return field.datetime ? "date with time" : "date";
|
|
1863
|
+
case "document":
|
|
1864
|
+
return "document (a file)";
|
|
1865
|
+
case "image":
|
|
1866
|
+
return "image (a file)";
|
|
1867
|
+
case "object":
|
|
1868
|
+
return `structure${field.conceptRef ? ` ${field.conceptRef}` : ""}`;
|
|
1869
|
+
case "list":
|
|
1870
|
+
return `list of ${kindLabel(field.item)}`;
|
|
1871
|
+
case "unknown":
|
|
1872
|
+
return "unknown";
|
|
1873
|
+
default:
|
|
1874
|
+
return field;
|
|
1483
1875
|
}
|
|
1484
|
-
return problems;
|
|
1485
1876
|
}
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
};
|
|
1492
|
-
var NOT_VALUES = {
|
|
1493
|
-
object: "structures",
|
|
1494
|
-
list: "lists",
|
|
1495
|
-
document: "files",
|
|
1496
|
-
image: "files"
|
|
1497
|
-
};
|
|
1498
|
-
var listPropsCache;
|
|
1499
|
-
function listProps() {
|
|
1500
|
-
if (listPropsCache) return listPropsCache;
|
|
1501
|
-
const found = /* @__PURE__ */ new Map([
|
|
1502
|
-
["DataTable", /* @__PURE__ */ new Map([["rows", "anything"]])]
|
|
1503
|
-
]);
|
|
1504
|
-
const components3 = catalog.data.components;
|
|
1505
|
-
for (const [type, definition] of Object.entries(components3)) {
|
|
1506
|
-
const shape = definition.props?.shape;
|
|
1507
|
-
for (const [prop, schema] of Object.entries(shape ?? {})) {
|
|
1508
|
-
const items = listItemsOf(schema);
|
|
1509
|
-
if (items === void 0) continue;
|
|
1510
|
-
if (!found.has(type)) found.set(type, /* @__PURE__ */ new Map());
|
|
1511
|
-
found.get(type).set(prop, items);
|
|
1512
|
-
}
|
|
1877
|
+
function constraints(field) {
|
|
1878
|
+
const notes = [];
|
|
1879
|
+
if (field.kind === "number") {
|
|
1880
|
+
if (field.min !== void 0) notes.push(`min ${field.min}`);
|
|
1881
|
+
if (field.max !== void 0) notes.push(`max ${field.max}`);
|
|
1513
1882
|
}
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
}
|
|
1517
|
-
|
|
1518
|
-
function unwrapped(schema) {
|
|
1519
|
-
let current = schema;
|
|
1520
|
-
for (let depth = 0; depth < 8; depth += 1) {
|
|
1521
|
-
const def = current.def;
|
|
1522
|
-
if (!def) return void 0;
|
|
1523
|
-
if (def.innerType === void 0) return def;
|
|
1524
|
-
current = def.innerType;
|
|
1883
|
+
if (field.kind === "text" || field.kind === "prose") {
|
|
1884
|
+
if (field.minLength !== void 0) notes.push(`at least ${field.minLength} characters`);
|
|
1885
|
+
if (field.maxLength !== void 0) notes.push(`at most ${field.maxLength} characters`);
|
|
1886
|
+
if (field.format) notes.push(`format ${field.format}`);
|
|
1525
1887
|
}
|
|
1526
|
-
|
|
1888
|
+
if (field.kind === "list") {
|
|
1889
|
+
if (field.itemCount !== void 0) notes.push(`at least ${field.itemCount} items`);
|
|
1890
|
+
if (field.maxItemCount !== void 0) notes.push(`at most ${field.maxItemCount} items`);
|
|
1891
|
+
}
|
|
1892
|
+
if (field.defaultValue !== void 0) notes.push(`default ${JSON.stringify(field.defaultValue)}`);
|
|
1893
|
+
if (field.examples && field.examples.length > 0) {
|
|
1894
|
+
notes.push(`examples ${field.examples.map((example) => JSON.stringify(example)).join(", ")}`);
|
|
1895
|
+
}
|
|
1896
|
+
if (field.hints && Object.keys(field.hints).length > 0) {
|
|
1897
|
+
notes.push(
|
|
1898
|
+
`hints ${Object.entries(field.hints).map(([key, value]) => `${key}=${value}`).join(", ")}`
|
|
1899
|
+
);
|
|
1900
|
+
}
|
|
1901
|
+
return notes;
|
|
1527
1902
|
}
|
|
1528
|
-
function
|
|
1529
|
-
const
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1903
|
+
function entryOf(field, path, depth, side, relative, seeded, frame = "page") {
|
|
1904
|
+
const notes = constraints(field);
|
|
1905
|
+
return {
|
|
1906
|
+
depth,
|
|
1907
|
+
path,
|
|
1908
|
+
kind: kindLabel(field),
|
|
1909
|
+
name: field.name,
|
|
1910
|
+
title: field.title && field.title !== field.name ? field.title : void 0,
|
|
1911
|
+
description: field.description,
|
|
1912
|
+
required: side === "input" ? field.required : void 0,
|
|
1913
|
+
gating: side === "input" && field.gating ? true : void 0,
|
|
1914
|
+
notes: notes.length > 0 ? notes : void 0,
|
|
1915
|
+
default: seeded || field.defaultValue === void 0 ? void 0 : JSON.stringify(field.defaultValue),
|
|
1916
|
+
delegated: side === "input" ? isDelegatedInput(field) : isDelegatedResult(field, frame),
|
|
1917
|
+
relative: relative ? true : void 0
|
|
1918
|
+
};
|
|
1533
1919
|
}
|
|
1534
|
-
function
|
|
1535
|
-
const
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
const
|
|
1540
|
-
const
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
const field = fieldAt(path);
|
|
1553
|
-
if (!field || field.kind === "unknown") return;
|
|
1554
|
-
if (field.kind !== "list") {
|
|
1555
|
-
const what = hasOwnProp(NOT_A_VALUE, field.kind) ? NOT_A_VALUE[field.kind].what : "a value";
|
|
1556
|
-
problems.push(
|
|
1557
|
-
`${key}: ${prop} takes a list, and ${path} is ${what}; a prop that takes a list reads a list path`
|
|
1558
|
-
);
|
|
1559
|
-
return;
|
|
1560
|
-
}
|
|
1561
|
-
if (items !== "values") return;
|
|
1562
|
-
const of = hasOwnProp(NOT_VALUES, field.item.kind) ? NOT_VALUES[field.item.kind] : void 0;
|
|
1563
|
-
if (!of) return;
|
|
1564
|
-
problems.push(
|
|
1565
|
-
`${key}: ${prop} takes a list of values, and ${path} is a list of ${of}; a list of ${of} is laid out as a repeat or a DataTable`
|
|
1566
|
-
);
|
|
1567
|
-
};
|
|
1568
|
-
const walk = (prop, value) => {
|
|
1569
|
-
if (Array.isArray(value)) {
|
|
1570
|
-
value.forEach((entry) => walk(prop, entry));
|
|
1571
|
-
return;
|
|
1572
|
-
}
|
|
1573
|
-
if (typeof value !== "object" || value === null) return;
|
|
1574
|
-
const record = value;
|
|
1575
|
-
if (typeof record.$state === "string") check(prop, record.$state);
|
|
1576
|
-
if (typeof record.$item === "string") {
|
|
1577
|
-
const path = itemPath(record.$item);
|
|
1578
|
-
if (path !== void 0) check(prop, path);
|
|
1579
|
-
}
|
|
1580
|
-
if (typeof record.$template === "string") {
|
|
1581
|
-
for (const path of interpolatedPaths(record.$template, itemPath)) check(prop, path);
|
|
1582
|
-
}
|
|
1583
|
-
for (const [name, entry] of Object.entries(record)) {
|
|
1584
|
-
if (name !== "$cond") walk(prop, entry);
|
|
1585
|
-
}
|
|
1586
|
-
};
|
|
1587
|
-
for (const [prop, value] of Object.entries(element.props ?? {})) {
|
|
1588
|
-
const items = listy?.get(prop);
|
|
1589
|
-
if (items === void 0 || Array.isArray(value)) {
|
|
1590
|
-
walk(prop, value);
|
|
1591
|
-
continue;
|
|
1592
|
-
}
|
|
1593
|
-
if (typeof value !== "object" || value === null) continue;
|
|
1594
|
-
const record = value;
|
|
1595
|
-
if (typeof record.$state === "string") checkList(prop, record.$state, items);
|
|
1596
|
-
if (typeof record.$item === "string") {
|
|
1597
|
-
const path = itemPath(record.$item);
|
|
1598
|
-
if (path !== void 0) checkList(prop, path, items);
|
|
1920
|
+
function describe(field, path, depth, side, entries, seeded = false, frame = "page") {
|
|
1921
|
+
const entry = entryOf(field, path, depth, side, false, seeded, frame);
|
|
1922
|
+
entries.push(entry);
|
|
1923
|
+
if (entry.delegated) return;
|
|
1924
|
+
if (field.kind === "object") {
|
|
1925
|
+
const seededBelow = seeded || field.defaultValue !== void 0 || side === "input" && !field.required;
|
|
1926
|
+
for (const child of field.fields) {
|
|
1927
|
+
describe(child, joinPath(path, child.name), depth + 1, side, entries, seededBelow, frame);
|
|
1928
|
+
}
|
|
1929
|
+
}
|
|
1930
|
+
if (field.kind === "list" && side === "result") {
|
|
1931
|
+
const item = field.item;
|
|
1932
|
+
entry.item_kind = kindLabel(item);
|
|
1933
|
+
entry.item_description = item.description;
|
|
1934
|
+
if (item.kind === "object" && !isDelegatedResult(item, frame)) {
|
|
1935
|
+
entry.item_laid_out = true;
|
|
1936
|
+
for (const child of item.fields) {
|
|
1937
|
+
describeRelative(child, child.name, depth + 2, entries, side, frame);
|
|
1599
1938
|
}
|
|
1600
1939
|
}
|
|
1601
1940
|
}
|
|
1602
|
-
return problems;
|
|
1603
1941
|
}
|
|
1604
|
-
function
|
|
1605
|
-
const
|
|
1606
|
-
|
|
1607
|
-
if (
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
} else {
|
|
1612
|
-
for (const path of underInputs) {
|
|
1613
|
-
if (!inputFieldAtPath(inputs, path)) {
|
|
1614
|
-
problems.push(`${path} is bound, and no input has it`);
|
|
1615
|
-
}
|
|
1942
|
+
function describeRelative(field, relativePath, depth, entries, side = "result", frame = "page") {
|
|
1943
|
+
const entry = entryOf(field, relativePath, depth, side, true, false, frame);
|
|
1944
|
+
entries.push(entry);
|
|
1945
|
+
if (entry.delegated) return;
|
|
1946
|
+
if (field.kind === "object") {
|
|
1947
|
+
for (const child of field.fields) {
|
|
1948
|
+
describeRelative(child, joinPath(relativePath, child.name), depth + 1, entries, side, frame);
|
|
1616
1949
|
}
|
|
1617
1950
|
}
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1951
|
+
if (field.kind === "list" && side === "result") {
|
|
1952
|
+
const item = field.item;
|
|
1953
|
+
entry.item_kind = kindLabel(item);
|
|
1954
|
+
entry.item_description = item.description;
|
|
1955
|
+
if (item.kind === "object" && !isDelegatedResult(item, frame)) {
|
|
1956
|
+
entry.item_laid_out = true;
|
|
1957
|
+
for (const child of item.fields) {
|
|
1958
|
+
describeRelative(
|
|
1959
|
+
child,
|
|
1960
|
+
joinPath(relativePath, "<i>", child.name),
|
|
1961
|
+
depth + 2,
|
|
1962
|
+
entries,
|
|
1963
|
+
side,
|
|
1964
|
+
frame
|
|
1965
|
+
);
|
|
1966
|
+
}
|
|
1623
1967
|
}
|
|
1624
1968
|
}
|
|
1625
|
-
return problems;
|
|
1626
|
-
}
|
|
1627
|
-
function repeatPaths(spec) {
|
|
1628
|
-
const found = [];
|
|
1629
|
-
for (const element of Object.values(spec.elements)) {
|
|
1630
|
-
const statePath = element.repeat?.statePath;
|
|
1631
|
-
if (typeof statePath === "string") found.push(statePath);
|
|
1632
|
-
}
|
|
1633
|
-
return found;
|
|
1634
1969
|
}
|
|
1635
|
-
function
|
|
1636
|
-
|
|
1637
|
-
|
|
1970
|
+
function returnsOf(result) {
|
|
1971
|
+
const shape = result.kind === "list" ? result.item : result;
|
|
1972
|
+
const members = shape.kind === "object" ? shape.fields : [shape];
|
|
1973
|
+
return members.map((member) => {
|
|
1974
|
+
const title = member.title ?? member.name.replace(/_/g, " ");
|
|
1975
|
+
return member.description && member.description !== title ? `${title}: ${member.description}` : title;
|
|
1976
|
+
});
|
|
1638
1977
|
}
|
|
1639
|
-
function
|
|
1640
|
-
if (
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
}
|
|
1644
|
-
return [path];
|
|
1978
|
+
function styleOf(style) {
|
|
1979
|
+
if (!style) return void 0;
|
|
1980
|
+
const { name, direction } = APP_STYLES[style];
|
|
1981
|
+
return { name, direction };
|
|
1645
1982
|
}
|
|
1646
|
-
function
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
return [`the layout is not a well-formed spec: ${String(error)}`];
|
|
1983
|
+
function inputBrief(subject, fields, { frame = "page", style, result } = {}) {
|
|
1984
|
+
const paths = [];
|
|
1985
|
+
for (const field of fields) {
|
|
1986
|
+
describe(field, joinPath(INPUTS_ROOT, field.name), 0, "input", paths, false, frame);
|
|
1651
1987
|
}
|
|
1988
|
+
return {
|
|
1989
|
+
side: "input",
|
|
1990
|
+
frame,
|
|
1991
|
+
pipe_ref: subject.pipeRef,
|
|
1992
|
+
description: subject.description,
|
|
1993
|
+
name: subject.name,
|
|
1994
|
+
paths,
|
|
1995
|
+
run_control: frame === "composer" ? COMPOSER_RUN_COMPONENT : RUN_COMPONENT,
|
|
1996
|
+
...frame === "composer" && result ? { returns: returnsOf(result) } : {},
|
|
1997
|
+
...style ? { style: styleOf(style) } : {}
|
|
1998
|
+
};
|
|
1652
1999
|
}
|
|
1653
|
-
function
|
|
1654
|
-
const
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
}
|
|
1666
|
-
}
|
|
1667
|
-
if (element.type === "MthdsResult") {
|
|
1668
|
-
if (!path || !descriptor.result || !resultFieldAtPath(descriptor.result, path)) {
|
|
1669
|
-
problems.push(`${key}: MthdsResult delegates ${String(written)}, which no result has`);
|
|
1670
|
-
}
|
|
1671
|
-
}
|
|
1672
|
-
}
|
|
1673
|
-
const { bound, read, adrift } = mentionedPaths(spec, parents);
|
|
1674
|
-
for (const key of new Set(adrift)) {
|
|
1675
|
-
problems.push(`${key}: reads the current item, and no repeat above it has one`);
|
|
1676
|
-
}
|
|
1677
|
-
problems.push(...boundProblems(bound, descriptor.inputs));
|
|
1678
|
-
if (!descriptor.inputs) {
|
|
1679
|
-
const result = descriptor.result;
|
|
1680
|
-
const fieldAt2 = (path) => result ? resultFieldAtPath(result, path) : void 0;
|
|
1681
|
-
const resolves2 = (path) => fieldAt2(path) !== void 0;
|
|
1682
|
-
problems.push(...staleRepeats(spec, parents, RESULT_ROOT, resolves2, "result"));
|
|
1683
|
-
for (const path of staleReads(read, RESULT_ROOT, resolves2)) {
|
|
1684
|
-
problems.push(`${path} is read, and no result has it`);
|
|
2000
|
+
function resultBrief(subject, field, state, { frame = "page", style } = {}) {
|
|
2001
|
+
const paths = [];
|
|
2002
|
+
if (field.kind === "object" && !isDelegatedResult(field, frame)) {
|
|
2003
|
+
paths.push({
|
|
2004
|
+
depth: 0,
|
|
2005
|
+
path: RESULT_ROOT,
|
|
2006
|
+
kind: kindLabel(field),
|
|
2007
|
+
description: field.description,
|
|
2008
|
+
delegated: false
|
|
2009
|
+
});
|
|
2010
|
+
for (const child of field.fields) {
|
|
2011
|
+
describe(child, joinPath(RESULT_ROOT, child.name), 1, "result", paths, false, frame);
|
|
1685
2012
|
}
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
}
|
|
1689
|
-
const inputs = descriptor.inputs;
|
|
1690
|
-
const fieldAt = (path) => inputFieldAtPath(inputs, path);
|
|
1691
|
-
const resolves = (path) => fieldAt(path) !== void 0;
|
|
1692
|
-
problems.push(...staleRepeats(spec, parents, INPUTS_ROOT, resolves, "input"));
|
|
1693
|
-
for (const path of staleReads(read, INPUTS_ROOT, resolves)) {
|
|
1694
|
-
problems.push(`${path} is read, and no input has it`);
|
|
2013
|
+
} else {
|
|
2014
|
+
describe(field, RESULT_ROOT, 0, "result", paths, false, frame);
|
|
1695
2015
|
}
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
2016
|
+
return {
|
|
2017
|
+
side: "result",
|
|
2018
|
+
frame,
|
|
2019
|
+
pipe_ref: subject.pipeRef,
|
|
2020
|
+
description: subject.description,
|
|
2021
|
+
paths,
|
|
2022
|
+
...style ? { style: styleOf(style) } : {},
|
|
2023
|
+
sample_state: JSON.stringify(state, null, 2)
|
|
1701
2024
|
};
|
|
1702
|
-
for (const field of inputs) {
|
|
1703
|
-
if (!field.required) continue;
|
|
1704
|
-
for (const path of uncoveredUnder(field, joinPath(INPUTS_ROOT, field.name), offered)) {
|
|
1705
|
-
problems.push(`${path} is required, and the layout offers nowhere to enter it`);
|
|
1706
|
-
}
|
|
1707
|
-
}
|
|
1708
|
-
return problems;
|
|
1709
|
-
}
|
|
1710
|
-
function layoutFits(descriptor, spec) {
|
|
1711
|
-
return layoutProblems(descriptor, spec).length === 0;
|
|
1712
2025
|
}
|
|
1713
2026
|
function specToJsonl(spec) {
|
|
1714
2027
|
const lines = [];
|
|
@@ -1764,7 +2077,7 @@ function specFromJsonl(jsonl) {
|
|
|
1764
2077
|
function jsonlLines(jsonl) {
|
|
1765
2078
|
return jsonl.split("\n").filter((line) => line.trim().length > 0);
|
|
1766
2079
|
}
|
|
1767
|
-
var BrandContext =
|
|
2080
|
+
var BrandContext = React4.createContext(null);
|
|
1768
2081
|
function BrandProvider({
|
|
1769
2082
|
manifest,
|
|
1770
2083
|
children
|
|
@@ -1773,7 +2086,7 @@ function BrandProvider({
|
|
|
1773
2086
|
return /* @__PURE__ */ jsx(BrandContext.Provider, { value: manifest, children });
|
|
1774
2087
|
}
|
|
1775
2088
|
function useBrand() {
|
|
1776
|
-
const manifest =
|
|
2089
|
+
const manifest = React4.useContext(BrandContext);
|
|
1777
2090
|
if (!manifest)
|
|
1778
2091
|
throw new Error(
|
|
1779
2092
|
"useBrand: no brand in scope. Pass `brand` to GenerativePage, or wrap the tree in BrandProvider."
|
|
@@ -1784,7 +2097,7 @@ var WEIGHTS = "400;500;600;700";
|
|
|
1784
2097
|
function useWebfont(webfont) {
|
|
1785
2098
|
const provider = webfont?.provider;
|
|
1786
2099
|
const family = webfont?.family;
|
|
1787
|
-
|
|
2100
|
+
React4.useEffect(() => {
|
|
1788
2101
|
if (!provider || !family) return;
|
|
1789
2102
|
const key = `${provider}:${family}`;
|
|
1790
2103
|
if (document.head.querySelector(`link[data-brand-webfont="${CSS.escape(key)}"]`)) return;
|
|
@@ -1804,9 +2117,19 @@ function useWebfont(webfont) {
|
|
|
1804
2117
|
document.head.appendChild(link);
|
|
1805
2118
|
}, [provider, family]);
|
|
1806
2119
|
}
|
|
2120
|
+
var FrameHostContext = React4.createContext({});
|
|
2121
|
+
function FrameHostProvider({
|
|
2122
|
+
host,
|
|
2123
|
+
children
|
|
2124
|
+
}) {
|
|
2125
|
+
return /* @__PURE__ */ jsx(FrameHostContext.Provider, { value: host, children });
|
|
2126
|
+
}
|
|
2127
|
+
function useFrameHost() {
|
|
2128
|
+
return React4.useContext(FrameHostContext);
|
|
2129
|
+
}
|
|
1807
2130
|
function useBoundField(literal, binding, empty, { checks, validateOn }) {
|
|
1808
2131
|
const [boundValue, setBoundValue] = useBoundProp(literal ?? void 0, binding);
|
|
1809
|
-
const [localValue, setLocalValue] =
|
|
2132
|
+
const [localValue, setLocalValue] = React4.useState(literal ?? empty);
|
|
1810
2133
|
const isBound = Boolean(binding);
|
|
1811
2134
|
const hasValidation = Boolean(binding && checks?.length);
|
|
1812
2135
|
const when = validateOn ?? "change";
|
|
@@ -1846,11 +2169,16 @@ function Card({
|
|
|
1846
2169
|
return (
|
|
1847
2170
|
// A style's panel: a host writes the style's field fill onto `--input`
|
|
1848
2171
|
// here, as on its own panel, so the fields inside do not sink into it.
|
|
2172
|
+
// A panel's corner is one and a half times a control's, as the rail's is.
|
|
1849
2173
|
/* @__PURE__ */ jsxs(
|
|
1850
2174
|
"div",
|
|
1851
2175
|
{
|
|
1852
2176
|
"data-style-panel": "",
|
|
1853
|
-
className: cn(
|
|
2177
|
+
className: cn(
|
|
2178
|
+
"rounded-[calc(var(--radius,0.5rem)*1.5)] p-6 text-card-foreground",
|
|
2179
|
+
panelSurfaceClass,
|
|
2180
|
+
panelFlatShadowClass
|
|
2181
|
+
),
|
|
1854
2182
|
children: [
|
|
1855
2183
|
props.title || props.description ? /* @__PURE__ */ jsxs("div", { className: "mb-4 space-y-1.5", children: [
|
|
1856
2184
|
props.title ? /* @__PURE__ */ jsx("h3", { className: cn("text-lg leading-none", headingClass(600)), children: props.title }) : null,
|
|
@@ -1940,7 +2268,16 @@ function Collapsible({
|
|
|
1940
2268
|
open: props.defaultOpen ?? false,
|
|
1941
2269
|
"data-slot": "collapsible",
|
|
1942
2270
|
children: [
|
|
1943
|
-
/* @__PURE__ */
|
|
2271
|
+
/* @__PURE__ */ jsxs("summary", { className: "flex min-h-11 cursor-pointer list-none items-center justify-between gap-3 rounded-md px-4 py-3 text-sm font-medium select-none focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset [&::-webkit-details-marker]:hidden", children: [
|
|
2272
|
+
/* @__PURE__ */ jsx("span", { children: props.title }),
|
|
2273
|
+
/* @__PURE__ */ jsx(
|
|
2274
|
+
ChevronDown,
|
|
2275
|
+
{
|
|
2276
|
+
"aria-hidden": "true",
|
|
2277
|
+
className: "size-4 shrink-0 text-muted-foreground transition-transform [details[open]>summary_&]:rotate-180"
|
|
2278
|
+
}
|
|
2279
|
+
)
|
|
2280
|
+
] }),
|
|
1944
2281
|
/* @__PURE__ */ jsx("div", { className: "border-t border-border px-4 py-3", children })
|
|
1945
2282
|
]
|
|
1946
2283
|
}
|
|
@@ -2064,7 +2401,7 @@ function Progress({
|
|
|
2064
2401
|
] });
|
|
2065
2402
|
}
|
|
2066
2403
|
function useControlId(name) {
|
|
2067
|
-
return `jr-${name}-${
|
|
2404
|
+
return `jr-${name}-${React4.useId()}`;
|
|
2068
2405
|
}
|
|
2069
2406
|
function Input({
|
|
2070
2407
|
props,
|
|
@@ -2243,9 +2580,9 @@ function Button({
|
|
|
2243
2580
|
}
|
|
2244
2581
|
);
|
|
2245
2582
|
}
|
|
2246
|
-
var DescriptorContext =
|
|
2583
|
+
var DescriptorContext = React4.createContext({});
|
|
2247
2584
|
function useDescriptorScope() {
|
|
2248
|
-
return
|
|
2585
|
+
return React4.useContext(DescriptorContext);
|
|
2249
2586
|
}
|
|
2250
2587
|
function DescriptorProvider({
|
|
2251
2588
|
scope,
|
|
@@ -2292,13 +2629,28 @@ function useAbsolutePath(path) {
|
|
|
2292
2629
|
if (path.startsWith("/")) return path;
|
|
2293
2630
|
return repeat ? `${repeat.basePath}/${path}` : void 0;
|
|
2294
2631
|
}
|
|
2295
|
-
function
|
|
2296
|
-
|
|
2632
|
+
function withoutOptionalMark(label) {
|
|
2633
|
+
return label.replace(/\s*\(optional\)\s*$/i, "") || label;
|
|
2634
|
+
}
|
|
2635
|
+
function MthdsField({
|
|
2636
|
+
props
|
|
2637
|
+
}) {
|
|
2638
|
+
const scope = React4.useContext(DescriptorContext);
|
|
2297
2639
|
const path = useAbsolutePath(props.path) ?? "";
|
|
2298
|
-
const
|
|
2640
|
+
const found = scope.inputs && path ? inputFieldAtPath(scope.inputs, path) : void 0;
|
|
2641
|
+
const field = React4.useMemo(
|
|
2642
|
+
() => found && (props.label || props.hint) ? {
|
|
2643
|
+
...found,
|
|
2644
|
+
// The control marks an optional field itself, so a label that
|
|
2645
|
+
// says "(optional)" too would say it twice.
|
|
2646
|
+
title: props.label ? withoutOptionalMark(props.label) : found.title,
|
|
2647
|
+
description: props.hint || found.description
|
|
2648
|
+
} : found,
|
|
2649
|
+
[found, props.label, props.hint]
|
|
2650
|
+
);
|
|
2299
2651
|
const value = useStateValue(path);
|
|
2300
2652
|
const { set } = useStateStore();
|
|
2301
|
-
const onChange =
|
|
2653
|
+
const onChange = React4.useCallback((next) => set(path, next), [set, path]);
|
|
2302
2654
|
if (!field) return /* @__PURE__ */ jsx(Unresolved, { path: props.path, side: "input" });
|
|
2303
2655
|
return /* @__PURE__ */ jsx(
|
|
2304
2656
|
FieldRenderer,
|
|
@@ -2312,7 +2664,7 @@ function MthdsField({ props }) {
|
|
|
2312
2664
|
);
|
|
2313
2665
|
}
|
|
2314
2666
|
function MthdsResult({ props }) {
|
|
2315
|
-
const scope =
|
|
2667
|
+
const scope = React4.useContext(DescriptorContext);
|
|
2316
2668
|
const path = useAbsolutePath(props.path) ?? "";
|
|
2317
2669
|
const field = scope.result && path ? resultFieldAtPath(scope.result, path) : void 0;
|
|
2318
2670
|
const value = useStateValue(path);
|
|
@@ -2325,7 +2677,7 @@ function AccessibleSelect({ props, bindings, emit }) {
|
|
|
2325
2677
|
props.value ?? void 0,
|
|
2326
2678
|
bindings?.value
|
|
2327
2679
|
);
|
|
2328
|
-
const [localValue, setLocalValue] =
|
|
2680
|
+
const [localValue, setLocalValue] = React4.useState("");
|
|
2329
2681
|
const isBound = Boolean(bindings?.value);
|
|
2330
2682
|
const value = isBound ? boundValue ?? "" : localValue;
|
|
2331
2683
|
const setValue = isBound ? setBoundValue : setLocalValue;
|
|
@@ -2357,7 +2709,7 @@ function AccessibleSelect({ props, bindings, emit }) {
|
|
|
2357
2709
|
errors.length > 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: errors[0] }) : null
|
|
2358
2710
|
] });
|
|
2359
2711
|
}
|
|
2360
|
-
function
|
|
2712
|
+
function valueAt2(row, relativePath) {
|
|
2361
2713
|
let current = row;
|
|
2362
2714
|
for (const segment of relativePath.split("/").filter((part) => part.length > 0)) {
|
|
2363
2715
|
if (typeof current !== "object" || current === null) return void 0;
|
|
@@ -2374,6 +2726,21 @@ function formatCell(value) {
|
|
|
2374
2726
|
if (Array.isArray(value)) return value.map(formatCell).join(", ");
|
|
2375
2727
|
return JSON.stringify(value);
|
|
2376
2728
|
}
|
|
2729
|
+
function formatColumnCell(value, format) {
|
|
2730
|
+
const written = format === "date" ? readDateContent(value)?.date : void 0;
|
|
2731
|
+
const day = written === void 0 ? null : /^\d{4}-\d{2}-\d{2}/.exec(written);
|
|
2732
|
+
if (day) {
|
|
2733
|
+
const date = /* @__PURE__ */ new Date(`${day[0]}T12:00:00Z`);
|
|
2734
|
+
if (!Number.isNaN(date.getTime()))
|
|
2735
|
+
return date.toLocaleDateString("en-GB", {
|
|
2736
|
+
day: "numeric",
|
|
2737
|
+
month: "short",
|
|
2738
|
+
year: "numeric",
|
|
2739
|
+
timeZone: "UTC"
|
|
2740
|
+
});
|
|
2741
|
+
}
|
|
2742
|
+
return formatCell(value);
|
|
2743
|
+
}
|
|
2377
2744
|
function DataTable({ props }) {
|
|
2378
2745
|
const rows = Array.isArray(props.rows) ? props.rows : [];
|
|
2379
2746
|
const columns = props.columns ?? [];
|
|
@@ -2388,7 +2755,7 @@ function DataTable({ props }) {
|
|
|
2388
2755
|
},
|
|
2389
2756
|
column.path
|
|
2390
2757
|
)) }) }),
|
|
2391
|
-
/* @__PURE__ */ jsx("tbody", { children: rows.map((row, index) => /* @__PURE__ */ jsx("tr", { className: "border-b border-border/60 last:border-b-0", children: columns.map((column) => /* @__PURE__ */ jsx("td", { className: "px-2.5 py-1.5 align-top text-foreground", children:
|
|
2758
|
+
/* @__PURE__ */ jsx("tbody", { children: rows.map((row, index) => /* @__PURE__ */ jsx("tr", { className: "border-b border-border/60 last:border-b-0", children: columns.map((column) => /* @__PURE__ */ jsx("td", { className: "px-2.5 py-1.5 align-top text-foreground", children: formatColumnCell(valueAt2(row, column.path), column.format) }, column.path)) }, index)) })
|
|
2392
2759
|
] }) });
|
|
2393
2760
|
}
|
|
2394
2761
|
function numberFormat(format) {
|
|
@@ -2440,8 +2807,8 @@ function Split({
|
|
|
2440
2807
|
}
|
|
2441
2808
|
function Tabs({ props, children }) {
|
|
2442
2809
|
const tabs = props.tabs ?? [];
|
|
2443
|
-
const panels =
|
|
2444
|
-
const [value, setValue] =
|
|
2810
|
+
const panels = React4.Children.toArray(children);
|
|
2811
|
+
const [value, setValue] = React4.useState(tabs[0]?.value ?? "");
|
|
2445
2812
|
return /* @__PURE__ */ jsxs(TabsPrimitive.Root, { value, onValueChange: setValue, className: "w-full", children: [
|
|
2446
2813
|
/* @__PURE__ */ jsx(TabsPrimitive.List, { className: "inline-flex h-10 items-center justify-start rounded-md bg-muted p-1 text-muted-foreground max-sm:h-auto max-sm:flex-wrap", children: tabs.map((tab) => /* @__PURE__ */ jsx(
|
|
2447
2814
|
TabsPrimitive.Trigger,
|
|
@@ -2471,8 +2838,8 @@ var SECONDARY_BUTTON = cn(
|
|
|
2471
2838
|
);
|
|
2472
2839
|
function Steps({ props, children }) {
|
|
2473
2840
|
const steps = props.steps ?? [];
|
|
2474
|
-
const panels =
|
|
2475
|
-
const [index, setIndex] =
|
|
2841
|
+
const panels = React4.Children.toArray(children);
|
|
2842
|
+
const [index, setIndex] = React4.useState(0);
|
|
2476
2843
|
const last = steps.length - 1;
|
|
2477
2844
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-5", children: [
|
|
2478
2845
|
/* @__PURE__ */ jsx("ol", { className: "flex flex-wrap items-center gap-x-5 gap-y-2", children: steps.map((label, position) => /* @__PURE__ */ jsxs(
|
|
@@ -2601,7 +2968,7 @@ function Segmented({ props, bindings, emit }) {
|
|
|
2601
2968
|
props.value ?? void 0,
|
|
2602
2969
|
bindings?.value
|
|
2603
2970
|
);
|
|
2604
|
-
const [localValue, setLocalValue] =
|
|
2971
|
+
const [localValue, setLocalValue] = React4.useState("");
|
|
2605
2972
|
const isBound = Boolean(bindings?.value);
|
|
2606
2973
|
const value = isBound ? boundValue ?? "" : localValue;
|
|
2607
2974
|
const setValue = isBound ? setBoundValue : setLocalValue;
|
|
@@ -2641,7 +3008,7 @@ function NumberInput({ props, bindings, emit }) {
|
|
|
2641
3008
|
props.value ?? void 0,
|
|
2642
3009
|
bindings?.value
|
|
2643
3010
|
);
|
|
2644
|
-
const [localValue, setLocalValue] =
|
|
3011
|
+
const [localValue, setLocalValue] = React4.useState(void 0);
|
|
2645
3012
|
const isBound = Boolean(bindings?.value);
|
|
2646
3013
|
const value = isBound ? boundValue : localValue;
|
|
2647
3014
|
const setValue = isBound ? setBoundValue : setLocalValue;
|
|
@@ -2715,7 +3082,330 @@ var components2 = {
|
|
|
2715
3082
|
Metric: (ctx) => /* @__PURE__ */ jsx(Metric, { ...ctx })
|
|
2716
3083
|
};
|
|
2717
3084
|
var generativeRenderers = components2;
|
|
2718
|
-
var
|
|
3085
|
+
var RADIUS = "rounded-[calc(var(--radius,0.5rem)*1.5)]";
|
|
3086
|
+
function useAbsolute(path) {
|
|
3087
|
+
const repeat = useRepeatScope();
|
|
3088
|
+
if (path.startsWith("/")) return path;
|
|
3089
|
+
if (!repeat) return path;
|
|
3090
|
+
return path === "" ? repeat.basePath : `${repeat.basePath}/${path}`;
|
|
3091
|
+
}
|
|
3092
|
+
function asDate(value) {
|
|
3093
|
+
if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}/.test(value)) return void 0;
|
|
3094
|
+
const date = /* @__PURE__ */ new Date(`${value.slice(0, 10)}T12:00:00Z`);
|
|
3095
|
+
return Number.isNaN(date.getTime()) ? void 0 : date;
|
|
3096
|
+
}
|
|
3097
|
+
function Composer({ props, children, emit }) {
|
|
3098
|
+
const host = useFrameHost();
|
|
3099
|
+
const busy = useDescriptorScope().env?.disabled ?? false;
|
|
3100
|
+
const two = props.columns === "2";
|
|
3101
|
+
return /* @__PURE__ */ jsxs(
|
|
3102
|
+
"div",
|
|
3103
|
+
{
|
|
3104
|
+
className: cn("mx-auto flex w-full flex-col gap-7", two ? "max-w-[980px]" : "max-w-[740px]"),
|
|
3105
|
+
children: [
|
|
3106
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
3107
|
+
/* @__PURE__ */ jsx(
|
|
3108
|
+
"h1",
|
|
3109
|
+
{
|
|
3110
|
+
className: cn(
|
|
3111
|
+
"text-[32px] leading-[1.1] text-balance text-foreground sm:text-[38px] sm:leading-[1.08]",
|
|
3112
|
+
headingClass(700, true)
|
|
3113
|
+
),
|
|
3114
|
+
children: props.headline
|
|
3115
|
+
}
|
|
3116
|
+
),
|
|
3117
|
+
props.lede ? /* @__PURE__ */ jsx("p", { className: "mt-3.5 max-w-[62ch] text-[17px] leading-relaxed text-muted-foreground", children: props.lede }) : null
|
|
3118
|
+
] }),
|
|
3119
|
+
/* @__PURE__ */ jsxs(
|
|
3120
|
+
"div",
|
|
3121
|
+
{
|
|
3122
|
+
"data-style-panel": "",
|
|
3123
|
+
className: cn(RADIUS, panelSurfaceClass, panelFlatShadowClass, "p-7 max-sm:p-5"),
|
|
3124
|
+
children: [
|
|
3125
|
+
/* @__PURE__ */ jsx(
|
|
3126
|
+
"div",
|
|
3127
|
+
{
|
|
3128
|
+
className: cn(
|
|
3129
|
+
"grid gap-8",
|
|
3130
|
+
two && "md:block md:columns-2 md:gap-x-10 md:[&>*+*]:mt-8 md:[&>*>h2]:break-after-avoid md:[&>*>*:not(h2)]:break-inside-avoid"
|
|
3131
|
+
),
|
|
3132
|
+
children
|
|
3133
|
+
}
|
|
3134
|
+
),
|
|
3135
|
+
/* @__PURE__ */ jsxs("div", { className: "sticky bottom-0 z-[2] -mx-7 -mb-7 mt-7 flex items-center justify-between gap-4 rounded-b-[calc(var(--radius,0.5rem)*1.5)] border-t border-border [background-color:var(--panel-fill,var(--card,hsl(0_0%_100%)))] px-7 pt-[18px] pb-7 max-sm:-mx-5 max-sm:-mb-5 max-sm:flex-col-reverse max-sm:items-stretch max-sm:px-5 max-sm:pb-5", children: [
|
|
3136
|
+
host.eta ? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-2 text-sm text-muted-foreground max-sm:justify-center", children: [
|
|
3137
|
+
/* @__PURE__ */ jsx(Clock, { className: "size-4", "aria-hidden": "true" }),
|
|
3138
|
+
" ",
|
|
3139
|
+
host.eta
|
|
3140
|
+
] }) : /* @__PURE__ */ jsx("span", {}),
|
|
3141
|
+
/* @__PURE__ */ jsxs(
|
|
3142
|
+
"button",
|
|
3143
|
+
{
|
|
3144
|
+
type: "button",
|
|
3145
|
+
disabled: busy,
|
|
3146
|
+
onClick: () => emit("press"),
|
|
3147
|
+
className: cn(
|
|
3148
|
+
"inline-flex min-h-11 items-center justify-center gap-2 rounded-[var(--radius,0.5rem)] bg-primary px-[22px] text-[15px] font-semibold text-primary-foreground transition-all hover:bg-primary/90",
|
|
3149
|
+
actionShadowClass,
|
|
3150
|
+
focusOutlineClass,
|
|
3151
|
+
"disabled:cursor-not-allowed disabled:opacity-60 disabled:hover:bg-primary"
|
|
3152
|
+
),
|
|
3153
|
+
children: [
|
|
3154
|
+
props.runLabel,
|
|
3155
|
+
" ",
|
|
3156
|
+
/* @__PURE__ */ jsx(ArrowRight, { className: "size-4", "aria-hidden": "true" })
|
|
3157
|
+
]
|
|
3158
|
+
}
|
|
3159
|
+
)
|
|
3160
|
+
] })
|
|
3161
|
+
]
|
|
3162
|
+
}
|
|
3163
|
+
),
|
|
3164
|
+
props.notes && props.notes.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "grid gap-x-8 gap-y-2.5 px-1 sm:grid-cols-2", children: props.notes.map((note, index) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-2.5 text-sm text-muted-foreground", children: [
|
|
3165
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: linkTextClass, children: "\u2713" }),
|
|
3166
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0", children: note })
|
|
3167
|
+
] }, index)) }) : null
|
|
3168
|
+
]
|
|
3169
|
+
}
|
|
3170
|
+
);
|
|
3171
|
+
}
|
|
3172
|
+
function FieldGroup({ props, children }) {
|
|
3173
|
+
return /* @__PURE__ */ jsxs("section", { className: "flex min-w-0 flex-col gap-5", children: [
|
|
3174
|
+
props.title ? /* @__PURE__ */ jsx("h2", { className: cn("text-[17px] leading-snug text-foreground", headingClass(600)), children: props.title }) : null,
|
|
3175
|
+
children
|
|
3176
|
+
] });
|
|
3177
|
+
}
|
|
3178
|
+
function ResultHeader({ props }) {
|
|
3179
|
+
const host = useFrameHost();
|
|
3180
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-6 max-sm:flex-col", children: [
|
|
3181
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
3182
|
+
props.eyebrow ? /* @__PURE__ */ jsx("p", { className: cn("mb-1.5 text-[13px] font-semibold", linkTextClass), children: props.eyebrow }) : null,
|
|
3183
|
+
/* @__PURE__ */ jsx(
|
|
3184
|
+
"h1",
|
|
3185
|
+
{
|
|
3186
|
+
className: cn(
|
|
3187
|
+
"text-[28px] leading-[1.12] text-balance text-foreground sm:text-[32px]",
|
|
3188
|
+
headingClass(700, true)
|
|
3189
|
+
),
|
|
3190
|
+
children: props.title
|
|
3191
|
+
}
|
|
3192
|
+
),
|
|
3193
|
+
props.subtitle ? /* @__PURE__ */ jsx("p", { className: "mt-2 text-[15px] text-muted-foreground", children: props.subtitle }) : null
|
|
3194
|
+
] }),
|
|
3195
|
+
host.actions && host.actions.length > 0 && host.onAction ? /* @__PURE__ */ jsx("div", { className: "flex shrink-0 gap-2", children: host.actions.map((label, i) => /* @__PURE__ */ jsx(
|
|
3196
|
+
"button",
|
|
3197
|
+
{
|
|
3198
|
+
type: "button",
|
|
3199
|
+
onClick: () => host.onAction?.(label),
|
|
3200
|
+
className: cn(
|
|
3201
|
+
"inline-flex min-h-11 items-center rounded-[var(--radius,0.5rem)] px-4 text-sm font-semibold sm:min-h-9",
|
|
3202
|
+
focusOutlineClass,
|
|
3203
|
+
i === 0 ? "bg-primary text-primary-foreground" : "border border-border bg-background text-foreground"
|
|
3204
|
+
),
|
|
3205
|
+
children: label
|
|
3206
|
+
},
|
|
3207
|
+
`${i}-${label}`
|
|
3208
|
+
)) }) : null
|
|
3209
|
+
] });
|
|
3210
|
+
}
|
|
3211
|
+
function segmentMix(index, count) {
|
|
3212
|
+
return count <= 1 ? 100 : Math.round(100 - index * 75 / (count - 1));
|
|
3213
|
+
}
|
|
3214
|
+
function segmentColor(index, count) {
|
|
3215
|
+
return `color-mix(in oklab, var(--link, var(--primary, hsl(240 5.9% 10%))) ${segmentMix(index, count)}%, var(--muted, hsl(240 4.8% 95.9%)))`;
|
|
3216
|
+
}
|
|
3217
|
+
function amount(value, unit) {
|
|
3218
|
+
if (unit && /^[A-Z]{3}$/.test(unit)) {
|
|
3219
|
+
try {
|
|
3220
|
+
return new Intl.NumberFormat("en-GB", {
|
|
3221
|
+
style: "currency",
|
|
3222
|
+
currency: unit,
|
|
3223
|
+
maximumFractionDigits: 0
|
|
3224
|
+
}).format(value);
|
|
3225
|
+
} catch {
|
|
3226
|
+
}
|
|
3227
|
+
}
|
|
3228
|
+
const n = new Intl.NumberFormat("en-GB", { maximumFractionDigits: 2 }).format(value);
|
|
3229
|
+
return unit ? `${n} ${unit}` : n;
|
|
3230
|
+
}
|
|
3231
|
+
function ProportionBar({ props }) {
|
|
3232
|
+
const rows = Array.isArray(props.items) ? props.items : [];
|
|
3233
|
+
const parts = rows.map((row) => ({
|
|
3234
|
+
label: String(row[props.labelKey] ?? ""),
|
|
3235
|
+
value: Number(row[props.valueKey] ?? 0)
|
|
3236
|
+
})).filter((p) => Number.isFinite(p.value) && p.value > 0);
|
|
3237
|
+
const sum = parts.reduce((s, p) => s + p.value, 0);
|
|
3238
|
+
const total = typeof props.total === "number" ? props.total : sum;
|
|
3239
|
+
const scale = Math.max(sum, total, typeof props.of === "number" ? props.of : 0) || 1;
|
|
3240
|
+
const cap = (s) => s.charAt(0).toUpperCase() + s.slice(1);
|
|
3241
|
+
return /* @__PURE__ */ jsxs(
|
|
3242
|
+
"div",
|
|
3243
|
+
{
|
|
3244
|
+
"data-style-panel": "",
|
|
3245
|
+
className: cn(
|
|
3246
|
+
RADIUS,
|
|
3247
|
+
panelSurfaceClass,
|
|
3248
|
+
panelFlatShadowClass,
|
|
3249
|
+
"flex flex-col gap-3.5 px-6 py-5"
|
|
3250
|
+
),
|
|
3251
|
+
children: [
|
|
3252
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-baseline gap-x-2.5", children: [
|
|
3253
|
+
/* @__PURE__ */ jsx("span", { className: "text-[15px] text-muted-foreground", children: props.label }),
|
|
3254
|
+
/* @__PURE__ */ jsx("strong", { className: "text-2xl font-semibold tabular-nums text-foreground", children: amount(total, props.unit) }),
|
|
3255
|
+
typeof props.of === "number" ? /* @__PURE__ */ jsxs("span", { className: "text-[15px] text-muted-foreground", children: [
|
|
3256
|
+
"of ",
|
|
3257
|
+
amount(props.of, props.unit)
|
|
3258
|
+
] }) : null
|
|
3259
|
+
] }),
|
|
3260
|
+
/* @__PURE__ */ jsx("div", { className: "flex h-2 gap-0.5 overflow-hidden rounded-full bg-muted", "aria-hidden": "true", children: parts.map((p, i) => /* @__PURE__ */ jsx(
|
|
3261
|
+
"span",
|
|
3262
|
+
{
|
|
3263
|
+
style: {
|
|
3264
|
+
width: `${p.value / scale * 100}%`,
|
|
3265
|
+
background: segmentColor(i, parts.length)
|
|
3266
|
+
}
|
|
3267
|
+
},
|
|
3268
|
+
`${i}-${p.label}`
|
|
3269
|
+
)) }),
|
|
3270
|
+
/* @__PURE__ */ jsx("ul", { className: "flex flex-wrap gap-x-5 gap-y-1", children: parts.map((p, i) => /* @__PURE__ */ jsxs(
|
|
3271
|
+
"li",
|
|
3272
|
+
{
|
|
3273
|
+
className: "inline-flex items-center gap-2 text-sm text-muted-foreground",
|
|
3274
|
+
children: [
|
|
3275
|
+
/* @__PURE__ */ jsx(
|
|
3276
|
+
"span",
|
|
3277
|
+
{
|
|
3278
|
+
className: "size-2 rounded-[2px]",
|
|
3279
|
+
style: {
|
|
3280
|
+
background: segmentColor(i, parts.length)
|
|
3281
|
+
},
|
|
3282
|
+
"aria-hidden": "true"
|
|
3283
|
+
}
|
|
3284
|
+
),
|
|
3285
|
+
cap(p.label),
|
|
3286
|
+
" ",
|
|
3287
|
+
amount(p.value, props.unit)
|
|
3288
|
+
]
|
|
3289
|
+
},
|
|
3290
|
+
`${i}-${p.label}`
|
|
3291
|
+
)) })
|
|
3292
|
+
]
|
|
3293
|
+
}
|
|
3294
|
+
);
|
|
3295
|
+
}
|
|
3296
|
+
var COLOR_VALUE = /^(?:#[0-9a-f]{3,8}|(?:rgba?|hsla?|hwb|lab|lch|oklab|oklch)\([\w\s.,%/+-]*\)|[a-z]+)$/i;
|
|
3297
|
+
function Swatches({ props }) {
|
|
3298
|
+
const colors = (props.colors ?? []).filter(
|
|
3299
|
+
(c) => typeof c === "string" && COLOR_VALUE.test(c.trim())
|
|
3300
|
+
);
|
|
3301
|
+
return /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: colors.map((color, i) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3302
|
+
/* @__PURE__ */ jsx(
|
|
3303
|
+
"span",
|
|
3304
|
+
{
|
|
3305
|
+
className: "h-7 w-11 rounded-[3px] border border-border",
|
|
3306
|
+
style: { backgroundColor: color.trim() }
|
|
3307
|
+
}
|
|
3308
|
+
),
|
|
3309
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono text-[11px] text-muted-foreground", children: color })
|
|
3310
|
+
] }, `${color}-${i}`)) });
|
|
3311
|
+
}
|
|
3312
|
+
var ASPECT = {
|
|
3313
|
+
"16:9": "aspect-video",
|
|
3314
|
+
"4:3": "aspect-[4/3]",
|
|
3315
|
+
"1:1": "aspect-square"
|
|
3316
|
+
};
|
|
3317
|
+
function Picture({
|
|
3318
|
+
props
|
|
3319
|
+
}) {
|
|
3320
|
+
const path = useAbsolute(props.path);
|
|
3321
|
+
const value = useStateValue(path);
|
|
3322
|
+
const resolve = useResolveUrl();
|
|
3323
|
+
const content = readImageContent(value);
|
|
3324
|
+
const src = content ? viewableUrl(resolve?.(content.url)) ?? viewableUrl(content.publicUrl) ?? viewableUrl(content.url) : void 0;
|
|
3325
|
+
const aspect = props.aspect && props.aspect !== "auto" ? ASPECT[props.aspect] : void 0;
|
|
3326
|
+
if (!src) return null;
|
|
3327
|
+
return /* @__PURE__ */ jsx(
|
|
3328
|
+
"img",
|
|
3329
|
+
{
|
|
3330
|
+
src,
|
|
3331
|
+
alt: props.alt ?? content?.caption ?? "",
|
|
3332
|
+
referrerPolicy: "no-referrer",
|
|
3333
|
+
className: cn(
|
|
3334
|
+
"block w-full rounded-[var(--radius,0.5rem)] border border-border bg-muted object-cover",
|
|
3335
|
+
aspect
|
|
3336
|
+
)
|
|
3337
|
+
}
|
|
3338
|
+
);
|
|
3339
|
+
}
|
|
3340
|
+
function present(value) {
|
|
3341
|
+
return value !== void 0 && value !== null && value !== "";
|
|
3342
|
+
}
|
|
3343
|
+
function Fact({
|
|
3344
|
+
props
|
|
3345
|
+
}) {
|
|
3346
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 rounded-[var(--radius,0.5rem)] border border-border bg-background px-4 py-3", children: [
|
|
3347
|
+
/* @__PURE__ */ jsx("span", { className: "text-[13px] text-muted-foreground", children: props.label }),
|
|
3348
|
+
/* @__PURE__ */ jsx("span", { className: "text-[16px] font-medium text-foreground tabular-nums", children: present(props.value) ? String(props.value) : "\u2014" }),
|
|
3349
|
+
props.detail ? /* @__PURE__ */ jsx("span", { className: "text-[13px] text-muted-foreground", children: props.detail }) : null
|
|
3350
|
+
] });
|
|
3351
|
+
}
|
|
3352
|
+
function Detail({ props }) {
|
|
3353
|
+
if (!present(props.value)) return null;
|
|
3354
|
+
return (
|
|
3355
|
+
// A rule between the rows of a list of details, never under one set in a
|
|
3356
|
+
// row: there it read as an underline on every detail but the last.
|
|
3357
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[minmax(0,8.5rem)_minmax(0,1fr)] gap-3 border-b border-border py-2.5 text-[14px] last:border-b-0 [.flex-row>&]:border-b-0 [.flex-row>&]:grid-cols-[auto_minmax(0,1fr)]", children: [
|
|
3358
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: props.label }),
|
|
3359
|
+
/* @__PURE__ */ jsx("span", { className: "text-foreground", children: String(props.value) })
|
|
3360
|
+
] })
|
|
3361
|
+
);
|
|
3362
|
+
}
|
|
3363
|
+
var DATE_STYLES = {
|
|
3364
|
+
long: { weekday: "long", day: "numeric", month: "long", year: "numeric", timeZone: "UTC" },
|
|
3365
|
+
short: { day: "numeric", month: "short", year: "numeric", timeZone: "UTC" },
|
|
3366
|
+
weekday: { weekday: "short", day: "numeric", month: "long", timeZone: "UTC" }
|
|
3367
|
+
};
|
|
3368
|
+
function DateText({ props }) {
|
|
3369
|
+
const date = asDate(props.value);
|
|
3370
|
+
if (!date) return null;
|
|
3371
|
+
const tone = props.tone === "accent" ? cn("text-[13px] font-semibold", linkTextClass) : props.tone === "muted" ? "text-sm text-muted-foreground" : "text-[15px] text-foreground";
|
|
3372
|
+
return /* @__PURE__ */ jsx("span", { className: cn("block", tone), children: date.toLocaleDateString("en-GB", DATE_STYLES[props.style ?? "long"]) });
|
|
3373
|
+
}
|
|
3374
|
+
function TextList({ props }) {
|
|
3375
|
+
const items = Array.isArray(props.items) ? props.items.filter((x) => typeof x === "string" && x.trim()) : [];
|
|
3376
|
+
if (items.length === 0) return null;
|
|
3377
|
+
const marker = props.marker ?? "bullet";
|
|
3378
|
+
const List2 = marker === "number" ? "ol" : "ul";
|
|
3379
|
+
return /* @__PURE__ */ jsx(List2, { className: "flex flex-col gap-2.5", children: items.map((text, index) => /* @__PURE__ */ jsxs("li", { className: "flex gap-3 text-[15px] leading-relaxed text-foreground", children: [
|
|
3380
|
+
/* @__PURE__ */ jsx(
|
|
3381
|
+
"span",
|
|
3382
|
+
{
|
|
3383
|
+
"aria-hidden": "true",
|
|
3384
|
+
className: cn(
|
|
3385
|
+
"mt-[0.55em] shrink-0",
|
|
3386
|
+
marker === "bullet" && "size-1.5 rounded-full bg-[color:var(--link,var(--primary,hsl(240_5.9%_10%)))]",
|
|
3387
|
+
marker === "number" && cn("mt-0 min-w-5 text-sm font-semibold tabular-nums", linkTextClass),
|
|
3388
|
+
marker === "check" && cn("mt-0", linkTextClass)
|
|
3389
|
+
),
|
|
3390
|
+
children: marker === "number" ? `${index + 1}.` : marker === "check" ? "\u2713" : null
|
|
3391
|
+
}
|
|
3392
|
+
),
|
|
3393
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0", children: String(text) })
|
|
3394
|
+
] }, index)) });
|
|
3395
|
+
}
|
|
3396
|
+
var frameRenderers = {
|
|
3397
|
+
TextList: (ctx) => /* @__PURE__ */ jsx(TextList, { ...ctx }),
|
|
3398
|
+
DateText: (ctx) => /* @__PURE__ */ jsx(DateText, { ...ctx }),
|
|
3399
|
+
Composer: (ctx) => /* @__PURE__ */ jsx(Composer, { ...ctx }),
|
|
3400
|
+
FieldGroup: (ctx) => /* @__PURE__ */ jsx(FieldGroup, { ...ctx }),
|
|
3401
|
+
ResultHeader: (ctx) => /* @__PURE__ */ jsx(ResultHeader, { ...ctx }),
|
|
3402
|
+
ProportionBar: (ctx) => /* @__PURE__ */ jsx(ProportionBar, { ...ctx }),
|
|
3403
|
+
Swatches: (ctx) => /* @__PURE__ */ jsx(Swatches, { ...ctx }),
|
|
3404
|
+
Picture: (ctx) => /* @__PURE__ */ jsx(Picture, { ...ctx }),
|
|
3405
|
+
Fact: (ctx) => /* @__PURE__ */ jsx(Fact, { ...ctx }),
|
|
3406
|
+
Detail: (ctx) => /* @__PURE__ */ jsx(Detail, { ...ctx })
|
|
3407
|
+
};
|
|
3408
|
+
var ResultSlotContext = React4.createContext(null);
|
|
2719
3409
|
function ResultSlotProvider({
|
|
2720
3410
|
slot,
|
|
2721
3411
|
children
|
|
@@ -2723,7 +3413,7 @@ function ResultSlotProvider({
|
|
|
2723
3413
|
return /* @__PURE__ */ jsx(ResultSlotContext.Provider, { value: slot, children });
|
|
2724
3414
|
}
|
|
2725
3415
|
function useResultSlot() {
|
|
2726
|
-
return
|
|
3416
|
+
return React4.useContext(ResultSlotContext);
|
|
2727
3417
|
}
|
|
2728
3418
|
var CONTAINER = "mx-auto w-full max-w-6xl px-6 sm:px-8";
|
|
2729
3419
|
var LABEL2 = "block text-[13.5px] leading-none font-medium text-foreground";
|
|
@@ -2799,7 +3489,7 @@ function Hero({ props }) {
|
|
|
2799
3489
|
] });
|
|
2800
3490
|
}
|
|
2801
3491
|
function Workspace({ props, children }) {
|
|
2802
|
-
const [work, rail] =
|
|
3492
|
+
const [work, rail] = React4.Children.toArray(children);
|
|
2803
3493
|
const railLeft = props.rail === "left";
|
|
2804
3494
|
return /* @__PURE__ */ jsxs(
|
|
2805
3495
|
"div",
|
|
@@ -2871,22 +3561,24 @@ function Rail({ props, children }) {
|
|
|
2871
3561
|
)
|
|
2872
3562
|
);
|
|
2873
3563
|
}
|
|
2874
|
-
function
|
|
3564
|
+
function present2(value) {
|
|
2875
3565
|
return value !== void 0 && value !== null && value !== "";
|
|
2876
3566
|
}
|
|
2877
3567
|
function SummaryRow({ props }) {
|
|
2878
|
-
const text = [props.value, props.detail].filter(
|
|
3568
|
+
const text = [props.value, props.detail].filter(present2).map(String).join(props.separator ?? " ");
|
|
2879
3569
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between gap-4 border-b border-border/60 py-3 first:pt-0 last:border-b-0", children: [
|
|
2880
3570
|
/* @__PURE__ */ jsx("span", { className: "shrink-0 text-[13px] text-muted-foreground", children: props.label }),
|
|
2881
3571
|
text ? /* @__PURE__ */ jsx("span", { className: "text-right text-[13px] font-medium text-foreground", children: text }) : /* @__PURE__ */ jsx("span", { className: "text-[13px] text-muted-foreground/50", children: props.placeholder ?? "\u2014" })
|
|
2882
3572
|
] });
|
|
2883
3573
|
}
|
|
2884
3574
|
function Cta({ props, emit }) {
|
|
3575
|
+
const busy = useDescriptorScope().env?.disabled ?? false;
|
|
2885
3576
|
return /* @__PURE__ */ jsxs("div", { className: "mt-6", children: [
|
|
2886
3577
|
/* @__PURE__ */ jsx(
|
|
2887
3578
|
"button",
|
|
2888
3579
|
{
|
|
2889
3580
|
type: "button",
|
|
3581
|
+
disabled: busy,
|
|
2890
3582
|
onClick: () => emit("press"),
|
|
2891
3583
|
className: cn(
|
|
2892
3584
|
"inline-flex h-12 w-full items-center justify-center rounded-lg bg-primary px-6 text-sm font-semibold text-primary-foreground transition-all hover:bg-primary/90",
|
|
@@ -2894,7 +3586,8 @@ function Cta({ props, emit }) {
|
|
|
2894
3586
|
// it had. Focus is an outline, which no shadow a style sets can
|
|
2895
3587
|
// replace or hide.
|
|
2896
3588
|
actionShadowClass,
|
|
2897
|
-
focusOutlineClass
|
|
3589
|
+
focusOutlineClass,
|
|
3590
|
+
"disabled:cursor-not-allowed disabled:opacity-60 disabled:hover:bg-primary"
|
|
2898
3591
|
),
|
|
2899
3592
|
children: props.label
|
|
2900
3593
|
}
|
|
@@ -2925,7 +3618,7 @@ function useTextField(props, bindings) {
|
|
|
2925
3618
|
props.value ?? void 0,
|
|
2926
3619
|
bindings?.value
|
|
2927
3620
|
);
|
|
2928
|
-
const [localValue, setLocalValue] =
|
|
3621
|
+
const [localValue, setLocalValue] = React4.useState("");
|
|
2929
3622
|
const isBound = Boolean(bindings?.value);
|
|
2930
3623
|
const value = isBound ? boundValue ?? "" : localValue;
|
|
2931
3624
|
const setValue = isBound ? setBoundValue : setLocalValue;
|
|
@@ -3014,7 +3707,8 @@ var { registry: generativeRegistry } = defineRegistry(catalog, {
|
|
|
3014
3707
|
Rail: (ctx) => /* @__PURE__ */ jsx(Rail, { ...ctx }),
|
|
3015
3708
|
SummaryRow: (ctx) => /* @__PURE__ */ jsx(SummaryRow, { ...ctx }),
|
|
3016
3709
|
Cta: (ctx) => /* @__PURE__ */ jsx(Cta, { ...ctx }),
|
|
3017
|
-
Footer: (ctx) => /* @__PURE__ */ jsx(Footer, { ...ctx })
|
|
3710
|
+
Footer: (ctx) => /* @__PURE__ */ jsx(Footer, { ...ctx }),
|
|
3711
|
+
...frameRenderers
|
|
3018
3712
|
}
|
|
3019
3713
|
});
|
|
3020
3714
|
function GenerativePage({
|
|
@@ -3027,24 +3721,40 @@ function GenerativePage({
|
|
|
3027
3721
|
brand
|
|
3028
3722
|
}) {
|
|
3029
3723
|
const { inputs, result, env, idPrefix } = scope;
|
|
3030
|
-
const stableScope =
|
|
3724
|
+
const stableScope = React4.useMemo(
|
|
3031
3725
|
() => ({ inputs, result, env, idPrefix }),
|
|
3032
3726
|
[inputs, result, env, idPrefix]
|
|
3033
3727
|
);
|
|
3034
|
-
const latest =
|
|
3035
|
-
|
|
3728
|
+
const latest = React4.useRef({ onRun, store });
|
|
3729
|
+
React4.useEffect(() => {
|
|
3036
3730
|
latest.current = { onRun, store };
|
|
3037
3731
|
});
|
|
3038
|
-
const
|
|
3732
|
+
const running = React4.useRef(false);
|
|
3733
|
+
const [handlers] = React4.useState(() => ({
|
|
3039
3734
|
run: () => {
|
|
3040
|
-
|
|
3735
|
+
if (running.current) return void 0;
|
|
3736
|
+
running.current = true;
|
|
3737
|
+
let pending;
|
|
3738
|
+
try {
|
|
3739
|
+
pending = latest.current.onRun?.(latest.current.store.getSnapshot());
|
|
3740
|
+
} catch (error) {
|
|
3741
|
+
running.current = false;
|
|
3742
|
+
throw error;
|
|
3743
|
+
}
|
|
3744
|
+
if (isThenable(pending)) {
|
|
3745
|
+
return Promise.resolve(pending).finally(() => {
|
|
3746
|
+
running.current = false;
|
|
3747
|
+
});
|
|
3748
|
+
}
|
|
3749
|
+
running.current = false;
|
|
3750
|
+
return void 0;
|
|
3041
3751
|
}
|
|
3042
3752
|
}));
|
|
3043
3753
|
const page = /* @__PURE__ */ jsx(DescriptorProvider, { scope: stableScope, children: /* @__PURE__ */ jsx(JSONUIProvider, { registry, store, handlers, children: /* @__PURE__ */ jsx(Renderer, { spec, registry, loading }) }) });
|
|
3044
3754
|
return brand ? /* @__PURE__ */ jsx(BrandProvider, { manifest: brand, children: page }) : page;
|
|
3045
3755
|
}
|
|
3046
3756
|
function useStoreSnapshot(store) {
|
|
3047
|
-
return
|
|
3757
|
+
return React4.useSyncExternalStore(
|
|
3048
3758
|
store.subscribe,
|
|
3049
3759
|
store.getSnapshot,
|
|
3050
3760
|
store.getServerSnapshot ?? store.getSnapshot
|
|
@@ -3097,6 +3807,8 @@ function fixtureId(fixture) {
|
|
|
3097
3807
|
return [
|
|
3098
3808
|
fixture.producer,
|
|
3099
3809
|
fixture.model,
|
|
3810
|
+
fixture.frame ?? null,
|
|
3811
|
+
fixture.style ?? null,
|
|
3100
3812
|
fixture.seed ? "seeded" : null,
|
|
3101
3813
|
fixture.critic ? "critic" : null
|
|
3102
3814
|
].filter((part) => part !== null).join("--");
|
|
@@ -3108,7 +3820,10 @@ var PRODUCER_LABEL = {
|
|
|
3108
3820
|
};
|
|
3109
3821
|
function fixtureLabel(fixture) {
|
|
3110
3822
|
const parts = [PRODUCER_LABEL[fixture.producer], fixture.model];
|
|
3823
|
+
if (fixture.frame) parts.push(`${fixture.frame} frame`);
|
|
3824
|
+
if (fixture.style) parts.push(`${fixture.style} style`);
|
|
3111
3825
|
if (fixture.seed) parts.push("with a seed");
|
|
3826
|
+
if (fixture.repairs) parts.push(`repaired \xD7 ${fixture.repairs}`);
|
|
3112
3827
|
if (fixture.critic) {
|
|
3113
3828
|
parts.push(
|
|
3114
3829
|
`${fixture.critic.model} critic \xD7 ${fixture.critic.rounds} round${fixture.critic.rounds === 1 ? "" : "s"}`
|
|
@@ -3127,6 +3842,6 @@ function findFixture(fixtures, pipeRef, id) {
|
|
|
3127
3842
|
return found;
|
|
3128
3843
|
}
|
|
3129
3844
|
|
|
3130
|
-
export { BrandProvider, COMPONENT_NAMES, COMPONENT_RENDERINGS, CUSTOM_COMPONENTS, DESIGNER_BRIEF_CONCEPT, DESIGNER_CATALOG_CONCEPT, DescriptorProvider, GenerativePage, ICON_NAMES, INPUTS_ROOT, METRIC_FORMATS, PICKED_SHADCN, PRODUCT_COMPONENTS, PROMPT_HASH, RESULT_ROOT, ResultSlotProvider, absoluteHatchPath, catalog, designerCatalog, fieldAtSegments, findFixture, fixtureId, fixtureLabel, formatProblems, generativeRegistry, generativeRenderers, inputBrief, inputFieldAtPath, isDelegatedInput, isDelegatedResult, joinPath, jsonlLines, layoutFits, layoutProblems, pathFromDomId, payloadToState, repeatBasePathOf, resultBrief, resultFieldAtPath, segmentsUnder, specFromJsonl, specToJsonl, useBrand, useDescriptorScope, useResultSlot, useStoreSnapshot, validateAgainstCatalog };
|
|
3845
|
+
export { BrandProvider, COMPONENT_NAMES, COMPONENT_RENDERINGS, COMPOSER_COMPONENTS, CUSTOM_COMPONENTS, DESIGNER_BRIEF_CONCEPT, DESIGNER_CATALOG_CONCEPT, DescriptorProvider, FRAMES, FRAME_COMPONENTS, FrameHostProvider, GenerativePage, ICON_NAMES, INPUTS_ROOT, METRIC_FORMATS, PICKED_SHADCN, PRODUCT_COMPONENTS, PROMPT_HASH, REPAIR_ATTEMPTS, RESULT_COMPONENTS, RESULT_ROOT, ResultSlotProvider, absoluteHatchPath, catalog, componentNamesFor, designerCatalog, domIdFor, fieldAtSegments, findFixture, fixtureId, fixtureLabel, formatProblems, frameCatalog, generativeRegistry, generativeRenderers, inputBrief, inputFieldAtPath, isDelegatedInput, isDelegatedResult, joinPath, jsonlLines, layoutCheckProblems, layoutFits, layoutProblems, pathFromDomId, payloadToState, promptHashSubject, repeatBasePathOf, resultBrief, resultFieldAtPath, seedLine, segmentsUnder, specFromJsonl, specToJsonl, useBrand, useDescriptorScope, useFrameHost, useResultSlot, useStoreSnapshot, validateAgainstCatalog };
|
|
3131
3846
|
//# sourceMappingURL=index.js.map
|
|
3132
3847
|
//# sourceMappingURL=index.js.map
|