cortena-ui 1.3.0 → 1.4.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/README.md +74 -3
- package/dist/a2ui/catalogue-doc.d.ts +44 -0
- package/dist/a2ui/catalogue-doc.js +169 -0
- package/dist/a2ui/catalogue-doc.js.map +1 -0
- package/dist/a2ui/catalogue.d.ts +44 -0
- package/dist/a2ui/catalogue.js +942 -0
- package/dist/a2ui/catalogue.js.map +1 -0
- package/dist/a2ui/index.d.ts +7 -0
- package/dist/a2ui/message.d.ts +232 -0
- package/dist/a2ui/message.js +365 -0
- package/dist/a2ui/message.js.map +1 -0
- package/dist/a2ui/renderer.d.ts +46 -0
- package/dist/a2ui/renderer.js +252 -0
- package/dist/a2ui/renderer.js.map +1 -0
- package/dist/a2ui/views.d.ts +80 -0
- package/dist/a2ui/views.js +596 -0
- package/dist/a2ui/views.js.map +1 -0
- package/dist/a2ui.d.ts +8 -0
- package/dist/a2ui.js +7 -0
- package/dist/chart.d.ts +9 -0
- package/dist/chart.js +9 -0
- package/dist/components/accordion.d.ts +22 -0
- package/dist/components/accordion.js +63 -0
- package/dist/components/accordion.js.map +1 -0
- package/dist/components/alert.d.ts +15 -0
- package/dist/components/alert.js +64 -0
- package/dist/components/alert.js.map +1 -0
- package/dist/components/avatar.d.ts +18 -0
- package/dist/components/avatar.js +40 -0
- package/dist/components/avatar.js.map +1 -0
- package/dist/components/badge.d.ts +12 -0
- package/dist/components/badge.js +47 -0
- package/dist/components/badge.js.map +1 -0
- package/dist/components/breadcrumb.d.ts +71 -0
- package/dist/components/breadcrumb.js +123 -0
- package/dist/components/breadcrumb.js.map +1 -0
- package/dist/components/button-link.d.ts +28 -0
- package/dist/components/button-link.js +24 -0
- package/dist/components/button-link.js.map +1 -0
- package/dist/components/button.d.ts +24 -0
- package/dist/components/button.js +65 -0
- package/dist/components/button.js.map +1 -0
- package/dist/components/calendar.d.ts +28 -0
- package/dist/components/calendar.js +123 -0
- package/dist/components/calendar.js.map +1 -0
- package/dist/components/card.d.ts +32 -0
- package/dist/components/card.js +57 -0
- package/dist/components/card.js.map +1 -0
- package/dist/components/chart/chart.d.ts +71 -0
- package/dist/components/chart/chart.js +167 -0
- package/dist/components/chart/chart.js.map +1 -0
- package/dist/components/chart/container.d.ts +88 -0
- package/dist/components/chart/container.js +189 -0
- package/dist/components/chart/container.js.map +1 -0
- package/dist/components/chart/data.js +128 -0
- package/dist/components/chart/data.js.map +1 -0
- package/dist/components/chart/index.d.ts +9 -0
- package/dist/components/chart/index.js +10 -0
- package/dist/components/chart/nivo-charts.js +225 -0
- package/dist/components/chart/nivo-charts.js.map +1 -0
- package/dist/components/chart/nivo-lazy.js +50 -0
- package/dist/components/chart/nivo-lazy.js.map +1 -0
- package/dist/components/chart/nivo-theme.d.ts +156 -0
- package/dist/components/chart/nivo-theme.js +161 -0
- package/dist/components/chart/nivo-theme.js.map +1 -0
- package/dist/components/chart/recharts-charts.js +276 -0
- package/dist/components/chart/recharts-charts.js.map +1 -0
- package/dist/components/chart/recharts-lazy.js +58 -0
- package/dist/components/chart/recharts-lazy.js.map +1 -0
- package/dist/components/chart/recharts-parts.d.ts +10 -0
- package/dist/components/chart/recharts-parts.js +25 -0
- package/dist/components/chart/recharts-parts.js.map +1 -0
- package/dist/components/chart/tokens.d.ts +62 -0
- package/dist/components/chart/tokens.js +192 -0
- package/dist/components/chart/tokens.js.map +1 -0
- package/dist/components/chart/types.d.ts +114 -0
- package/dist/components/chart/types.js +27 -0
- package/dist/components/chart/types.js.map +1 -0
- package/dist/components/checkbox.d.ts +20 -0
- package/dist/components/checkbox.js +24 -0
- package/dist/components/checkbox.js.map +1 -0
- package/dist/components/chip.d.ts +17 -0
- package/dist/components/chip.js +47 -0
- package/dist/components/chip.js.map +1 -0
- package/dist/components/combobox.d.ts +76 -0
- package/dist/components/combobox.js +201 -0
- package/dist/components/combobox.js.map +1 -0
- package/dist/components/command.d.ts +50 -0
- package/dist/components/command.js +117 -0
- package/dist/components/command.js.map +1 -0
- package/dist/components/data-table/data-table.d.ts +65 -0
- package/dist/components/data-table/data-table.js +588 -0
- package/dist/components/data-table/data-table.js.map +1 -0
- package/dist/components/data-table/export.d.ts +23 -0
- package/dist/components/data-table/export.js +95 -0
- package/dist/components/data-table/export.js.map +1 -0
- package/dist/components/data-table/features.d.ts +66 -0
- package/dist/components/data-table/features.js +103 -0
- package/dist/components/data-table/features.js.map +1 -0
- package/dist/components/data-table/index.d.ts +8 -0
- package/dist/components/data-table/parts.d.ts +79 -0
- package/dist/components/data-table/parts.js +400 -0
- package/dist/components/data-table/parts.js.map +1 -0
- package/dist/components/data-table/system-columns.js +84 -0
- package/dist/components/data-table/system-columns.js.map +1 -0
- package/dist/components/data-table/types.d.ts +172 -0
- package/dist/components/data-table/use-data-table.d.ts +19 -0
- package/dist/components/data-table/use-data-table.js +171 -0
- package/dist/components/data-table/use-data-table.js.map +1 -0
- package/dist/components/data-table/use-server-source.js +200 -0
- package/dist/components/data-table/use-server-source.js.map +1 -0
- package/dist/components/date-field.d.ts +54 -0
- package/dist/components/date-field.js +235 -0
- package/dist/components/date-field.js.map +1 -0
- package/dist/components/date-picker.d.ts +42 -0
- package/dist/components/date-picker.js +125 -0
- package/dist/components/date-picker.js.map +1 -0
- package/dist/components/dialog.d.ts +36 -0
- package/dist/components/dialog.js +97 -0
- package/dist/components/dialog.js.map +1 -0
- package/dist/components/dropdown-menu.d.ts +54 -0
- package/dist/components/dropdown-menu.js +191 -0
- package/dist/components/dropdown-menu.js.map +1 -0
- package/dist/components/dropzone.d.ts +48 -0
- package/dist/components/dropzone.js +185 -0
- package/dist/components/dropzone.js.map +1 -0
- package/dist/components/empty-state.d.ts +22 -0
- package/dist/components/empty-state.js +46 -0
- package/dist/components/empty-state.js.map +1 -0
- package/dist/components/error-banner.d.ts +17 -0
- package/dist/components/error-banner.js +52 -0
- package/dist/components/error-banner.js.map +1 -0
- package/dist/components/field.d.ts +64 -0
- package/dist/components/field.js +133 -0
- package/dist/components/field.js.map +1 -0
- package/dist/components/form.d.ts +37 -0
- package/dist/components/form.js +103 -0
- package/dist/components/form.js.map +1 -0
- package/dist/components/input.d.ts +17 -0
- package/dist/components/input.js +26 -0
- package/dist/components/input.js.map +1 -0
- package/dist/components/kbd.d.ts +11 -0
- package/dist/components/kbd.js +20 -0
- package/dist/components/kbd.js.map +1 -0
- package/dist/components/label.d.ts +14 -0
- package/dist/components/label.js +28 -0
- package/dist/components/label.js.map +1 -0
- package/dist/components/loading-skeleton.d.ts +22 -0
- package/dist/components/loading-skeleton.js +123 -0
- package/dist/components/loading-skeleton.js.map +1 -0
- package/dist/components/markdown.d.ts +44 -0
- package/dist/components/markdown.js +231 -0
- package/dist/components/markdown.js.map +1 -0
- package/dist/components/page-header.d.ts +26 -0
- package/dist/components/page-header.js +53 -0
- package/dist/components/page-header.js.map +1 -0
- package/dist/components/popover.d.ts +29 -0
- package/dist/components/popover.js +74 -0
- package/dist/components/popover.js.map +1 -0
- package/dist/components/progress.d.ts +22 -0
- package/dist/components/progress.js +49 -0
- package/dist/components/progress.js.map +1 -0
- package/dist/components/radio-group.d.ts +20 -0
- package/dist/components/radio-group.js +29 -0
- package/dist/components/radio-group.js.map +1 -0
- package/dist/components/scroll-area.d.ts +25 -0
- package/dist/components/scroll-area.js +39 -0
- package/dist/components/scroll-area.js.map +1 -0
- package/dist/components/section-card.d.ts +29 -0
- package/dist/components/section-card.js +55 -0
- package/dist/components/section-card.js.map +1 -0
- package/dist/components/segmented.d.ts +27 -0
- package/dist/components/segmented.js +32 -0
- package/dist/components/segmented.js.map +1 -0
- package/dist/components/select.d.ts +62 -0
- package/dist/components/select.js +97 -0
- package/dist/components/select.js.map +1 -0
- package/dist/components/separator.d.ts +19 -0
- package/dist/components/separator.js +23 -0
- package/dist/components/separator.js.map +1 -0
- package/dist/components/sheet.d.ts +35 -0
- package/dist/components/sheet.js +131 -0
- package/dist/components/sheet.js.map +1 -0
- package/dist/components/skeleton.d.ts +12 -0
- package/dist/components/skeleton.js +22 -0
- package/dist/components/skeleton.js.map +1 -0
- package/dist/components/sortable-list.d.ts +67 -0
- package/dist/components/sortable-list.js +206 -0
- package/dist/components/sortable-list.js.map +1 -0
- package/dist/components/spinner.d.ts +29 -0
- package/dist/components/spinner.js +34 -0
- package/dist/components/spinner.js.map +1 -0
- package/dist/components/status-dot.d.ts +26 -0
- package/dist/components/status-dot.js +47 -0
- package/dist/components/status-dot.js.map +1 -0
- package/dist/components/switch.d.ts +21 -0
- package/dist/components/switch.js +21 -0
- package/dist/components/switch.js.map +1 -0
- package/dist/components/tabs.d.ts +24 -0
- package/dist/components/tabs.js +60 -0
- package/dist/components/tabs.js.map +1 -0
- package/dist/components/textarea.d.ts +19 -0
- package/dist/components/textarea.js +47 -0
- package/dist/components/textarea.js.map +1 -0
- package/dist/components/toast.d.ts +47 -0
- package/dist/components/toast.js +106 -0
- package/dist/components/toast.js.map +1 -0
- package/dist/components/toolbar.d.ts +19 -0
- package/dist/components/toolbar.js +45 -0
- package/dist/components/toolbar.js.map +1 -0
- package/dist/components/tooltip.d.ts +28 -0
- package/dist/components/tooltip.js +59 -0
- package/dist/components/tooltip.js.map +1 -0
- package/dist/core.d.ts +44 -0
- package/dist/core.js +44 -0
- package/dist/data-table.d.ts +9 -0
- package/dist/data-table.js +7 -0
- package/dist/form.d.ts +7 -0
- package/dist/form.js +7 -0
- package/dist/hooks/use-cortena-theme.d.ts +98 -0
- package/dist/hooks/use-cortena-theme.js +145 -0
- package/dist/hooks/use-cortena-theme.js.map +1 -0
- package/dist/index.d.ts +75 -2678
- package/dist/index.js +66 -8598
- package/dist/lib/cn.d.ts +10 -0
- package/dist/lib/cn.js +15 -0
- package/dist/lib/cn.js.map +1 -0
- package/dist/lib/render.d.ts +23 -0
- package/dist/lib/render.js +20 -0
- package/dist/lib/render.js.map +1 -0
- package/dist/lib/shakeable.js +39 -0
- package/dist/lib/shakeable.js.map +1 -0
- package/dist/markdown.d.ts +3 -0
- package/dist/markdown.js +3 -0
- package/dist/sortable-list.d.ts +3 -0
- package/dist/sortable-list.js +3 -0
- package/package.json +37 -14
- package/src/a2ui/catalogue.ts +140 -103
- package/src/a2ui/views.tsx +5 -2
- package/src/components/alert.tsx +1 -1
- package/src/components/badge.tsx +1 -1
- package/src/components/button.tsx +1 -1
- package/src/components/chart/chart.tsx +72 -25
- package/src/components/chart/container.tsx +24 -39
- package/src/components/chart/index.tsx +4 -2
- package/src/components/chart/nivo-charts.tsx +41 -13
- package/src/components/chart/nivo-lazy.tsx +52 -0
- package/src/components/chart/recharts-charts.tsx +98 -3
- package/src/components/chart/recharts-lazy.tsx +72 -0
- package/src/components/chart/recharts-parts.tsx +34 -0
- package/src/components/chart/tokens.ts +1 -1
- package/src/components/chart/types.ts +14 -0
- package/src/components/chip.tsx +1 -1
- package/src/components/combobox.tsx +2 -2
- package/src/components/data-table/export.ts +18 -2
- package/src/components/data-table/features.ts +77 -45
- package/src/components/data-table/parts.tsx +15 -0
- package/src/components/data-table/use-data-table.ts +7 -2
- package/src/components/data-table/use-server-source.ts +17 -4
- package/src/components/date-field.tsx +1 -1
- package/src/components/error-banner.tsx +1 -1
- package/src/components/field.tsx +2 -2
- package/src/components/form.tsx +2 -2
- package/src/components/input.tsx +1 -1
- package/src/components/label.tsx +1 -1
- package/src/components/markdown.tsx +5 -4
- package/src/components/sheet.tsx +2 -2
- package/src/components/sortable-list.tsx +2 -2
- package/src/components/textarea.tsx +1 -1
- package/src/components/toast.tsx +1 -1
- package/src/entries/a2ui.ts +11 -0
- package/src/entries/chart.ts +10 -0
- package/src/entries/core.ts +91 -0
- package/src/entries/data-table.ts +9 -0
- package/src/entries/form.ts +24 -0
- package/src/entries/markdown.ts +9 -0
- package/src/entries/sortable-list.ts +13 -0
- package/src/index.ts +32 -98
- package/src/lib/shakeable.ts +33 -0
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1,942 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { shakeable } from "../lib/shakeable.js";
|
|
3
|
+
import { AlertView, BadgeView, ButtonLinkView, ButtonView, CardView, ChartView, CheckboxView, ColumnView, DataTableView, DateFieldView, DividerView, EmptyStateView, ImageView, LinkView, MarkdownView, ProgressViewComponent, RadioGroupView, RowView, SectionCardView, SelectView, SpacerView, StatusDotView, SwitchView, TabsView, TextAreaView, TextFieldView, TextView } from "./views.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
//#region src/a2ui/catalogue.ts
|
|
6
|
+
/**
|
|
7
|
+
* The A2UI catalogue, bound to cortena-ui.
|
|
8
|
+
*
|
|
9
|
+
* A2UI's safety property is that an agent may only choose from a catalogue the
|
|
10
|
+
* host controls: it cannot emit markup, styles or script, only a component name
|
|
11
|
+
* and properties the host validates. This file is that catalogue. Each entry
|
|
12
|
+
* declares
|
|
13
|
+
*
|
|
14
|
+
* - the A2UI component name an agent writes,
|
|
15
|
+
* - a zod schema for its **resolved** properties (bindings already read),
|
|
16
|
+
* - the event names it can raise,
|
|
17
|
+
* - whether it takes children,
|
|
18
|
+
* - a self-contained example, which is both the doc's sample and a fixture,
|
|
19
|
+
* - the cortena-ui view that draws it.
|
|
20
|
+
*
|
|
21
|
+
* The vocabulary therefore grows with the package rather than with a parser:
|
|
22
|
+
* adding a component here adds it to what every agent can draw, and
|
|
23
|
+
* `catalogue-doc.ts` regenerates the prompt section from the same object, so
|
|
24
|
+
* prompt and renderer cannot drift (DESIGN-34).
|
|
25
|
+
*
|
|
26
|
+
* Schemas describe resolved values because the renderer resolves `{ path }`
|
|
27
|
+
* bindings, unwraps literals and normalises actions before validating. A view
|
|
28
|
+
* therefore never receives an unchecked value, and a property an agent got
|
|
29
|
+
* wrong produces an error card naming the property rather than a blank area.
|
|
30
|
+
*/
|
|
31
|
+
/** Keeps each entry's props type tied to its view without widening the record. */
|
|
32
|
+
function entry(definition) {
|
|
33
|
+
return definition;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A resolved action.
|
|
37
|
+
*
|
|
38
|
+
* On the wire an agent writes A2UI v0.9's `{ event: { name, context } }`, the
|
|
39
|
+
* bare `{ name, context }`, or just the name as a string; the renderer
|
|
40
|
+
* normalises all three to this before validation.
|
|
41
|
+
*/
|
|
42
|
+
const Action = /* @__PURE__ */ shakeable(() => z.object({
|
|
43
|
+
name: z.string().describe("Event name sent back to the agent."),
|
|
44
|
+
context: z.record(z.string(), z.unknown()).optional().describe("Extra values merged into the action payload.")
|
|
45
|
+
}).describe("An action reported to the agent when the user interacts."));
|
|
46
|
+
const Option = /* @__PURE__ */ shakeable(() => z.object({
|
|
47
|
+
value: z.string().describe("Value written to the data model."),
|
|
48
|
+
label: z.string().optional().describe("Text shown to the user; defaults to the value."),
|
|
49
|
+
disabled: z.boolean().optional()
|
|
50
|
+
}));
|
|
51
|
+
const gap = /* @__PURE__ */ shakeable(() => z.union([
|
|
52
|
+
z.literal(0),
|
|
53
|
+
z.literal(1),
|
|
54
|
+
z.literal(2),
|
|
55
|
+
z.literal(3),
|
|
56
|
+
z.literal(4),
|
|
57
|
+
z.literal(6),
|
|
58
|
+
z.literal(8)
|
|
59
|
+
]).describe("Spacing step between children."));
|
|
60
|
+
const padding = /* @__PURE__ */ shakeable(() => z.union([
|
|
61
|
+
z.literal(0),
|
|
62
|
+
z.literal(1),
|
|
63
|
+
z.literal(2),
|
|
64
|
+
z.literal(3),
|
|
65
|
+
z.literal(4),
|
|
66
|
+
z.literal(6),
|
|
67
|
+
z.literal(8)
|
|
68
|
+
]).describe("Inner padding step."));
|
|
69
|
+
const alignment = /* @__PURE__ */ shakeable(() => z.enum([
|
|
70
|
+
"start",
|
|
71
|
+
"center",
|
|
72
|
+
"end",
|
|
73
|
+
"stretch",
|
|
74
|
+
"baseline"
|
|
75
|
+
]).describe("Cross-axis alignment."));
|
|
76
|
+
const justification = /* @__PURE__ */ shakeable(() => z.enum([
|
|
77
|
+
"start",
|
|
78
|
+
"center",
|
|
79
|
+
"end",
|
|
80
|
+
"between"
|
|
81
|
+
]).describe("Main-axis distribution."));
|
|
82
|
+
const fieldChrome = /* @__PURE__ */ shakeable(() => ({
|
|
83
|
+
label: z.string().optional().describe("Field label."),
|
|
84
|
+
description: z.string().optional().describe("Helper text under the control."),
|
|
85
|
+
error: z.string().optional().describe("Validation message; also marks the field invalid."),
|
|
86
|
+
disabled: z.boolean().optional()
|
|
87
|
+
}));
|
|
88
|
+
const buttonVariant = /* @__PURE__ */ shakeable(() => z.enum([
|
|
89
|
+
"primary",
|
|
90
|
+
"secondary",
|
|
91
|
+
"outline",
|
|
92
|
+
"ghost",
|
|
93
|
+
"soft",
|
|
94
|
+
"destructive",
|
|
95
|
+
"link"
|
|
96
|
+
]).describe("Visual weight."));
|
|
97
|
+
const buttonSize = /* @__PURE__ */ shakeable(() => z.enum([
|
|
98
|
+
"sm",
|
|
99
|
+
"md",
|
|
100
|
+
"lg"
|
|
101
|
+
]).describe("Control size."));
|
|
102
|
+
/**
|
|
103
|
+
* Root-relative means one slash and then a path. `//evil.example/x` is
|
|
104
|
+
* protocol-relative — the browser resolves it against the page's scheme and
|
|
105
|
+
* goes off-origin — and `/\evil.example` is the same trick, because browsers
|
|
106
|
+
* treat a backslash after the leading slash as a second slash.
|
|
107
|
+
*/
|
|
108
|
+
const rootRelative = (value) => value.startsWith("/") && value[1] !== "/" && value[1] !== "\\";
|
|
109
|
+
/**
|
|
110
|
+
* A URL an agent may point at.
|
|
111
|
+
*
|
|
112
|
+
* Restricted by scheme rather than sanitised after the fact: `javascript:` and
|
|
113
|
+
* friends never reach the DOM because they never pass validation, so the
|
|
114
|
+
* component gets an error card instead.
|
|
115
|
+
*/
|
|
116
|
+
const httpUrl = /* @__PURE__ */ shakeable(() => z.string().refine((value) => /^https?:\/\//i.test(value) || rootRelative(value) || value.startsWith("#"), "Must be an http(s), root-relative or fragment URL.").describe("Destination URL (http, https, root-relative or fragment)."));
|
|
117
|
+
const imageUrl = /* @__PURE__ */ shakeable(() => z.string().refine((value) => /^https?:\/\//i.test(value) || /^data:image\//i.test(value) || rootRelative(value), "Must be an http(s), root-relative or data:image URL.").describe("Image URL (http, https, root-relative or data:image)."));
|
|
118
|
+
/** Every chart type the Chart composite draws, Recharts and Nivo alike. */
|
|
119
|
+
const chartType = /* @__PURE__ */ shakeable(() => z.enum([
|
|
120
|
+
"bar",
|
|
121
|
+
"line",
|
|
122
|
+
"area",
|
|
123
|
+
"pie",
|
|
124
|
+
"donut",
|
|
125
|
+
"scatter",
|
|
126
|
+
"scatterplot",
|
|
127
|
+
"radar",
|
|
128
|
+
"funnel",
|
|
129
|
+
"heatmap",
|
|
130
|
+
"calendar",
|
|
131
|
+
"treemap",
|
|
132
|
+
"sunburst"
|
|
133
|
+
]).describe("Chart type; the package picks Recharts or Nivo for it."));
|
|
134
|
+
/**
|
|
135
|
+
* A table's rows, or a handle to them.
|
|
136
|
+
*
|
|
137
|
+
* The server form is the point of `04-data-tables.md` in an agent context: the
|
|
138
|
+
* agent calls a tool, gets back a `sourceId`, and passes that. The host resolves
|
|
139
|
+
* it through `resolveDataSource`, so search, sort and paging stay on the backend
|
|
140
|
+
* and a large result never travels through the model.
|
|
141
|
+
*/
|
|
142
|
+
const tableSource = /* @__PURE__ */ shakeable(() => z.union([z.object({
|
|
143
|
+
kind: z.literal("client"),
|
|
144
|
+
rows: z.array(z.record(z.string(), z.unknown())).describe("The rows, inline.")
|
|
145
|
+
}), z.object({
|
|
146
|
+
kind: z.literal("server"),
|
|
147
|
+
sourceId: z.string().describe("Handle obtained from a tool; the host resolves it to a server source.")
|
|
148
|
+
})]).describe("Where the table's rows come from."));
|
|
149
|
+
const layout = /* @__PURE__ */ shakeable(() => ({
|
|
150
|
+
Column: entry({
|
|
151
|
+
name: "Column",
|
|
152
|
+
group: "layout",
|
|
153
|
+
summary: "Stacks its children vertically.",
|
|
154
|
+
props: z.object({
|
|
155
|
+
gap: gap.optional(),
|
|
156
|
+
padding: padding.optional(),
|
|
157
|
+
align: alignment.optional(),
|
|
158
|
+
justify: justification.optional()
|
|
159
|
+
}),
|
|
160
|
+
events: [],
|
|
161
|
+
children: "many",
|
|
162
|
+
example: { components: [
|
|
163
|
+
{
|
|
164
|
+
id: "col",
|
|
165
|
+
component: "Column",
|
|
166
|
+
gap: 3,
|
|
167
|
+
children: ["col-a", "col-b"]
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
id: "col-a",
|
|
171
|
+
component: "Text",
|
|
172
|
+
text: "First",
|
|
173
|
+
role: "body"
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
id: "col-b",
|
|
177
|
+
component: "Text",
|
|
178
|
+
text: "Second",
|
|
179
|
+
role: "body"
|
|
180
|
+
}
|
|
181
|
+
] },
|
|
182
|
+
view: ColumnView
|
|
183
|
+
}),
|
|
184
|
+
Row: entry({
|
|
185
|
+
name: "Row",
|
|
186
|
+
group: "layout",
|
|
187
|
+
summary: "Lays its children out horizontally, wrapping by default.",
|
|
188
|
+
props: z.object({
|
|
189
|
+
gap: gap.optional(),
|
|
190
|
+
padding: padding.optional(),
|
|
191
|
+
align: alignment.optional(),
|
|
192
|
+
justify: justification.optional(),
|
|
193
|
+
wrap: z.boolean().optional().describe("Set false to keep one line.")
|
|
194
|
+
}),
|
|
195
|
+
events: [],
|
|
196
|
+
children: "many",
|
|
197
|
+
example: { components: [
|
|
198
|
+
{
|
|
199
|
+
id: "row",
|
|
200
|
+
component: "Row",
|
|
201
|
+
gap: 2,
|
|
202
|
+
children: ["row-a", "row-b"]
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
id: "row-a",
|
|
206
|
+
component: "Badge",
|
|
207
|
+
label: "Open",
|
|
208
|
+
variant: "info"
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
id: "row-b",
|
|
212
|
+
component: "Badge",
|
|
213
|
+
label: "3 days",
|
|
214
|
+
variant: "neutral"
|
|
215
|
+
}
|
|
216
|
+
] },
|
|
217
|
+
view: RowView
|
|
218
|
+
}),
|
|
219
|
+
Card: entry({
|
|
220
|
+
name: "Card",
|
|
221
|
+
group: "layout",
|
|
222
|
+
summary: "A bordered surface grouping related content.",
|
|
223
|
+
props: z.object({
|
|
224
|
+
accent: z.boolean().optional().describe("Draw the border in the ring colour."),
|
|
225
|
+
flush: z.boolean().optional().describe("Remove the body padding.")
|
|
226
|
+
}),
|
|
227
|
+
events: [],
|
|
228
|
+
children: "many",
|
|
229
|
+
example: { components: [{
|
|
230
|
+
id: "card",
|
|
231
|
+
component: "Card",
|
|
232
|
+
children: ["card-text"]
|
|
233
|
+
}, {
|
|
234
|
+
id: "card-text",
|
|
235
|
+
component: "Text",
|
|
236
|
+
text: "Inside a card.",
|
|
237
|
+
role: "body"
|
|
238
|
+
}] },
|
|
239
|
+
view: CardView
|
|
240
|
+
}),
|
|
241
|
+
SectionCard: entry({
|
|
242
|
+
name: "SectionCard",
|
|
243
|
+
group: "layout",
|
|
244
|
+
summary: "A card with a title and description header above its children.",
|
|
245
|
+
props: z.object({
|
|
246
|
+
title: z.string().describe("Header title."),
|
|
247
|
+
description: z.string().optional().describe("Header description."),
|
|
248
|
+
flush: z.boolean().optional()
|
|
249
|
+
}),
|
|
250
|
+
events: [],
|
|
251
|
+
children: "many",
|
|
252
|
+
example: { components: [{
|
|
253
|
+
id: "section",
|
|
254
|
+
component: "SectionCard",
|
|
255
|
+
title: "Pipeline",
|
|
256
|
+
description: "Deals closing this quarter.",
|
|
257
|
+
children: ["section-text"]
|
|
258
|
+
}, {
|
|
259
|
+
id: "section-text",
|
|
260
|
+
component: "Text",
|
|
261
|
+
text: "Twelve open deals.",
|
|
262
|
+
role: "body"
|
|
263
|
+
}] },
|
|
264
|
+
view: SectionCardView
|
|
265
|
+
}),
|
|
266
|
+
Divider: entry({
|
|
267
|
+
name: "Divider",
|
|
268
|
+
group: "layout",
|
|
269
|
+
summary: "A hairline rule between sections.",
|
|
270
|
+
props: z.object({ orientation: z.enum(["horizontal", "vertical"]).optional() }),
|
|
271
|
+
events: [],
|
|
272
|
+
children: "none",
|
|
273
|
+
example: { components: [{
|
|
274
|
+
id: "divider",
|
|
275
|
+
component: "Divider"
|
|
276
|
+
}] },
|
|
277
|
+
view: DividerView
|
|
278
|
+
}),
|
|
279
|
+
Spacer: entry({
|
|
280
|
+
name: "Spacer",
|
|
281
|
+
group: "layout",
|
|
282
|
+
summary: "Blank vertical space where a gap is not enough.",
|
|
283
|
+
props: z.object({ size: gap.optional().describe("Height step; default 4.") }),
|
|
284
|
+
events: [],
|
|
285
|
+
children: "none",
|
|
286
|
+
example: { components: [{
|
|
287
|
+
id: "spacer",
|
|
288
|
+
component: "Spacer",
|
|
289
|
+
size: 4
|
|
290
|
+
}] },
|
|
291
|
+
view: SpacerView
|
|
292
|
+
})
|
|
293
|
+
}));
|
|
294
|
+
const text = /* @__PURE__ */ shakeable(() => ({
|
|
295
|
+
Text: entry({
|
|
296
|
+
name: "Text",
|
|
297
|
+
group: "text",
|
|
298
|
+
summary: "A run of plain text at one of the type-scale roles.",
|
|
299
|
+
props: z.object({
|
|
300
|
+
text: z.string().describe("The text to show."),
|
|
301
|
+
role: z.enum([
|
|
302
|
+
"heading",
|
|
303
|
+
"subheading",
|
|
304
|
+
"body",
|
|
305
|
+
"caption",
|
|
306
|
+
"eyebrow"
|
|
307
|
+
]).optional().describe("Type-scale role; default body."),
|
|
308
|
+
tone: z.enum([
|
|
309
|
+
"default",
|
|
310
|
+
"muted",
|
|
311
|
+
"success",
|
|
312
|
+
"warning",
|
|
313
|
+
"danger",
|
|
314
|
+
"info"
|
|
315
|
+
]).optional().describe("Semantic colour; default foreground."),
|
|
316
|
+
align: z.enum([
|
|
317
|
+
"start",
|
|
318
|
+
"center",
|
|
319
|
+
"end"
|
|
320
|
+
]).optional(),
|
|
321
|
+
mono: z.boolean().optional().describe("Render in the mono face, for ids and numbers.")
|
|
322
|
+
}),
|
|
323
|
+
events: [],
|
|
324
|
+
children: "none",
|
|
325
|
+
example: { components: [{
|
|
326
|
+
id: "heading",
|
|
327
|
+
component: "Text",
|
|
328
|
+
text: "Quarterly review",
|
|
329
|
+
role: "heading"
|
|
330
|
+
}] },
|
|
331
|
+
view: TextView
|
|
332
|
+
}),
|
|
333
|
+
Markdown: entry({
|
|
334
|
+
name: "Markdown",
|
|
335
|
+
group: "text",
|
|
336
|
+
summary: "Rich text as markdown; sanitised, with GFM tables and code blocks.",
|
|
337
|
+
props: z.object({
|
|
338
|
+
text: z.string().describe("Markdown source."),
|
|
339
|
+
compact: z.boolean().optional().describe("Tighter rhythm, for chat bubbles.")
|
|
340
|
+
}),
|
|
341
|
+
events: [],
|
|
342
|
+
children: "none",
|
|
343
|
+
example: { components: [{
|
|
344
|
+
id: "md",
|
|
345
|
+
component: "Markdown",
|
|
346
|
+
text: "**Summary**\n\n- Revenue up 12%\n- Churn flat\n",
|
|
347
|
+
compact: true
|
|
348
|
+
}] },
|
|
349
|
+
view: MarkdownView
|
|
350
|
+
})
|
|
351
|
+
}));
|
|
352
|
+
const input = /* @__PURE__ */ shakeable(() => ({
|
|
353
|
+
TextField: entry({
|
|
354
|
+
name: "TextField",
|
|
355
|
+
group: "input",
|
|
356
|
+
summary: "A single-line text input.",
|
|
357
|
+
props: z.object({
|
|
358
|
+
...fieldChrome,
|
|
359
|
+
value: z.string().optional().describe("Current value; bind it to the data model."),
|
|
360
|
+
placeholder: z.string().optional(),
|
|
361
|
+
type: z.enum([
|
|
362
|
+
"text",
|
|
363
|
+
"email",
|
|
364
|
+
"url",
|
|
365
|
+
"tel",
|
|
366
|
+
"number",
|
|
367
|
+
"password",
|
|
368
|
+
"search"
|
|
369
|
+
]).optional().describe("Input type; default text."),
|
|
370
|
+
required: z.boolean().optional(),
|
|
371
|
+
onChange: Action.optional().describe("Raised after the user stops typing.")
|
|
372
|
+
}),
|
|
373
|
+
events: ["change"],
|
|
374
|
+
children: "none",
|
|
375
|
+
example: {
|
|
376
|
+
data: { form: { name: "" } },
|
|
377
|
+
components: [{
|
|
378
|
+
id: "name",
|
|
379
|
+
component: "TextField",
|
|
380
|
+
label: "Full name",
|
|
381
|
+
value: { path: "/form/name" },
|
|
382
|
+
placeholder: "Ada Lovelace",
|
|
383
|
+
onChange: { event: { name: "nameChanged" } }
|
|
384
|
+
}]
|
|
385
|
+
},
|
|
386
|
+
view: TextFieldView
|
|
387
|
+
}),
|
|
388
|
+
TextArea: entry({
|
|
389
|
+
name: "TextArea",
|
|
390
|
+
group: "input",
|
|
391
|
+
summary: "A multi-line text input.",
|
|
392
|
+
props: z.object({
|
|
393
|
+
...fieldChrome,
|
|
394
|
+
value: z.string().optional(),
|
|
395
|
+
placeholder: z.string().optional(),
|
|
396
|
+
rows: z.number().int().min(2).max(20).optional().describe("Visible rows; default 4."),
|
|
397
|
+
autoGrow: z.boolean().optional().describe("Grow with the content."),
|
|
398
|
+
onChange: Action.optional()
|
|
399
|
+
}),
|
|
400
|
+
events: ["change"],
|
|
401
|
+
children: "none",
|
|
402
|
+
example: {
|
|
403
|
+
data: { form: { notes: "" } },
|
|
404
|
+
components: [{
|
|
405
|
+
id: "notes",
|
|
406
|
+
component: "TextArea",
|
|
407
|
+
label: "Notes",
|
|
408
|
+
value: { path: "/form/notes" },
|
|
409
|
+
rows: 3,
|
|
410
|
+
onChange: { event: { name: "notesChanged" } }
|
|
411
|
+
}]
|
|
412
|
+
},
|
|
413
|
+
view: TextAreaView
|
|
414
|
+
}),
|
|
415
|
+
Select: entry({
|
|
416
|
+
name: "Select",
|
|
417
|
+
group: "input",
|
|
418
|
+
summary: "A dropdown offering one of a fixed list of options.",
|
|
419
|
+
props: z.object({
|
|
420
|
+
...fieldChrome,
|
|
421
|
+
value: z.string().optional(),
|
|
422
|
+
placeholder: z.string().optional(),
|
|
423
|
+
options: z.array(Option).min(1).describe("The options to choose from."),
|
|
424
|
+
onChange: Action.optional()
|
|
425
|
+
}),
|
|
426
|
+
events: ["change"],
|
|
427
|
+
children: "none",
|
|
428
|
+
example: {
|
|
429
|
+
data: { form: { region: "ap-south-1" } },
|
|
430
|
+
components: [{
|
|
431
|
+
id: "region",
|
|
432
|
+
component: "Select",
|
|
433
|
+
label: "Region",
|
|
434
|
+
value: { path: "/form/region" },
|
|
435
|
+
options: [{
|
|
436
|
+
value: "ap-south-1",
|
|
437
|
+
label: "Mumbai"
|
|
438
|
+
}, {
|
|
439
|
+
value: "eu-west-1",
|
|
440
|
+
label: "Ireland"
|
|
441
|
+
}],
|
|
442
|
+
onChange: { event: { name: "regionChanged" } }
|
|
443
|
+
}]
|
|
444
|
+
},
|
|
445
|
+
view: SelectView
|
|
446
|
+
}),
|
|
447
|
+
Checkbox: entry({
|
|
448
|
+
name: "Checkbox",
|
|
449
|
+
group: "input",
|
|
450
|
+
summary: "A single on/off box with a label.",
|
|
451
|
+
props: z.object({
|
|
452
|
+
label: z.string().optional().describe("Text beside the box."),
|
|
453
|
+
description: z.string().optional(),
|
|
454
|
+
disabled: z.boolean().optional(),
|
|
455
|
+
checked: z.boolean().optional(),
|
|
456
|
+
onChange: Action.optional()
|
|
457
|
+
}),
|
|
458
|
+
events: ["change"],
|
|
459
|
+
children: "none",
|
|
460
|
+
example: {
|
|
461
|
+
data: { form: { terms: false } },
|
|
462
|
+
components: [{
|
|
463
|
+
id: "terms",
|
|
464
|
+
component: "Checkbox",
|
|
465
|
+
label: "I accept the terms",
|
|
466
|
+
checked: { path: "/form/terms" },
|
|
467
|
+
onChange: { event: { name: "termsChanged" } }
|
|
468
|
+
}]
|
|
469
|
+
},
|
|
470
|
+
view: CheckboxView
|
|
471
|
+
}),
|
|
472
|
+
Switch: entry({
|
|
473
|
+
name: "Switch",
|
|
474
|
+
group: "input",
|
|
475
|
+
summary: "A toggle for a setting that takes effect immediately.",
|
|
476
|
+
props: z.object({
|
|
477
|
+
label: z.string().optional(),
|
|
478
|
+
description: z.string().optional(),
|
|
479
|
+
disabled: z.boolean().optional(),
|
|
480
|
+
checked: z.boolean().optional(),
|
|
481
|
+
onChange: Action.optional()
|
|
482
|
+
}),
|
|
483
|
+
events: ["change"],
|
|
484
|
+
children: "none",
|
|
485
|
+
example: {
|
|
486
|
+
data: { form: { alerts: true } },
|
|
487
|
+
components: [{
|
|
488
|
+
id: "alerts",
|
|
489
|
+
component: "Switch",
|
|
490
|
+
label: "Email alerts",
|
|
491
|
+
checked: { path: "/form/alerts" },
|
|
492
|
+
onChange: { event: { name: "alertsChanged" } }
|
|
493
|
+
}]
|
|
494
|
+
},
|
|
495
|
+
view: SwitchView
|
|
496
|
+
}),
|
|
497
|
+
RadioGroup: entry({
|
|
498
|
+
name: "RadioGroup",
|
|
499
|
+
group: "input",
|
|
500
|
+
summary: "One choice from a short visible list.",
|
|
501
|
+
props: z.object({
|
|
502
|
+
label: z.string().optional(),
|
|
503
|
+
description: z.string().optional(),
|
|
504
|
+
disabled: z.boolean().optional(),
|
|
505
|
+
value: z.string().optional(),
|
|
506
|
+
options: z.array(Option).min(2).describe("Two or more choices."),
|
|
507
|
+
onChange: Action.optional()
|
|
508
|
+
}),
|
|
509
|
+
events: ["change"],
|
|
510
|
+
children: "none",
|
|
511
|
+
example: {
|
|
512
|
+
data: { form: { plan: "pro" } },
|
|
513
|
+
components: [{
|
|
514
|
+
id: "plan",
|
|
515
|
+
component: "RadioGroup",
|
|
516
|
+
label: "Plan",
|
|
517
|
+
value: { path: "/form/plan" },
|
|
518
|
+
options: [{
|
|
519
|
+
value: "free",
|
|
520
|
+
label: "Free"
|
|
521
|
+
}, {
|
|
522
|
+
value: "pro",
|
|
523
|
+
label: "Pro"
|
|
524
|
+
}],
|
|
525
|
+
onChange: { event: { name: "planChanged" } }
|
|
526
|
+
}]
|
|
527
|
+
},
|
|
528
|
+
view: RadioGroupView
|
|
529
|
+
}),
|
|
530
|
+
DateField: entry({
|
|
531
|
+
name: "DateField",
|
|
532
|
+
group: "input",
|
|
533
|
+
summary: "A date, typed or picked from a calendar. ISO yyyy-mm-dd on the wire.",
|
|
534
|
+
props: z.object({
|
|
535
|
+
...fieldChrome,
|
|
536
|
+
value: z.string().optional().describe("ISO date, yyyy-mm-dd."),
|
|
537
|
+
min: z.string().optional().describe("Earliest selectable ISO date."),
|
|
538
|
+
max: z.string().optional().describe("Latest selectable ISO date."),
|
|
539
|
+
onChange: Action.optional()
|
|
540
|
+
}),
|
|
541
|
+
events: ["change"],
|
|
542
|
+
children: "none",
|
|
543
|
+
example: {
|
|
544
|
+
data: { form: { start: "2026-09-01" } },
|
|
545
|
+
components: [{
|
|
546
|
+
id: "start",
|
|
547
|
+
component: "DateField",
|
|
548
|
+
label: "Start date",
|
|
549
|
+
value: { path: "/form/start" },
|
|
550
|
+
onChange: { event: { name: "startChanged" } }
|
|
551
|
+
}]
|
|
552
|
+
},
|
|
553
|
+
view: DateFieldView
|
|
554
|
+
}),
|
|
555
|
+
Button: entry({
|
|
556
|
+
name: "Button",
|
|
557
|
+
group: "input",
|
|
558
|
+
summary: "A button. Set submit to report the whole data model with the action.",
|
|
559
|
+
props: z.object({
|
|
560
|
+
label: z.string().describe("Button text."),
|
|
561
|
+
variant: buttonVariant.optional().describe("Visual weight; default primary."),
|
|
562
|
+
size: buttonSize.optional(),
|
|
563
|
+
disabled: z.boolean().optional(),
|
|
564
|
+
submit: z.boolean().optional().describe("Send the surface data model as the action payload; use for form submits."),
|
|
565
|
+
onPress: Action.optional().describe("Raised when the user presses the button.")
|
|
566
|
+
}),
|
|
567
|
+
events: ["press", "submit"],
|
|
568
|
+
children: "none",
|
|
569
|
+
example: { components: [{
|
|
570
|
+
id: "save",
|
|
571
|
+
component: "Button",
|
|
572
|
+
label: "Save",
|
|
573
|
+
variant: "primary",
|
|
574
|
+
submit: true,
|
|
575
|
+
onPress: { event: { name: "saveProfile" } }
|
|
576
|
+
}] },
|
|
577
|
+
view: ButtonView
|
|
578
|
+
}),
|
|
579
|
+
ButtonLink: entry({
|
|
580
|
+
name: "ButtonLink",
|
|
581
|
+
group: "input",
|
|
582
|
+
summary: "A link that looks like a button. Navigates; raises no action.",
|
|
583
|
+
props: z.object({
|
|
584
|
+
label: z.string(),
|
|
585
|
+
href: httpUrl,
|
|
586
|
+
variant: buttonVariant.optional().describe("Visual weight; default secondary."),
|
|
587
|
+
size: buttonSize.optional(),
|
|
588
|
+
target: z.enum(["_self", "_blank"]).optional()
|
|
589
|
+
}),
|
|
590
|
+
events: [],
|
|
591
|
+
children: "none",
|
|
592
|
+
example: { components: [{
|
|
593
|
+
id: "docs",
|
|
594
|
+
component: "ButtonLink",
|
|
595
|
+
label: "Open runbook",
|
|
596
|
+
href: "https://example.com/runbook",
|
|
597
|
+
target: "_blank"
|
|
598
|
+
}] },
|
|
599
|
+
view: ButtonLinkView
|
|
600
|
+
})
|
|
601
|
+
}));
|
|
602
|
+
const feedback = /* @__PURE__ */ shakeable(() => ({
|
|
603
|
+
Badge: entry({
|
|
604
|
+
name: "Badge",
|
|
605
|
+
group: "feedback",
|
|
606
|
+
summary: "A small status label.",
|
|
607
|
+
props: z.object({
|
|
608
|
+
label: z.string(),
|
|
609
|
+
variant: z.enum([
|
|
610
|
+
"default",
|
|
611
|
+
"success",
|
|
612
|
+
"warning",
|
|
613
|
+
"danger",
|
|
614
|
+
"info",
|
|
615
|
+
"neutral",
|
|
616
|
+
"outline"
|
|
617
|
+
]).optional()
|
|
618
|
+
}),
|
|
619
|
+
events: [],
|
|
620
|
+
children: "none",
|
|
621
|
+
example: { components: [{
|
|
622
|
+
id: "badge",
|
|
623
|
+
component: "Badge",
|
|
624
|
+
label: "Active",
|
|
625
|
+
variant: "success"
|
|
626
|
+
}] },
|
|
627
|
+
view: BadgeView
|
|
628
|
+
}),
|
|
629
|
+
Alert: entry({
|
|
630
|
+
name: "Alert",
|
|
631
|
+
group: "feedback",
|
|
632
|
+
summary: "A callout carrying a short message the user should notice.",
|
|
633
|
+
props: z.object({
|
|
634
|
+
title: z.string().optional(),
|
|
635
|
+
description: z.string().optional(),
|
|
636
|
+
variant: z.enum([
|
|
637
|
+
"default",
|
|
638
|
+
"success",
|
|
639
|
+
"warn",
|
|
640
|
+
"danger",
|
|
641
|
+
"info"
|
|
642
|
+
]).optional()
|
|
643
|
+
}),
|
|
644
|
+
events: [],
|
|
645
|
+
children: "none",
|
|
646
|
+
example: { components: [{
|
|
647
|
+
id: "alert",
|
|
648
|
+
component: "Alert",
|
|
649
|
+
variant: "warn",
|
|
650
|
+
title: "Quota at 90%",
|
|
651
|
+
description: "Upgrade before the end of the month."
|
|
652
|
+
}] },
|
|
653
|
+
view: AlertView
|
|
654
|
+
}),
|
|
655
|
+
Progress: entry({
|
|
656
|
+
name: "Progress",
|
|
657
|
+
group: "feedback",
|
|
658
|
+
summary: "A determinate or indeterminate progress bar.",
|
|
659
|
+
props: z.object({
|
|
660
|
+
value: z.number().nullable().optional().describe("Null renders the indeterminate bar."),
|
|
661
|
+
max: z.number().optional().describe("Maximum; default 100."),
|
|
662
|
+
label: z.string().optional(),
|
|
663
|
+
showValue: z.boolean().optional().describe("Set false to hide the numeric readout.")
|
|
664
|
+
}),
|
|
665
|
+
events: [],
|
|
666
|
+
children: "none",
|
|
667
|
+
example: { components: [{
|
|
668
|
+
id: "progress",
|
|
669
|
+
component: "Progress",
|
|
670
|
+
label: "Indexing",
|
|
671
|
+
value: 64
|
|
672
|
+
}] },
|
|
673
|
+
view: ProgressViewComponent
|
|
674
|
+
}),
|
|
675
|
+
StatusDot: entry({
|
|
676
|
+
name: "StatusDot",
|
|
677
|
+
group: "feedback",
|
|
678
|
+
summary: "A coloured dot with a caption, for live status.",
|
|
679
|
+
props: z.object({
|
|
680
|
+
label: z.string().optional(),
|
|
681
|
+
tone: z.enum([
|
|
682
|
+
"accent",
|
|
683
|
+
"success",
|
|
684
|
+
"warning",
|
|
685
|
+
"danger",
|
|
686
|
+
"info",
|
|
687
|
+
"neutral"
|
|
688
|
+
]).optional(),
|
|
689
|
+
live: z.boolean().optional().describe("Add a pulsing halo for an active state.")
|
|
690
|
+
}),
|
|
691
|
+
events: [],
|
|
692
|
+
children: "none",
|
|
693
|
+
example: { components: [{
|
|
694
|
+
id: "status",
|
|
695
|
+
component: "StatusDot",
|
|
696
|
+
label: "Running",
|
|
697
|
+
tone: "success",
|
|
698
|
+
live: true
|
|
699
|
+
}] },
|
|
700
|
+
view: StatusDotView
|
|
701
|
+
}),
|
|
702
|
+
EmptyState: entry({
|
|
703
|
+
name: "EmptyState",
|
|
704
|
+
group: "feedback",
|
|
705
|
+
summary: "The 'nothing here' surface; children become its actions.",
|
|
706
|
+
props: z.object({
|
|
707
|
+
title: z.string(),
|
|
708
|
+
description: z.string().optional(),
|
|
709
|
+
size: z.enum(["default", "compact"]).optional()
|
|
710
|
+
}),
|
|
711
|
+
events: [],
|
|
712
|
+
children: "many",
|
|
713
|
+
example: { components: [{
|
|
714
|
+
id: "empty",
|
|
715
|
+
component: "EmptyState",
|
|
716
|
+
title: "No results",
|
|
717
|
+
description: "Try a wider date range.",
|
|
718
|
+
children: ["empty-action"]
|
|
719
|
+
}, {
|
|
720
|
+
id: "empty-action",
|
|
721
|
+
component: "Button",
|
|
722
|
+
label: "Reset filters",
|
|
723
|
+
variant: "secondary",
|
|
724
|
+
onPress: { event: { name: "resetFilters" } }
|
|
725
|
+
}] },
|
|
726
|
+
view: EmptyStateView
|
|
727
|
+
})
|
|
728
|
+
}));
|
|
729
|
+
const data = /* @__PURE__ */ shakeable(() => ({
|
|
730
|
+
DataTable: entry({
|
|
731
|
+
name: "DataTable",
|
|
732
|
+
group: "data",
|
|
733
|
+
summary: "A sortable, searchable table. Pass rows inline, or a server sourceId obtained from a tool.",
|
|
734
|
+
props: z.object({
|
|
735
|
+
columns: z.array(z.object({
|
|
736
|
+
id: z.string().describe("Row property this column reads."),
|
|
737
|
+
label: z.string().optional().describe("Header text; defaults to the id."),
|
|
738
|
+
align: z.enum([
|
|
739
|
+
"start",
|
|
740
|
+
"center",
|
|
741
|
+
"end"
|
|
742
|
+
]).optional(),
|
|
743
|
+
filter: z.enum(["faceted", "text"]).optional().describe("Add a toolbar filter for this column."),
|
|
744
|
+
width: z.number().optional()
|
|
745
|
+
})).min(1),
|
|
746
|
+
dataSource: tableSource,
|
|
747
|
+
pageSize: z.number().int().min(1).max(200).optional().describe("Rows per page; default 10."),
|
|
748
|
+
density: z.enum(["default", "compact"]).optional(),
|
|
749
|
+
searchPlaceholder: z.string().optional(),
|
|
750
|
+
emptyMessage: z.string().optional(),
|
|
751
|
+
maxHeight: z.number().optional().describe("Scrolling body height in px."),
|
|
752
|
+
onRowClick: Action.optional().describe("Raised with the clicked row.")
|
|
753
|
+
}),
|
|
754
|
+
events: ["rowClick"],
|
|
755
|
+
children: "none",
|
|
756
|
+
example: { components: [{
|
|
757
|
+
id: "table",
|
|
758
|
+
component: "DataTable",
|
|
759
|
+
columns: [
|
|
760
|
+
{
|
|
761
|
+
id: "name",
|
|
762
|
+
label: "Name"
|
|
763
|
+
},
|
|
764
|
+
{
|
|
765
|
+
id: "status",
|
|
766
|
+
label: "Status",
|
|
767
|
+
filter: "faceted"
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
id: "deals",
|
|
771
|
+
label: "Deals",
|
|
772
|
+
align: "end"
|
|
773
|
+
}
|
|
774
|
+
],
|
|
775
|
+
dataSource: {
|
|
776
|
+
kind: "client",
|
|
777
|
+
rows: [{
|
|
778
|
+
name: "Ada Lovelace",
|
|
779
|
+
status: "active",
|
|
780
|
+
deals: 12
|
|
781
|
+
}, {
|
|
782
|
+
name: "Grace Hopper",
|
|
783
|
+
status: "invited",
|
|
784
|
+
deals: 4
|
|
785
|
+
}]
|
|
786
|
+
},
|
|
787
|
+
onRowClick: { event: { name: "openContact" } }
|
|
788
|
+
}] },
|
|
789
|
+
view: DataTableView
|
|
790
|
+
}),
|
|
791
|
+
Chart: entry({
|
|
792
|
+
name: "Chart",
|
|
793
|
+
group: "data",
|
|
794
|
+
summary: "Any chart the package draws: bar, line, area, pie, donut, scatter, radar, funnel, heatmap, calendar, treemap, sunburst.",
|
|
795
|
+
props: z.object({
|
|
796
|
+
type: chartType,
|
|
797
|
+
data: z.unknown().describe("Rows [{category, series…}] for bar/radar; series [{id, data:[{x,y}]}] for line/area/scatter/heatmap; slices [{id,value}] for pie/donut/funnel; days [{day,value}] for calendar; a tree {id, children} for treemap/sunburst."),
|
|
798
|
+
title: z.string().optional().describe("Caption above the chart."),
|
|
799
|
+
height: z.number().int().min(120).max(800).optional().describe("Drawing height in px."),
|
|
800
|
+
stacked: z.boolean().optional(),
|
|
801
|
+
legend: z.boolean().optional(),
|
|
802
|
+
grid: z.boolean().optional(),
|
|
803
|
+
scale: z.enum(["sequential", "diverging"]).optional().describe("Heatmap and calendar scale."),
|
|
804
|
+
indexBy: z.string().optional().describe("Category key for row data."),
|
|
805
|
+
keys: z.array(z.string()).optional().describe("Series keys for row data."),
|
|
806
|
+
from: z.string().optional().describe("Calendar range start, ISO date."),
|
|
807
|
+
to: z.string().optional().describe("Calendar range end, ISO date."),
|
|
808
|
+
emptyMessage: z.string().optional()
|
|
809
|
+
}),
|
|
810
|
+
events: [],
|
|
811
|
+
children: "none",
|
|
812
|
+
example: { components: [{
|
|
813
|
+
id: "chart",
|
|
814
|
+
component: "Chart",
|
|
815
|
+
type: "bar",
|
|
816
|
+
title: "Revenue by month",
|
|
817
|
+
data: [{
|
|
818
|
+
month: "Jan",
|
|
819
|
+
revenue: 42,
|
|
820
|
+
cost: 18
|
|
821
|
+
}, {
|
|
822
|
+
month: "Feb",
|
|
823
|
+
revenue: 51,
|
|
824
|
+
cost: 22
|
|
825
|
+
}]
|
|
826
|
+
}] },
|
|
827
|
+
view: ChartView
|
|
828
|
+
})
|
|
829
|
+
}));
|
|
830
|
+
const other = /* @__PURE__ */ shakeable(() => ({
|
|
831
|
+
Tabs: entry({
|
|
832
|
+
name: "Tabs",
|
|
833
|
+
group: "layout",
|
|
834
|
+
summary: "Tabbed panels; the nth child is the nth tab's panel.",
|
|
835
|
+
props: z.object({
|
|
836
|
+
tabs: z.array(z.object({
|
|
837
|
+
value: z.string(),
|
|
838
|
+
label: z.string()
|
|
839
|
+
})).min(2).describe("Tab bar, in order."),
|
|
840
|
+
value: z.string().optional().describe("Selected tab; defaults to the first."),
|
|
841
|
+
onChange: Action.optional()
|
|
842
|
+
}),
|
|
843
|
+
events: ["tabChange"],
|
|
844
|
+
children: "many",
|
|
845
|
+
example: { components: [
|
|
846
|
+
{
|
|
847
|
+
id: "tabs",
|
|
848
|
+
component: "Tabs",
|
|
849
|
+
tabs: [{
|
|
850
|
+
value: "summary",
|
|
851
|
+
label: "Summary"
|
|
852
|
+
}, {
|
|
853
|
+
value: "detail",
|
|
854
|
+
label: "Detail"
|
|
855
|
+
}],
|
|
856
|
+
children: ["tab-summary", "tab-detail"],
|
|
857
|
+
onChange: { event: { name: "tabChanged" } }
|
|
858
|
+
},
|
|
859
|
+
{
|
|
860
|
+
id: "tab-summary",
|
|
861
|
+
component: "Text",
|
|
862
|
+
text: "Two open incidents.",
|
|
863
|
+
role: "body"
|
|
864
|
+
},
|
|
865
|
+
{
|
|
866
|
+
id: "tab-detail",
|
|
867
|
+
component: "Text",
|
|
868
|
+
text: "INC-42, INC-51.",
|
|
869
|
+
role: "body"
|
|
870
|
+
}
|
|
871
|
+
] },
|
|
872
|
+
view: TabsView
|
|
873
|
+
}),
|
|
874
|
+
Image: entry({
|
|
875
|
+
name: "Image",
|
|
876
|
+
group: "text",
|
|
877
|
+
summary: "An image. Alt text is required.",
|
|
878
|
+
props: z.object({
|
|
879
|
+
src: imageUrl,
|
|
880
|
+
alt: z.string().describe("Alternative text; required."),
|
|
881
|
+
width: z.number().optional(),
|
|
882
|
+
height: z.number().optional(),
|
|
883
|
+
rounded: z.boolean().optional().describe("Set false for square corners."),
|
|
884
|
+
fit: z.enum(["cover", "contain"]).optional()
|
|
885
|
+
}),
|
|
886
|
+
events: [],
|
|
887
|
+
children: "none",
|
|
888
|
+
example: { components: [{
|
|
889
|
+
id: "image",
|
|
890
|
+
component: "Image",
|
|
891
|
+
src: "https://example.com/chart.png",
|
|
892
|
+
alt: "Revenue by month",
|
|
893
|
+
height: 160
|
|
894
|
+
}] },
|
|
895
|
+
view: ImageView
|
|
896
|
+
}),
|
|
897
|
+
Link: entry({
|
|
898
|
+
name: "Link",
|
|
899
|
+
group: "text",
|
|
900
|
+
summary: "An inline text link.",
|
|
901
|
+
props: z.object({
|
|
902
|
+
label: z.string(),
|
|
903
|
+
href: httpUrl,
|
|
904
|
+
target: z.enum(["_self", "_blank"]).optional()
|
|
905
|
+
}),
|
|
906
|
+
events: [],
|
|
907
|
+
children: "none",
|
|
908
|
+
example: { components: [{
|
|
909
|
+
id: "link",
|
|
910
|
+
component: "Link",
|
|
911
|
+
label: "View the incident",
|
|
912
|
+
href: "https://example.com/inc-42",
|
|
913
|
+
target: "_blank"
|
|
914
|
+
}] },
|
|
915
|
+
view: LinkView
|
|
916
|
+
})
|
|
917
|
+
}));
|
|
918
|
+
/**
|
|
919
|
+
* The catalogue an agent draws from, and the renderer's default.
|
|
920
|
+
*
|
|
921
|
+
* A host may narrow it (hand the renderer a subset) but should not widen it
|
|
922
|
+
* with components the prompt does not describe: an agent can only usefully
|
|
923
|
+
* emit what `catalogue-doc.ts` told it about.
|
|
924
|
+
*/
|
|
925
|
+
const defaultCatalogue = /* @__PURE__ */ shakeable(() => Object.freeze({
|
|
926
|
+
...layout,
|
|
927
|
+
...text,
|
|
928
|
+
...input,
|
|
929
|
+
...feedback,
|
|
930
|
+
...data,
|
|
931
|
+
...other
|
|
932
|
+
}));
|
|
933
|
+
/** Catalogue id an agent may echo in `createSurface.catalogId`. */
|
|
934
|
+
const A2UI_CATALOGUE_ID = "https://cortena.ai/a2ui/catalogues/cortena-ui/v1.json";
|
|
935
|
+
/** Every component name in the catalogue, sorted. */
|
|
936
|
+
function catalogueNames(catalogue = defaultCatalogue) {
|
|
937
|
+
return Object.keys(catalogue).sort();
|
|
938
|
+
}
|
|
939
|
+
//#endregion
|
|
940
|
+
export { A2UI_CATALOGUE_ID, catalogueNames, defaultCatalogue };
|
|
941
|
+
|
|
942
|
+
//# sourceMappingURL=catalogue.js.map
|