@servicetitan/json-render-react 0.2.0 → 0.3.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.
Files changed (86) hide show
  1. package/dist/catalog/context/catalog-prompt.md +229 -0
  2. package/dist/catalog/context/schema.json +56 -0
  3. package/dist/catalog/core/catalog-prompt.md +104 -90
  4. package/dist/catalog/core/schema.json +0 -1
  5. package/dist/catalog/marketing/catalog-prompt.md +104 -90
  6. package/dist/catalog/marketing/schema.json +0 -1
  7. package/dist/context/catalog/catalog-def.d.ts +50 -0
  8. package/dist/context/catalog/context-card.catalog.d.ts +19 -0
  9. package/dist/context/catalog/context-card.d.ts +8 -0
  10. package/dist/context/catalog/context-data-table.catalog.d.ts +34 -0
  11. package/dist/context/catalog/context-data-table.css.d.ts +2 -0
  12. package/dist/context/catalog/context-data-table.d.ts +6 -0
  13. package/dist/context/catalog/context-file-list.catalog.d.ts +11 -0
  14. package/dist/context/catalog/context-file-list.css.d.ts +16 -0
  15. package/dist/context/catalog/context-file-list.d.ts +6 -0
  16. package/dist/context/catalog/context-list.catalog.d.ts +48 -0
  17. package/dist/context/catalog/context-list.css.d.ts +16 -0
  18. package/dist/context/catalog/context-list.d.ts +6 -0
  19. package/dist/context/catalog/context-metric-grid.catalog.d.ts +22 -0
  20. package/dist/context/catalog/context-metric-grid.css.d.ts +13 -0
  21. package/dist/context/catalog/context-metric-grid.d.ts +6 -0
  22. package/dist/context/catalog/context-note-list.catalog.d.ts +15 -0
  23. package/dist/context/catalog/context-note-list.d.ts +6 -0
  24. package/dist/context/catalog/context-overview.catalog.d.ts +8 -0
  25. package/dist/context/catalog/context-overview.css.d.ts +2 -0
  26. package/dist/context/catalog/context-overview.d.ts +6 -0
  27. package/dist/context/catalog/context-panel.catalog.d.ts +6 -0
  28. package/dist/context/catalog/context-panel.css.d.ts +1 -0
  29. package/dist/context/catalog/context-panel.d.ts +6 -0
  30. package/dist/context/catalog/context-tabular-list.catalog.d.ts +19 -0
  31. package/dist/context/catalog/context-tabular-list.css.d.ts +17 -0
  32. package/dist/context/catalog/context-tabular-list.d.ts +6 -0
  33. package/dist/context/catalog/index.d.ts +10 -0
  34. package/dist/context/catalog/schemas.d.ts +151 -0
  35. package/dist/context/components/collapsible-card.css.d.ts +41 -0
  36. package/dist/context/components/collapsible-card.d.ts +14 -0
  37. package/dist/context/components/context-ai-summary.css.d.ts +5 -0
  38. package/dist/context/components/context-ai-summary.d.ts +4 -0
  39. package/dist/context/components/context-chip-tone.d.ts +10 -0
  40. package/dist/context/components/context-note-list.css.d.ts +10 -0
  41. package/dist/context/components/context-render-error-boundary.d.ts +21 -0
  42. package/dist/context/constants.d.ts +6 -0
  43. package/dist/context/index.d.ts +4 -0
  44. package/dist/context/validate-context-spec-deep.d.ts +9 -0
  45. package/dist/context/validate-context-spec.d.ts +11 -0
  46. package/dist/core/catalog/alert.catalog.d.ts +2 -0
  47. package/dist/core/catalog/button.catalog.d.ts +3 -0
  48. package/dist/core/catalog/card.catalog.d.ts +2 -0
  49. package/dist/core/catalog/catalog-def.d.ts +33 -19
  50. package/dist/core/catalog/checkbox.catalog.d.ts +1 -0
  51. package/dist/core/catalog/chip.catalog.d.ts +1 -0
  52. package/dist/core/catalog/flex.catalog.d.ts +13 -0
  53. package/dist/core/catalog/grid.catalog.d.ts +4 -0
  54. package/dist/core/catalog/input.catalog.d.ts +1 -0
  55. package/dist/core/catalog/link.catalog.d.ts +2 -0
  56. package/dist/core/catalog/listbox.catalog.d.ts +1 -0
  57. package/dist/core/catalog/radio-group.catalog.d.ts +1 -0
  58. package/dist/core/catalog/schemas.d.ts +33 -19
  59. package/dist/core/catalog/switch.catalog.d.ts +1 -0
  60. package/dist/core/catalog/text.catalog.d.ts +0 -8
  61. package/dist/core/catalog/textarea.catalog.d.ts +1 -0
  62. package/dist/generate.d.ts +4 -4
  63. package/dist/index.d.ts +6 -3
  64. package/dist/json-render-react.js +1820 -705
  65. package/dist/json-render-react.js.map +1 -1
  66. package/dist/marketing/catalog/catalog.d.ts +1 -1
  67. package/dist/marketing/catalog/index.d.ts +1 -1
  68. package/dist/marketing/catalog/scoped-catalogs.d.ts +4 -0
  69. package/dist/registry-utils.d.ts +1 -1
  70. package/dist/registry.d.ts +1 -0
  71. package/dist/renderers/context-spec-renderer.d.ts +6 -0
  72. package/dist/renderers/sectioned-context-renderer.css.d.ts +1 -0
  73. package/dist/renderers/sectioned-context-renderer.d.ts +36 -0
  74. package/dist/renderers/spec-renderer.d.ts +6 -1
  75. package/dist/renderers/types.d.ts +2 -1
  76. package/dist/renderers/wrap-context-registry.d.ts +3 -0
  77. package/dist/scoped-catalog.d.ts +64 -0
  78. package/dist/styles.css +1 -1
  79. package/dist/test/setup-dom.d.ts +1 -0
  80. package/dist/types.d.ts +6 -3
  81. package/package.json +4 -2
  82. package/dist/core/catalog/badge.catalog.d.ts +0 -12
  83. package/dist/core/catalog/badge.css.d.ts +0 -1
  84. package/dist/core/catalog/badge.d.ts +0 -8
  85. package/dist/marketing/catalog/teams.d.ts +0 -4
  86. package/dist/team-catalog.d.ts +0 -26
@@ -46,29 +46,28 @@ For lists where users can add/remove items (todos, carts, etc.), use pushState a
46
46
 
47
47
  IMPORTANT: State paths use RFC 6901 JSON Pointer syntax (e.g. "/todos/0/title"). Do NOT use JavaScript-style dot notation (e.g. "/todos.length" is WRONG). To generate unique IDs for new items, use "$id" instead of trying to read array length.
48
48
 
49
- AVAILABLE COMPONENTS (22):
50
-
51
- - Text: { content: string, variant?: "headline" | "body" | "eyebrow", size?: "small" | "medium" | "large" | "xlarge", subdued?: boolean, el?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" } - Display text. variant: headline=bold title, eyebrow=small label, body=default. size: small/medium/large/xlarge (headline and body only). subdued: deemphasized body text. el: heading element for variant=headline (default h3).
52
- - Card: { background?: "strong" | "stronger", padding?: "0" | "xsmall" | "small" | "medium" | "large" } - White surface with padding; groups related content. background: strong | stronger for elevated surfaces. padding: 0 | xsmall | small | medium (default) | large. [accepts children]
53
- - Flex: { direction?: "row" | "column", gap?: "1" | "2" | "3" | "4" | "5" | "6", alignItems?: "center" | "flex-start" | "flex-end" | "stretch" | "baseline", justifyContent?: "center" | "flex-start" | "flex-end" | "space-between" | "space-around" | "space-evenly", wrap?: "wrap" | "nowrap" | "wrap-reverse", grow?: number, shrink?: number, inline?: boolean } - Flex layout container. gap: 1=4px 2=8px 3=12px 4=16px 5=20px 6=24px. grow: 1=fill available width. alignItems: vertical alignment. justifyContent: horizontal distribution. [accepts children]
54
- - Grid: { templateColumns?: string, gap?: "1" | "2" | "3" | "4" | "5" | "6", bordered?: boolean } - CSS Grid layout. templateColumns: CSS grid-template-columns value — "repeat(3, 1fr)" for equal columns, "200px 1fr" for fixed+flex two-column (e.g. key-value tables), "1fr 1fr 80px" for multi-column tables. Children flow into grid cells left-to-right, top-to-bottom. gap: 1=4px … 6=24px. bordered: true renders a bordered table with row separators and cell padding — use for key-value and data tables. [accepts children]
55
- - Alert: { title: string, status?: "info" | "success" | "warning" | "danger", dismissible?: boolean } - Alert/notification banner. dismissible: true adds a close button that emits a "close" event. [accepts children]
56
- - Divider: { vertical?: boolean, spacing?: "0" | "1" | "2" | "3" | "4" | "5" | "6" | "8" | "12" | "half", alignContent?: "start" | "center" | "end" } - Divider between sections. vertical: true for vertical separator. spacing: gap around the divider. alignContent: alignment of content within the divider.
57
- - Icon: { name: "check-circle" | "in-progress" | "radio-button-unchecked", size?: "small" | "medium" | "large" | "xlarge", color?: string } - Anvil2 icon. name: check-circle=completed checkmark, in-progress=spinning partial circle, radio-button-unchecked=empty circle (pending)
58
- - Badge: { content?: string, offset?: { x?: string, y?: string } } - Unread notification count on a Button or Link. Wrap the interactive element as a child of Badge (the renderer adds position:relative). content: numerical count only (e.g. 3, 99+); omit for dot-only. offset: {x, y} CSS values to fine-tune position on non-square anchors like links. [accepts children]
59
- - Chip: { label: string, size?: "small" | "medium", color?: string, icon?: "check-circle" | "in-progress" | "radio-button-unchecked", removable?: boolean } - Inline label pill for metadata, tags, or categoriesuse for job statuses, not notification counts (use Badge for those). size: small | medium (default). color: any CSS color. icon: optional leading icon. removable: true adds a close button (not available for size=small).
60
- - Link: { label: string, href: string, appearance?: "primary" | "secondary", target?: "_blank" | "_self", ghost?: boolean } - Inline navigation link. href: destination URL. appearance: primary (default) | secondary. target: _blank opens in new tab (shows external-link icon). ghost: quieter styling (primary only).
61
- - ProgressBar: { label: string, value?: number, description?: string, indeterminate?: boolean } - Progress bar showing task completion. value: 0–100 (percentage). Omit value and set indeterminate=true for unknown progress.
49
+ AVAILABLE COMPONENTS (21):
50
+
51
+ - Text: { content: string, variant?: "headline" | "body" | "eyebrow", size?: "small" | "medium" | "large" | "xlarge", subdued?: boolean } - Display text. variant: headline=bold title, eyebrow=small uppercase label, body=default (default variant). size: small | medium (default) | large | xlarge — applies to headline and body only (ignored for eyebrow). subdued: deemphasized secondary text (body only). Use eyebrow+headline pairs for KPI/stat labels above values.
52
+ - Card: { title?: string, description?: string, background?: "strong" | "stronger", padding?: "0" | "xsmall" | "small" | "medium" | "large" } - White surface that groups a logical section of related content. title: optional headline rendered at the top of the card. description: optional subdued line below the title. Children render below the header and are stacked vertically with consistent spacing — you do not need to wrap them in a Flex. Prefer the built-in title/description over standalone Text children for the heading. background: strong | stronger for nested/elevated surfaces. padding: 0 | xsmall | small | medium (default) | large. Do not nest a Card inside another Card. [accepts children]
53
+ - Flex: { direction?: "row" | "column", gap?: "0" | "1" | "2" | "3" | "4" | "5" | "6" | "8" | "12" | "half", alignItems?: "center" | "flex-start" | "flex-end" | "stretch" | "baseline", justifyContent?: "center" | "flex-start" | "flex-end" | "space-between" | "space-around" | "space-evenly", alignSelf?: "auto" | "center" | "flex-start" | "flex-end" | "stretch" | "baseline", wrap?: "wrap" | "nowrap" | "wrap-reverse", grow?: number, shrink?: number, basis?: string, inline?: boolean } - Flex layout container. direction: row (default) | column — always set column when stacking children vertically. gap (spacing token, ~4px per step): half=2px 1=4px 2=8px 3=12px 4=16px 5=20px 6=24px 8=32px 12=48px. alignItems: cross-axis alignment of children. justifyContent: main-axis distribution. When this Flex is itself a child of another Flex, use grow (1=fill available space), shrink, basis (CSS flex-basis e.g. "200px"), and alignSelf to control how it flexes. [accepts children]
54
+ - Grid: { templateColumns?: string, gap?: "0" | "1" | "2" | "3" | "4" | "5" | "6" | "8" | "12" | "half", bordered?: boolean } - CSS Grid layout. templateColumns: CSS grid-template-columns value — "repeat(3, 1fr)" for equal columns, "200px 1fr" for fixed+flex two-column (e.g. key-value tables), "1fr 1fr 80px" for multi-column tables. Children flow into grid cells left-to-right, top-to-bottom. gap (spacing token, ~4px per step): 1=4px 2=8px … 6=24px 8=32px 12=48px (default 2). bordered: true renders a bordered table with row separators and cell padding — use for key-value and data tables. [accepts children]
55
+ - Alert: { title: string, status?: "info" | "success" | "warning" | "danger", dismissible?: boolean, aiMark?: boolean } - Inline notification banner with a required title. status: info (default) | success | warning | danger — danger for errors, warning for cautions, success for confirmations. Put the main message in the alert's children (rendered below the title). dismissible: true adds a close button that emits a "close" event. [accepts children] [events: close]
56
+ - Divider: { vertical?: boolean, spacing?: "0" | "1" | "2" | "3" | "4" | "5" | "6" | "8" | "12" | "half", alignContent?: "start" | "center" | "end" } - Horizontal (default) or vertical rule that separates content sections. vertical: true for a vertical separator between side-by-side content. spacing (space around the divider, ~4px per step): 0 (default) | half | 1–6 | 8 | 12. alignContent: alignment of any divider content (start | center | end). Place between logical sections — not as a top/bottom border of a container.
57
+ - Icon: { name: "check-circle" | "in-progress" | "radio-button-unchecked", size?: "small" | "medium" | "large" | "xlarge", color?: string } - Small status icon. name (only these three are available): check-circle=completed/success checkmark, in-progress=partial circle (active/working), radio-button-unchecked=empty circle (pending/not started). size: small | medium (default) | large | xlarge. color: any CSS color (defaults to the current text color). Commonly paired with status Text in lists and checklists.
58
+ - Chip: { label: string, size?: "small" | "medium", color?: string, icon?: "check-circle" | "in-progress" | "radio-button-unchecked", removable?: boolean } - Inline label pill for metadata, tags, or categories use for job statuses, not notification counts (use a Button/Link badge prop for those). size: small | medium (default). color: any CSS color. icon: optional leading status icon. removable: true adds a close button that emits a "close" event (ignored when size=small). [events: close]
59
+ - Link: { label: string, href: string, appearance?: "primary" | "secondary", target?: "_blank" | "_self", ghost?: boolean, badge?: string } - Inline navigation link (renders an <a>). Emits a "press" event when clicked handle navigation in on.press; href and target are inputs for the host/router rather than native browser navigation. href: destination URL for the host/router. appearance: primary (default) | secondary. target: _blank marks the link as external (shows external-link icon) and lets the host open a new tab if desired. ghost: quieter styling (primary only). badge: optional notification count shown as a superscript (e.g. "5"); use an empty string for a dot-only indicator. [events: press]
60
+ - ProgressBar: { label: string, value?: number, description?: string, indeterminate?: boolean } - Horizontal progress bar showing task completion. label is required (the accessible name for the bar). value: 0–100 percentage filled. Omit value and set indeterminate=true when progress cannot be measured (do not set both). description: optional helper text shown below the bar.
62
61
  - BarChart: { data: Array<{ category: string, value: number }>, orientation?: "vertical" | "horizontal", theme?: "monochrome" | "categorical" | "semantic", height?: number, unit?: string } - Bar chart (vertical or horizontal) with Anvil2 theme. data: [{category, value}]. theme: monochrome (default, ≤4 vars), categorical (5-9 distinct), semantic (success/neutral/warning/danger order). unit: tooltip suffix.
63
62
  - DonutChart: { data: Array<{ category: string, value: number }>, theme?: "monochrome" | "categorical" | "semantic", showLegend?: boolean, height?: number, unit?: string } - Donut chart with optional legend and Anvil2 theme. data: [{category, value}]. theme: monochrome (≤4 vars), categorical (5-9 distinct), semantic (status values).
64
63
  - LineChart: { data: Array<unknown>, series?: Array<string>, theme?: "monochrome" | "categorical" | "semantic", showLegend?: boolean, showDots?: boolean, height?: number, unit?: string } - Line chart for tracking trends over time with optional multiple series. data: array of objects with a "category" key (x-axis label) and one numeric key per series (e.g. [{category: "Jan", revenue: 100, cost: 60}]). series: explicit list of series keys to plot (inferred from data keys if omitted, max 6). theme: monochrome (1-2 series), categorical (3-6 distinct). showLegend: true when multiple series (default true for 2+ series). showDots: true adds data-point markers (default true). unit: tooltip value suffix.
65
- - Button: { label: string, appearance?: "primary" | "secondary" | "ghost", size?: "xsmall" | "small" | "medium" | "large", loading?: boolean, disabled?: boolean } - Clickable button. Every button automatically submits form data when pressed the element key is used as the actionId to identify which button was clicked. loading: true shows a spinner. disabled: true prevents interaction. size: xsmall | small | medium (default) | large.
66
- - Checkbox: { label: string, checked?: boolean, disabled?: boolean } - Checkbox input with label. Use $bindState on checked to track state.
67
- - Input: { label: string, placeholder?: string, type?: "text" | "password" | "email" | "tel" | "url" | "number", value?: string, disabled?: boolean } - Free-text input field for user-typed values (names, notes, numbers, etc). type: text (default), password (masked), email, tel (phone), url, number. Use $bindState on value to bind to state. Prefer this over Select when the value is not from a fixed list.
68
- - Textarea: { label: string, placeholder?: string, description?: string, moreInfo?: string, value?: string, rows?: number, disabled?: boolean } - Multi-line free-text input for long values (notes, descriptions, email body). Use $bindState on value to bind to state. rows: visible row count (default 3).
69
- - Listbox: { label: string, options: Array<{ value: string, label: string }>, value?: string, disabled?: boolean } - Listbox for choosing from a fixed list of known options. Use only when options are predefined. For free-text user input use Input instead.
70
- - RadioGroup: { label: string, options: Array<{ value: string, label: string }>, value?: string, disabled?: boolean } - Group of radio buttons for single selection. Use $bindState on value to capture selection.
71
- - Switch: { label: string, checked?: boolean, disabled?: boolean } - Toggle switch for binary on/off settings. Prefer over Checkbox for enabling/disabling features. Use $bindState on checked to track state.
64
+ - Button: { label: string, appearance?: "primary" | "secondary" | "ghost" | "danger", size?: "xsmall" | "small" | "medium" | "large", loading?: boolean, disabled?: boolean, badge?: string } - Clickable button. Emits a "press" event when clicked; inside a form the host treats press as a submit and uses the element key as the actionId, so no explicit on.press wiring is needed for form submits. appearance: primary | secondary (default) | ghost | danger (destructive actions like delete/cancel). size: xsmall | small | medium (default) | large. loading: true shows a spinner and blocks interaction. disabled: true prevents interaction. badge: optional notification count shown as a superscript (e.g. "3", "99+"); use an empty string for a dot-only indicator. [events: press]
65
+ - Checkbox: { label: string, checked?: boolean, disabled?: boolean } - Checkbox for selecting zero or more independent options that are submitted with a form (one Checkbox per option). For a single on/off setting with immediate effect prefer Switch. Bind state with $bindState on checked; emits a "change" event when toggled. disabled: true prevents toggling. [events: change]
66
+ - Input: { label: string, placeholder?: string, type?: "text" | "password" | "email" | "tel" | "url" | "number", value?: string, disabled?: boolean } - Free-text input field for user-typed values (names, notes, numbers, etc). type: text (default), password (masked), email, tel (phone), url, number. Bind value with $bindState so the typed value is captured in state; emits a "change" event on every keystroke. Prefer this over Listbox when the value is not from a fixed list. disabled: true prevents editing. [events: change]
67
+ - Textarea: { label: string, placeholder?: string, description?: string, moreInfo?: string, value?: string, rows?: number, disabled?: boolean } - Multi-line free-text input for long values (notes, descriptions, email body). Bind value with $bindState; emits a "change" event on every keystroke. rows: visible row count (default 3). description: helper text below the field. moreInfo: tooltip text on the label. disabled: true prevents editing. [events: change]
68
+ - Listbox: { label: string, options: Array<{ value: string, label: string }>, value?: string, disabled?: boolean } - Single-select dropdown for choosing one value from a fixed list of known options. options: [{ value, label }] — value is stored in state, label is shown. Bind the selection with $bindState on value; emits a "change" event on selection. Use only when options are predefined; for free-text user input use Input, and for 2–7 visible mutually-exclusive choices prefer RadioGroup. disabled: true prevents selection. [events: change]
69
+ - RadioGroup: { label: string, options: Array<{ value: string, label: string }>, value?: string, disabled?: boolean } - Group of radio buttons for picking one option from 2–7 visible mutually-exclusive choices. options: [{ value, label }]. Bind the selection with $bindState on value; emits a "change" event on selection. For longer option lists use Listbox. disabled: true prevents selection. [events: change]
70
+ - Switch: { label: string, checked?: boolean, disabled?: boolean } - Toggle switch for a single binary on/off setting with immediate effect (no form submit). Prefer over Checkbox for enabling/disabling features. Bind state with $bindState on checked; emits a "change" event when toggled. disabled: true prevents toggling. [events: change]
72
71
  - RevenueCard: { title: string, value: string, trend?: "up" | "down" | "flat", delta?: string } - KPI metric card. trend: up=green↑ down=red↓ flat=grey→. delta e.g. "+12% vs last month". Leaf node — no children.
73
72
 
74
73
  AVAILABLE ACTIONS:
@@ -168,117 +167,132 @@ CRITICAL — apply these rules before choosing any form component:
168
167
 
169
168
  ━━━ LAYOUT RULES ━━━
170
169
 
171
- 1. ALWAYS wrap everything in a root Flex { direction: "column", gap: "4" } — EXCEPT when the root element is a chart (BarChart or DonutChart), in which case use the chart as the single root element.
172
- 2. Use Card to group each logical section. Never put bare Text at the root level.
173
- 3. Inside a Card, use Flex { direction: "column", gap: "3" } as the first child.
170
+ 1. ALWAYS wrap everything in a root Flex { direction: "column", gap: "4" } — EXCEPT when the root element is a chart (BarChart, DonutChart, or LineChart), in which case use the chart as the single root element.
171
+ 2. Use Card to group each logical section. Never put bare Text at the root level. Use the Card title/description props for its heading.
172
+ 3. A Card stacks its children vertically on its own — only add a Flex inside a Card when you need a row (e.g. a chip row or button row).
174
173
  4. For side-by-side stats, use Flex { direction: "row", gap: "4" } with eyebrow+headline pairs.
175
- 5. Badge attaches to a Button or Link wrap the interactive element as a child of Badge in the spec (the renderer adds position: relative). Use Chip to show status labels, not Badge.
176
- 6. Divider separates content sections — can be placed between Cards or inside a Card (with padding="0" on the Card).
177
- 7. Button at the bottom of its Card inside Flex { direction: "row", gap: "2" }.
178
- 8. Do not nest Cards within Cards — use headings, body text, and actions to provide structure instead.
174
+ 5. To show a notification count on a Button or Link, set its badge prop (e.g. badge: "3") there is no standalone Badge component. Use Chip to show status labels.
175
+ 6. Divider separates content sections — place it between Cards, or between a Card's children for an explicit rule.
176
+ 7. Put a Card's action Buttons in a row Flex { direction: "row", gap: "2" } as the last child.
177
+ 8. Do not nest Cards within Cards — use the title/description, body text, and actions to provide structure instead.
179
178
 
180
179
  ━━━ CONTENT RULES ━━━
181
180
 
182
181
  - Use realistic ServiceTitan data: real names, job types, dollar amounts, dates.
183
- - For revenue/KPI summaries: use RevenueCard in a row Flex, one per metric.
182
+ - For revenue/KPI summaries: one metric per item in a row Flex — use RevenueCard when it is in the available components, otherwise an eyebrow+headline Text pair inside a Card.
184
183
  - For job/tech/customer lists: 3-4 Card items each with a Chip for status.
185
- - For checklists: Checkbox components inside a single Card.
184
+ - For checklists: Checkbox components inside a single Card, or Icon (check-circle / in-progress / radio-button-unchecked) + Text rows for read-only status.
186
185
  - For settings/toggles: Switch components for binary on/off, Checkbox for multi-select options, Listbox for fixed option lists, Input for free-text fields.
187
- - For forms: use Input for any free-text field (name, email, notes, address, etc.) — NEVER use Listbox for free-text. Use Listbox only when options are a fixed predefined list. Use RadioGroup for single-choice from a set of 2–7 mutually exclusive options. Bind all fields with $bindState. Add submit Buttons with a unique actionId prop per button — every Button automatically submits the form with its actionId, no on.press wiring needed.
186
+ - For forms: use Input for any free-text field (name, email, notes, address, etc.) — NEVER use Listbox for free-text. Use Listbox only when options are a fixed predefined list. Use RadioGroup for single-choice from a set of 2–7 mutually exclusive options. Bind all fields with $bindState. Give each submit Button a unique element key — every Button automatically submits the form using its element key as the actionId, no on.press wiring needed.
188
187
  - Status values: "Scheduled" | "In Progress" | "Completed" | "On Hold" | "Cancelled"
189
- - For any request mentioning "chart", "graph", "breakdown", "distribution", or "by region/tech/status": use BarChart or DonutChart as the root element. Do NOT wrap charts in Card or Flex.
188
+ - For any request mentioning "chart", "graph", "breakdown", "distribution", "trend", or "by region/tech/status": use a chart as the root element. Do NOT wrap charts in Card or Flex.
190
189
  - BarChart: best for comparisons across categories (revenue by region, jobs by tech).
191
190
  - DonutChart: best for part-of-whole breakdowns (job status mix, revenue share).
191
+ - LineChart: best for trends over time (revenue by month, calls per week), one or more series.
192
192
 
193
193
  ━━━ ANVIL2 COMPONENT BEST PRACTICES ━━━
194
194
 
195
+ Only use the props listed in each component's catalog entry above. Do NOT invent
196
+ props (no onClick on Card, no avatar/textWrap on Chip, no svg on Icon, etc.) —
197
+ unknown props are dropped.
198
+
195
199
  TEXT
196
- - Three variants only: "body" (default), "eyebrow", "headline".
197
- - "headline" REQUIRES the el prop ("h1""h4"). Always pair with a meaningful heading level.
198
- - "eyebrow" does NOT support size="xlarge".
199
- - Use subdued prop (variant="body" only) for de-emphasized secondary text.
200
- - When nesting body Text inside body Text, add inline prop to the inner Text so it renders as <span> not <p>.
200
+ - Three variants: "body" (default), "eyebrow" (small uppercase label), "headline" (bold title).
201
+ - size ("small" | "medium" | "large" | "xlarge") applies to headline and body only; it is ignored for eyebrow.
202
+ - Use subdued (body variant only) for de-emphasized secondary text.
201
203
  - Use eyebrow + headline pairs for KPI/stat labels above values.
204
+ - Prefer a Card's built-in title/description over standalone Text where it fits — fewer elements, more consistent.
202
205
 
203
206
  CARD
204
- - Always set flexDirection="column" when stacking children vertically (the default layout is inline-flex).
207
+ - A Card groups one logical section. Use its title (headline) and description (subdued line) props for the heading instead of standalone Text children.
208
+ - The Card stacks its children vertically with consistent spacing automatically — do NOT wrap children in a column Flex just to stack them. Use a row Flex only when you specifically need horizontal layout (e.g. a chip row or a button row).
205
209
  - Use background="strong" or "stronger" to visually differentiate nested sections.
206
- - padding options: "0" | "xsmall" | "small" | "medium" (default) | "large". Use padding="0" + Divider for section-divided cards.
207
- - For clickable cards, use InteractiveCard never add onClick to a plain Card.
208
- - To create sections within a Card: set padding="0", then place Divider between child elements.
210
+ - padding: "0" | "xsmall" | "small" | "medium" (default) | "large".
211
+ - Cards are not clickable put a Button or Link inside for actions. Never nest a Card inside another Card.
209
212
 
210
213
  FLEX
211
- - Use Flex for all layout containers within page content (not for top-level page column structure).
212
- - direction defaults to "row" always explicitly set direction="column" when stacking.
213
- - gap values are design tokens: "0" | "half" | "1" | "2" | "3" | "4" | "5" | "6" | "8" | "12" | "13" | "14".
214
- - Flex can be both a container and a flex item use grow, shrink, basis, alignSelf props when nested inside another Flex.
214
+ - Use Flex for layout containers within page content. direction defaults to "row" — always set direction="column" when stacking.
215
+ - gap values are spacing tokens: "0" | "half" | "1" | "2" | "3" | "4" | "5" | "6" | "8" | "12" (~4px per step).
216
+ - alignItems sets cross-axis alignment; justifyContent sets main-axis distribution.
217
+ - When a Flex is itself nested inside another Flex, use grow (1 = fill available space), shrink, basis (CSS flex-basis, e.g. "200px"), and alignSelf to control how it flexes.
218
+
219
+ GRID
220
+ - Use Grid for tabular / multi-column layouts. templateColumns is a CSS grid-template-columns value: "repeat(3, 1fr)" for equal columns, "200px 1fr" for key-value tables, "1fr 1fr 80px" for data tables.
221
+ - Children flow into cells left-to-right, top-to-bottom — emit one child element per cell.
222
+ - gap uses the same spacing tokens as Flex (default "2").
223
+ - Set bordered=true for key-value and data tables (adds row separators + cell padding).
215
224
 
216
225
  ALERT
217
- - Use status prop to set semantic meaning: "info" (default) | "success" | "warning" | "danger".
218
- - title is optional but strongly recommended — it is the primary label for the alert.
219
- - Alert is for contextual, inline notifications on the page, not for toasts or announcements.
220
- - Use status="danger" for errors, status="warning" for cautionary messages, status="success" for confirmations.
221
-
222
- BADGE
223
- - Badge indicates unread notifications or attention-required counts on Button or Link NEVER use it as a status label (use Chip for that).
224
- - In the spec, make Badge the parent and put the Button or Link as its child element; the renderer wraps them in position: relative.
225
- - Only put numerical values in the content prop. Cap at 99 (show "99+") or 999 for high-volume cases.
226
- - Omit content for a dot-only unread indicator (no count).
227
- - Use offset prop to fine-tune position when used on non-square elements like text links.
228
- - The child Button or Link must have a clear label (e.g., "Notifications", "Inbox"); do not add props that are not defined on the Badge catalog schema.
226
+ - status sets semantic meaning: "info" (default) | "success" | "warning" | "danger". Use danger for errors, warning for cautions, success for confirmations.
227
+ - title is required and is the primary label for the alert; put supporting detail in the children.
228
+ - Alert is for contextual, inline notifications on the page not toasts or announcements.
229
+ - Set dismissible=true to add a close button; wire on.close if the host needs to react.
230
+
231
+ NOTIFICATION BADGES
232
+ - There is no standalone Badge component. Show an unread/attention count by setting the badge prop on a Button or Link (e.g. badge: "3", badge: "99+"), or badge: "" for a dot-only indicator.
233
+ - Use a badge for counts only use Chip for status labels.
229
234
 
230
235
  CHIP
231
- - Chip visually labels and organizes statuses, metadata, and objects — NOT for notification counts (use Badge for that).
232
- - label prop is required — keep it short and descriptive.
233
- - Use color prop to convey status meaning (e.g., success = green, danger = red) — always pair color with text, never rely on color alone.
234
- - icon and avatar are mutually exclusive on a single Chip.
235
- - When size="small", only onClick OR onClose can be used, not both.
236
- - Default size is "medium". Use "small" in dense contexts (tables, tabs, sidenav).
237
- - Chips truncate by default; add textWrap to allow wrapping.
236
+ - Chip labels statuses, metadata, tags, and objects — NOT notification counts (use a Button/Link badge prop for those).
237
+ - label is required — keep it short. Default size is "medium"; use "small" in dense contexts (tables, tabs).
238
+ - Use color to convey status meaning (e.g. success = green, danger = red) — always pair color with the label text, never rely on color alone.
239
+ - icon (optional) is one of the three status icons: check-circle | in-progress | radio-button-unchecked.
240
+ - removable=true adds a close button that emits a "close" event (ignored when size="small").
238
241
  - Group multiple Chips in a Flex with gap="2" and wrap="wrap".
239
242
 
240
243
  DIVIDER
241
- - Use spacing prop to control vertical/horizontal space around the divider: "0"–"6" (in 0.5rem steps), "8", "12". Default is "0".
242
- - Use vertical prop for side-by-side content separation; default (horizontal) for stacked sections.
243
- - To divide Card sections: set Card padding="0" and place Divider between children with each child managing its own padding.
244
+ - spacing controls the space around the divider: "0" (default) | "half" | "1"–"6" | "8" | "12".
245
+ - Use vertical=true for side-by-side separation; default (horizontal) for stacked sections.
246
+ - To divide Card sections, set Card padding="0" and place Divider between children.
244
247
  - Place Divider between logical sections, not as a top/bottom border of a container.
245
248
 
246
249
  ICON
247
- - svg prop is required always import SVG assets from @servicetitan/anvil2/assets/icons/material/round/*.svg.
250
+ - name is one of three status icons: check-circle (completed/success) | in-progress (active) | radio-button-unchecked (pending). There are no other icon names.
248
251
  - size: "small" | "medium" (default) | "large" | "xlarge".
249
- - If Icon is standalone with no text label, provide aria-label for accessibility.
250
- - If Icon is paired with a visible text label, no aria-label needed.
251
- - Use color prop for custom colors (accepts CSS color values and CSS variables). For icon color that should match surrounding text, use inherit prop.
252
- - Do NOT use Icon for interactive affordances without a Tooltip and tabIndex={0}.
252
+ - color accepts any CSS color; omit it to inherit the surrounding text color.
253
+ - Pair Icon with a Text label for status rows and checklists.
253
254
 
254
255
  LINK
255
256
  - appearance: "primary" (default) | "secondary". Use primary for main navigation links.
256
- - ghost prop creates a quieter appearance — only valid when appearance="primary".
257
- - Link text must be descriptive (not "click here") — screen readers use the link text for context.
258
- - Use Link for navigation (renders <a>). For a button styled as a link, use LinkButton instead.
259
- - For external links, add target="_blank".
257
+ - ghost=true creates a quieter appearance — only valid when appearance="primary".
258
+ - Link text must be descriptive (not "click here") — screen readers rely on it.
259
+ - Link renders an <a> and emits a "press" event. Always handle navigation in on.press; href/target are inputs for the host/router rather than native browser navigation. For in-app routing wire on.press to atlas.navigate. For external links, use target="_blank" to tell the host to open a new tab.
260
+ - Set badge (e.g. "5") to show a notification count on the link.
260
261
 
261
262
  PROGRESSBAR
262
- - label (or aria-label / aria-labelledby) is required.
263
- - value (0–max) determines fill percentage. max defaults to 100.
264
- - Use indeterminate prop (no value) when progress cannot be determineddo NOT use both value and indeterminate together.
265
- - Use error prop (boolean or string) to show error state; string value shows an error message below the bar.
266
- - Use description prop for optional supplemental context below the bar.
263
+ - label is required it is the accessible name for the bar.
264
+ - value (0–100) sets the fill percentage.
265
+ - Set indeterminate=true (and omit value) when progress cannot be measurednever set both value and indeterminate.
266
+ - Use description for optional supplemental context below the bar.
267
+
268
+ BUTTON
269
+ - appearance: "primary" (main action) | "secondary" (default) | "ghost" (low-emphasis) | "danger" (destructive actions like delete/cancel).
270
+ - size: "xsmall" | "small" | "medium" (default) | "large".
271
+ - A Button emits a "press" event; inside a form the host treats press as a submit using the element's key as the actionId — give each submit Button a unique, descriptive key and do not wire on.press for plain form submits.
272
+ - Use loading=true while an action is in flight (shows a spinner and blocks interaction); disabled=true to prevent interaction.
273
+ - Set badge (e.g. "3") to show a notification count on the button; badge: "" renders a dot-only indicator.
274
+
275
+ FORM FIELDS (Input, Textarea, Listbox, RadioGroup, Switch, Checkbox)
276
+ - Every field MUST bind its value/checked prop with $bindState to a state path so the entered value is captured.
277
+ - Input/Textarea: free text. Listbox: single choice from a fixed option list. RadioGroup: single choice from 2–7 visible options. Switch: a single immediate on/off setting. Checkbox: zero-or-more independent options submitted with a form.
278
+ - These fields emit a "change" event; you rarely need to wire it — $bindState already syncs state. Set disabled=true to lock a field.
267
279
 
268
280
  BARCHART
269
281
  - Best for comparing values across categories (revenue by region, jobs by technician, calls by month).
270
- - Use for grouped comparisons across multiple categories; use stacked variant to show part-of-whole within each bar.
271
- - Apply 4px corner radius to the top of bars. Use 4px spacing between stacked segments.
272
- - Use monochrome color palette for data with natural order/progression (≤4 variables). Use categorical palette for 5–9 distinct categories.
282
+ - data is an array of { category, value }. orientation: "vertical" (default) | "horizontal" (use horizontal for long category labels).
283
+ - theme: "monochrome" (default, data with a natural order, ≤4 categories) | "categorical" (5–9 distinct categories) | "semantic" (success/neutral/warning/danger ordering).
284
+ - unit sets the tooltip value suffix (e.g. "$", "%").
273
285
  - Do NOT wrap in Card or Flex — use as the root element.
274
- - Always include title, axis labels, and legend.
275
286
 
276
287
  DONUTCHART
277
- - Best for part-of-whole breakdowns where all slices add up to 100%.
278
- - Use for showing proportions (job status mix, revenue share by category). NOT for precise category comparisons.
279
- - Sort slices from largest to smallest (clockwise). Group minor categories into an "Other" slice placed last.
280
- - Use 4px spacing (1.4px gap) between donut sections.
281
- - Preferred over pie charts for dashboards — the open center allows central metric labeling.
282
- - Use color to differentiate categories; apply extended palette for >5 categories; always ensure accessibility contrast.
288
+ - Best for part-of-whole breakdowns where all slices add up to 100% (job status mix, revenue share). NOT for precise category comparisons.
289
+ - data is an array of { category, value }. Sort slices largest to smallest; group minor categories into an "Other" slice placed last.
290
+ - theme: "monochrome" (≤4 categories) | "categorical" (5–9 distinct) | "semantic" (status values). showLegend toggles the legend; unit sets the tooltip suffix.
291
+ - Do NOT wrap in Card or Flex — use as the root element.
292
+
293
+ LINECHART
294
+ - Best for trends over time, with one or more series.
295
+ - data is an array of objects with a "category" key (x-axis label, e.g. month) and one numeric key per series, e.g. [{ category: "Jan", revenue: 100, cost: 60 }].
296
+ - series optionally names which keys to plot (inferred from the data keys if omitted, max 6). theme: "monochrome" (1–2 series) | "categorical" (3–6 series). showLegend (default true for 2+ series); showDots toggles point markers; unit sets the tooltip suffix.
283
297
  - Do NOT wrap in Card or Flex — use as the root element.
284
298
 
@@ -18,7 +18,6 @@
18
18
  "Alert",
19
19
  "Divider",
20
20
  "Icon",
21
- "Badge",
22
21
  "Chip",
23
22
  "Link",
24
23
  "ProgressBar",
@@ -0,0 +1,50 @@
1
+ import { contextContentComponents, contextShellComponents } from './schemas';
2
+ export { contextContentComponents, contextShellComponents };
3
+ export declare const contextComponents: Record<string, import('../..').ComponentCatalogDef>;
4
+ export declare const contextCatalog: import('@json-render/core').Catalog<{
5
+ spec: import('@json-render/core').SchemaType<"object", {
6
+ root: import('@json-render/core').SchemaType<"string", unknown>;
7
+ elements: import('@json-render/core').SchemaType<"record", import('@json-render/core').SchemaType<"object", {
8
+ type: import('@json-render/core').SchemaType<"ref", string>;
9
+ props: import('@json-render/core').SchemaType<"propsOf", string>;
10
+ children: import('@json-render/core').SchemaType<"array", import('@json-render/core').SchemaType<"string", unknown>>;
11
+ visible: import('@json-render/core').SchemaType<"any", unknown>;
12
+ }>>;
13
+ }>;
14
+ catalog: import('@json-render/core').SchemaType<"object", {
15
+ components: import('@json-render/core').SchemaType<"map", {
16
+ props: import('@json-render/core').SchemaType<"zod", unknown>;
17
+ slots: import('@json-render/core').SchemaType<"array", import('@json-render/core').SchemaType<"string", unknown>>;
18
+ description: import('@json-render/core').SchemaType<"string", unknown>;
19
+ example: import('@json-render/core').SchemaType<"any", unknown>;
20
+ }>;
21
+ actions: import('@json-render/core').SchemaType<"map", {
22
+ params: import('@json-render/core').SchemaType<"zod", unknown>;
23
+ description: import('@json-render/core').SchemaType<"string", unknown>;
24
+ }>;
25
+ }>;
26
+ }, {
27
+ components: Record<string, import('../..').ComponentCatalogDef>;
28
+ actions: {
29
+ "atlas.submitUserAction": {
30
+ params: import('zod').ZodObject<{
31
+ data: import('zod').ZodOptional<import('zod').ZodRecord<import('zod').ZodString, import('zod').ZodUnknown>>;
32
+ actionId: import('zod').ZodOptional<import('zod').ZodString>;
33
+ }, import('zod/v4/core').$strip>;
34
+ description: string;
35
+ };
36
+ "atlas.navigate": {
37
+ params: import('zod').ZodObject<{
38
+ url: import('zod').ZodString;
39
+ }, import('zod/v4/core').$strip>;
40
+ description: string;
41
+ };
42
+ "atlas.toolCall": {
43
+ params: import('zod').ZodObject<{
44
+ tool: import('zod').ZodString;
45
+ args: import('zod').ZodOptional<import('zod').ZodRecord<import('zod').ZodString, import('zod').ZodUnknown>>;
46
+ }, import('zod/v4/core').$strip>;
47
+ description: string;
48
+ };
49
+ };
50
+ }>;
@@ -0,0 +1,19 @@
1
+ import { z } from 'zod';
2
+ export declare const contextCardCatalog: {
3
+ props: z.ZodObject<{
4
+ title: z.ZodString;
5
+ defaultExpanded: z.ZodOptional<z.ZodBoolean>;
6
+ badge: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodObject<{
7
+ label: z.ZodString;
8
+ tone: z.ZodOptional<z.ZodEnum<{
9
+ success: "success";
10
+ info: "info";
11
+ warning: "warning";
12
+ danger: "danger";
13
+ neutral: "neutral";
14
+ }>>;
15
+ }, z.core.$strip>]>>;
16
+ }, z.core.$strip>;
17
+ slots: string[];
18
+ description: string;
19
+ };
@@ -0,0 +1,8 @@
1
+ import { ReactNode } from 'react';
2
+ import { z } from 'zod';
3
+ import { contextCardCatalog } from './context-card.catalog';
4
+ export { contextCardCatalog };
5
+ export declare const ContextCardRenderer: ({ props, children, }: {
6
+ props: z.infer<typeof contextCardCatalog.props>;
7
+ children?: ReactNode;
8
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,34 @@
1
+ import { z } from 'zod';
2
+ export declare const contextDataTableCatalog: {
3
+ props: z.ZodObject<{
4
+ columns: z.ZodArray<z.ZodObject<{
5
+ key: z.ZodString;
6
+ header: z.ZodString;
7
+ type: z.ZodOptional<z.ZodEnum<{
8
+ text: "text";
9
+ currency: "currency";
10
+ chip: "chip";
11
+ delta: "delta";
12
+ }>>;
13
+ sortable: z.ZodOptional<z.ZodBoolean>;
14
+ }, z.core.$strip>>;
15
+ rows: z.ZodArray<z.ZodIntersection<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodNull, z.ZodObject<{
16
+ label: z.ZodString;
17
+ tone: z.ZodOptional<z.ZodEnum<{
18
+ success: "success";
19
+ info: "info";
20
+ warning: "warning";
21
+ danger: "danger";
22
+ neutral: "neutral";
23
+ }>>;
24
+ }, z.core.$strip>]>>, z.ZodObject<{
25
+ id: z.ZodString;
26
+ }, z.core.$strip>>>;
27
+ defaultSortedColumn: z.ZodOptional<z.ZodObject<{
28
+ id: z.ZodString;
29
+ desc: z.ZodOptional<z.ZodBoolean>;
30
+ }, z.core.$strip>>;
31
+ }, z.core.$strip>;
32
+ slots: never[];
33
+ description: string;
34
+ };
@@ -0,0 +1,2 @@
1
+ export declare const tableScrollWrap: string;
2
+ export declare const deltaCell: string;
@@ -0,0 +1,6 @@
1
+ import { z } from 'zod';
2
+ import { contextDataTableCatalog } from './context-data-table.catalog';
3
+ export { contextDataTableCatalog };
4
+ export declare const ContextDataTableRenderer: ({ props, }: {
5
+ props: z.infer<typeof contextDataTableCatalog.props>;
6
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,11 @@
1
+ import { z } from 'zod';
2
+ export declare const contextFileListCatalog: {
3
+ props: z.ZodObject<{
4
+ items: z.ZodArray<z.ZodObject<{
5
+ label: z.ZodString;
6
+ url: z.ZodString;
7
+ }, z.core.$strip>>;
8
+ }, z.core.$strip>;
9
+ slots: never[];
10
+ description: string;
11
+ };
@@ -0,0 +1,16 @@
1
+ export declare const fileList: string;
2
+ /** Full-width interactive card for each file row. */
3
+ export declare const fileCard: string;
4
+ /** Icon + label layout inside the card. */
5
+ export declare const fileRowContent: string;
6
+ /** 32×32 gray circle behind list-row icons. */
7
+ export declare const fileIconBadge: string;
8
+ /** Preview dialog content wrapper. */
9
+ export declare const filePreviewContent: string;
10
+ /** Centers image or icon above the filename. */
11
+ export declare const filePreviewMedia: string;
12
+ export declare const filePreviewImage: string;
13
+ /** Non-image preview — large centered file-type icon. */
14
+ export declare const filePreviewIconWrap: string;
15
+ /** Filename caption below the preview media. */
16
+ export declare const filePreviewLabel: string;
@@ -0,0 +1,6 @@
1
+ import { z } from 'zod';
2
+ import { contextFileListCatalog } from './context-file-list.catalog';
3
+ export { contextFileListCatalog };
4
+ export declare const ContextFileListRenderer: ({ props, }: {
5
+ props: z.infer<typeof contextFileListCatalog.props>;
6
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,48 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * A single row in a ContextList — timesheet or recent-job style:
4
+ * title: "Devon Carter"
5
+ * meta: "04/28/2026 · 8H · $65/HR · $520 TOTAL"
6
+ * callout: "$520.00", calloutLabel: "INVOICED"
7
+ *
8
+ * Or with a leading job link:
9
+ * identifier: "134536", identifierHref: "https://..."
10
+ * title: "HVAC Inspection"
11
+ * meta: "04/28/2026 · DEVON CARTER"
12
+ */
13
+ export declare const listItemSchema: z.ZodObject<{
14
+ title: z.ZodString;
15
+ identifier: z.ZodOptional<z.ZodString>;
16
+ identifierHref: z.ZodOptional<z.ZodString>;
17
+ meta: z.ZodOptional<z.ZodString>;
18
+ callout: z.ZodOptional<z.ZodString>;
19
+ calloutTone: z.ZodOptional<z.ZodEnum<{
20
+ success: "success";
21
+ info: "info";
22
+ warning: "warning";
23
+ danger: "danger";
24
+ neutral: "neutral";
25
+ }>>;
26
+ calloutLabel: z.ZodOptional<z.ZodString>;
27
+ }, z.core.$strip>;
28
+ export declare const contextListCatalog: {
29
+ props: z.ZodObject<{
30
+ items: z.ZodArray<z.ZodObject<{
31
+ title: z.ZodString;
32
+ identifier: z.ZodOptional<z.ZodString>;
33
+ identifierHref: z.ZodOptional<z.ZodString>;
34
+ meta: z.ZodOptional<z.ZodString>;
35
+ callout: z.ZodOptional<z.ZodString>;
36
+ calloutTone: z.ZodOptional<z.ZodEnum<{
37
+ success: "success";
38
+ info: "info";
39
+ warning: "warning";
40
+ danger: "danger";
41
+ neutral: "neutral";
42
+ }>>;
43
+ calloutLabel: z.ZodOptional<z.ZodString>;
44
+ }, z.core.$strip>>;
45
+ }, z.core.$strip>;
46
+ slots: never[];
47
+ description: string;
48
+ };
@@ -0,0 +1,16 @@
1
+ /** Outer list wrapper. */
2
+ export declare const listRoot: string;
3
+ /** Subdued color for meta and callout labels. */
4
+ export declare const textSubdued: string;
5
+ /** A single list item row. */
6
+ export declare const listItem: string;
7
+ /** Two-column grid: left fills space, right shrinks to content. */
8
+ export declare const listItemGrid: string;
9
+ /** Left column — title row + meta row. */
10
+ export declare const listColLeft: string;
11
+ /** Title row: optional link, divider, title. */
12
+ export declare const listPrimaryRow: string;
13
+ /** Vertical divider between identifier link and title. */
14
+ export declare const listPrimaryDivider: string;
15
+ /** Right column — callout + callout label, right-aligned. */
16
+ export declare const listColRight: string;
@@ -0,0 +1,6 @@
1
+ import { z } from 'zod';
2
+ import { contextListCatalog } from './context-list.catalog';
3
+ export { contextListCatalog };
4
+ export declare const ContextListRenderer: ({ props, }: {
5
+ props: z.infer<typeof contextListCatalog.props>;
6
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,22 @@
1
+ import { z } from 'zod';
2
+ export declare const contextMetricGridCatalog: {
3
+ props: z.ZodObject<{
4
+ items: z.ZodArray<z.ZodObject<{
5
+ label: z.ZodString;
6
+ value: z.ZodString;
7
+ tone: z.ZodOptional<z.ZodEnum<{
8
+ success: "success";
9
+ info: "info";
10
+ warning: "warning";
11
+ danger: "danger";
12
+ neutral: "neutral";
13
+ }>>;
14
+ }, z.core.$strip>>;
15
+ columns: z.ZodOptional<z.ZodEnum<{
16
+ 3: "3";
17
+ 4: "4";
18
+ }>>;
19
+ }, z.core.$strip>;
20
+ slots: never[];
21
+ description: string;
22
+ };
@@ -0,0 +1,13 @@
1
+ export declare const metricGrid: import('@vanilla-extract/recipes').RuntimeFn<{
2
+ columns: {
3
+ "3": {
4
+ gridTemplateColumns: "repeat(3, minmax(0, 1fr))";
5
+ };
6
+ "4": {
7
+ gridTemplateColumns: "repeat(4, minmax(0, 1fr))";
8
+ };
9
+ };
10
+ }>;
11
+ /** Subdued color for KPI label eyebrows. */
12
+ export declare const eyebrowSubdued: string;
13
+ export declare const metricGridItem: string;
@@ -0,0 +1,6 @@
1
+ import { z } from 'zod';
2
+ import { contextMetricGridCatalog } from './context-metric-grid.catalog';
3
+ export { contextMetricGridCatalog };
4
+ export declare const ContextMetricGridRenderer: ({ props, }: {
5
+ props: z.infer<typeof contextMetricGridCatalog.props>;
6
+ }) => import("react/jsx-runtime").JSX.Element;