diff --git a/examples/component-showcase/package.json b/examples/component-showcase/package.json
index fab9e218..bb9b332a 100644
--- a/examples/component-showcase/package.json
+++ b/examples/component-showcase/package.json
@@ -5,8 +5,8 @@
"type": "module",
"scripts": {
"generate:reference": "bun run ../../scripts/generate-ui-component-reference.mjs",
- "generate:pages": "node scripts/generate-showcase.mjs",
- "generate": "bun run generate:reference && bun run generate:pages",
+ "generate:pages": "bun run generate:reference && node scripts/generate-showcase.mjs",
+ "generate": "bun run generate:pages",
"dev": "bun run generate && bun run ../../packages/cli/src/index.ts dev .",
"build": "bun run generate && bun run ../../packages/cli/src/index.ts build .",
"typecheck": "tsc --noEmit -p tsconfig.json",
diff --git a/examples/component-showcase/showcase-manifest.json b/examples/component-showcase/showcase-manifest.json
index b7531334..07caa776 100644
--- a/examples/component-showcase/showcase-manifest.json
+++ b/examples/component-showcase/showcase-manifest.json
@@ -1,8 +1,8 @@
{
"generatedFrom": "packages/ui/component-reference.json",
- "componentCount": 108,
+ "componentCount": 102,
"categoryCount": 11,
- "totalDemoCount": 419,
+ "totalDemoCount": 401,
"components": [
{
"name": "Accordion",
@@ -13,31 +13,11 @@
"demoCount": 3,
"propCount": 17,
"slots": [],
- "events": ["change", "open", "close"],
- "profiled": false
- },
- {
- "name": "AdvancedDatePicker",
- "mount": "AdvancedDatePicker",
- "slug": "advanced-date-picker",
- "category": "integrations",
- "purpose": "Theme-aware, responsive advanced date picker component.",
- "demoCount": 3,
- "propCount": 7,
- "slots": ["default"],
- "events": ["input", "change", "open", "close", "clear"],
- "profiled": false
- },
- {
- "name": "AdvancedRangeSlider",
- "mount": "AdvancedRangeSlider",
- "slug": "advanced-range-slider",
- "category": "integrations",
- "purpose": "Theme-aware, responsive advanced range slider component.",
- "demoCount": 3,
- "propCount": 7,
- "slots": ["default"],
- "events": ["input", "change", "start", "end"],
+ "events": [
+ "change",
+ "open",
+ "close"
+ ],
"profiled": false
},
{
@@ -49,7 +29,16 @@
"demoCount": 41,
"propCount": 51,
"slots": [],
- "events": ["search", "select", "change", "clear", "open", "close", "load", "error"],
+ "events": [
+ "search",
+ "select",
+ "change",
+ "clear",
+ "open",
+ "close",
+ "load",
+ "error"
+ ],
"profiled": false
},
{
@@ -61,7 +50,10 @@
"demoCount": 3,
"propCount": 21,
"slots": [],
- "events": ["dismiss", "action"],
+ "events": [
+ "dismiss",
+ "action"
+ ],
"profiled": false
},
{
@@ -73,7 +65,9 @@
"demoCount": 3,
"propCount": 19,
"slots": [],
- "events": ["dismiss"],
+ "events": [
+ "dismiss"
+ ],
"profiled": true
},
{
@@ -84,8 +78,16 @@
"purpose": "Reusable auth form component.",
"demoCount": 3,
"propCount": 13,
- "slots": ["default"],
- "events": ["submit", "change", "input", "focus", "blur"],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "submit",
+ "change",
+ "input",
+ "focus",
+ "blur"
+ ],
"profiled": false
},
{
@@ -96,7 +98,10 @@
"purpose": "Reusable auth split layout component.",
"demoCount": 3,
"propCount": 8,
- "slots": ["aside-extra", "form"],
+ "slots": [
+ "aside-extra",
+ "form"
+ ],
"events": [],
"profiled": false
},
@@ -109,7 +114,11 @@
"demoCount": 3,
"propCount": 18,
"slots": [],
- "events": ["load", "error", "click"],
+ "events": [
+ "load",
+ "error",
+ "click"
+ ],
"profiled": false
},
{
@@ -121,7 +130,9 @@
"demoCount": 3,
"propCount": 12,
"slots": [],
- "events": ["overflow"],
+ "events": [
+ "overflow"
+ ],
"profiled": false
},
{
@@ -145,7 +156,9 @@
"demoCount": 3,
"propCount": 22,
"slots": [],
- "events": ["dismiss"],
+ "events": [
+ "dismiss"
+ ],
"profiled": false
},
{
@@ -156,7 +169,9 @@
"purpose": "Theme-aware, responsive blockquote component.",
"demoCount": 3,
"propCount": 13,
- "slots": ["default"],
+ "slots": [
+ "default"
+ ],
"events": [],
"profiled": false
},
@@ -169,7 +184,9 @@
"demoCount": 3,
"propCount": 12,
"slots": [],
- "events": ["select"],
+ "events": [
+ "select"
+ ],
"profiled": true
},
{
@@ -180,8 +197,14 @@
"purpose": "Theme-aware, responsive button component.",
"demoCount": 8,
"propCount": 25,
- "slots": ["default"],
- "events": ["click", "focus", "blur"],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "click",
+ "focus",
+ "blur"
+ ],
"profiled": false
},
{
@@ -192,8 +215,14 @@
"purpose": "Theme-aware, responsive button group component.",
"demoCount": 3,
"propCount": 13,
- "slots": ["default"],
- "events": ["click", "select", "change"],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "click",
+ "select",
+ "change"
+ ],
"profiled": false
},
{
@@ -204,7 +233,12 @@
"purpose": "Close a page or major section with conversion-focused copy, actions, and optional supporting visual content.",
"demoCount": 3,
"propCount": 25,
- "slots": ["default", "actions", "visual", "footer"],
+ "slots": [
+ "default",
+ "actions",
+ "visual",
+ "footer"
+ ],
"events": [],
"profiled": true
},
@@ -216,8 +250,17 @@
"purpose": "Group related content in a responsive themed surface with title, description, content, and supporting slots.",
"demoCount": 3,
"propCount": 31,
- "slots": ["default"],
- "events": ["click", "action", "navigate", "dismiss", "load", "error"],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "click",
+ "action",
+ "navigate",
+ "dismiss",
+ "load",
+ "error"
+ ],
"profiled": true
},
{
@@ -228,7 +271,9 @@
"purpose": "Theme-aware, responsive carousel component.",
"demoCount": 3,
"propCount": 22,
- "slots": ["default"],
+ "slots": [
+ "default"
+ ],
"events": [
"initialize",
"change",
@@ -250,9 +295,15 @@
"category": "integrations",
"purpose": "Theme-aware, responsive chart component.",
"demoCount": 3,
- "propCount": 7,
- "slots": ["default"],
- "events": ["select", "dataPointClick", "legendToggle"],
+ "propCount": 12,
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "select",
+ "dataPointClick",
+ "legendToggle"
+ ],
"profiled": false
},
{
@@ -263,8 +314,15 @@
"purpose": "Theme-aware, responsive chat bubble component.",
"demoCount": 3,
"propCount": 11,
- "slots": ["default"],
- "events": ["action", "messageClick", "avatarClick", "linkClick"],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "action",
+ "messageClick",
+ "avatarClick",
+ "linkClick"
+ ],
"profiled": false
},
{
@@ -275,8 +333,16 @@
"purpose": "Theme-aware, responsive checkbox component.",
"demoCount": 3,
"propCount": 27,
- "slots": ["default"],
- "events": ["input", "change", "focus", "blur", "invalid"],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "input",
+ "change",
+ "focus",
+ "blur",
+ "invalid"
+ ],
"profiled": false
},
{
@@ -286,9 +352,15 @@
"category": "integrations",
"purpose": "Theme-aware, responsive clipboard component.",
"demoCount": 3,
- "propCount": 7,
- "slots": ["default"],
- "events": ["copy", "success", "error"],
+ "propCount": 11,
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "copy",
+ "success",
+ "error"
+ ],
"profiled": false
},
{
@@ -299,8 +371,14 @@
"purpose": "Theme-aware, responsive collapse component.",
"demoCount": 3,
"propCount": 8,
- "slots": ["default"],
- "events": ["toggle", "open", "close"],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "toggle",
+ "open",
+ "close"
+ ],
"profiled": false
},
{
@@ -312,7 +390,12 @@
"demoCount": 3,
"propCount": 19,
"slots": [],
- "events": ["input", "change", "focus", "blur"],
+ "events": [
+ "input",
+ "change",
+ "focus",
+ "blur"
+ ],
"profiled": false
},
{
@@ -323,7 +406,9 @@
"purpose": "Create responsive balanced content columns with configurable count, gap, density, and maximum width.",
"demoCount": 3,
"propCount": 6,
- "slots": ["default"],
+ "slots": [
+ "default"
+ ],
"events": [],
"profiled": true
},
@@ -336,7 +421,16 @@
"demoCount": 21,
"propCount": 41,
"slots": [],
- "events": ["search", "select", "change", "clear", "open", "close", "load", "error"],
+ "events": [
+ "search",
+ "select",
+ "change",
+ "clear",
+ "open",
+ "close",
+ "load",
+ "error"
+ ],
"profiled": false
},
{
@@ -346,9 +440,14 @@
"category": "integrations",
"purpose": "Theme-aware, responsive confetti component.",
"demoCount": 3,
- "propCount": 7,
- "slots": ["default"],
- "events": ["start", "complete"],
+ "propCount": 8,
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "start",
+ "complete"
+ ],
"profiled": false
},
{
@@ -359,7 +458,9 @@
"purpose": "Constrain and align page content with responsive gutters and compact, wide, or full width options.",
"demoCount": 3,
"propCount": 7,
- "slots": ["default"],
+ "slots": [
+ "default"
+ ],
"events": [],
"profiled": true
},
@@ -371,22 +472,20 @@
"purpose": "Open an accessible keyboard-aware action menu from pointer or keyboard context interactions.",
"demoCount": 3,
"propCount": 18,
- "slots": ["trigger", "header", "default", "footer"],
- "events": ["open", "close", "select", "action"],
+ "slots": [
+ "trigger",
+ "header",
+ "default",
+ "footer"
+ ],
+ "events": [
+ "open",
+ "close",
+ "select",
+ "action"
+ ],
"profiled": true
},
- {
- "name": "CopyMarkup",
- "mount": "CopyMarkup",
- "slug": "copy-markup",
- "category": "advanced-forms",
- "purpose": "Theme-aware, responsive copy markup component.",
- "demoCount": 3,
- "propCount": 13,
- "slots": [],
- "events": ["copy", "success", "error"],
- "profiled": false
- },
{
"name": "CustomScrollbar",
"mount": "CustomScrollbar",
@@ -395,7 +494,9 @@
"purpose": "Theme-aware, responsive custom scrollbar component.",
"demoCount": 2,
"propCount": 7,
- "slots": ["default"],
+ "slots": [
+ "default"
+ ],
"events": [],
"profiled": true
},
@@ -407,8 +508,13 @@
"purpose": "Theme-aware, responsive data map component.",
"demoCount": 3,
"propCount": 7,
- "slots": ["default"],
- "events": ["select", "change"],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "select",
+ "change"
+ ],
"profiled": false
},
{
@@ -419,7 +525,9 @@
"purpose": "Sortable, filterable, paginated data table with row selection.",
"demoCount": 9,
"propCount": 29,
- "slots": ["default"],
+ "slots": [
+ "default"
+ ],
"events": [
"sort",
"search",
@@ -441,7 +549,15 @@
"demoCount": 3,
"propCount": 25,
"slots": [],
- "events": ["input", "change", "open", "close", "focus", "blur", "invalid"],
+ "events": [
+ "input",
+ "change",
+ "open",
+ "close",
+ "focus",
+ "blur",
+ "invalid"
+ ],
"profiled": false
},
{
@@ -452,8 +568,13 @@
"purpose": "Theme-aware, responsive device frame component.",
"demoCount": 3,
"propCount": 14,
- "slots": ["default"],
- "events": ["change", "rotate"],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "change",
+ "rotate"
+ ],
"profiled": false
},
{
@@ -476,8 +597,17 @@
"purpose": "Theme-aware, responsive drag and drop component.",
"demoCount": 3,
"propCount": 7,
- "slots": ["default"],
- "events": ["dragStart", "dragEnd", "dragEnter", "dragLeave", "drop", "change"],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "dragStart",
+ "dragEnd",
+ "dragEnter",
+ "dragLeave",
+ "drop",
+ "change"
+ ],
"profiled": false
},
{
@@ -488,8 +618,17 @@
"purpose": "Present responsive modal side or bottom content with focus management, backdrop behavior, slots, and close events.",
"demoCount": 3,
"propCount": 20,
- "slots": ["trigger", "header", "default", "footer"],
- "events": ["open", "close", "cancel"],
+ "slots": [
+ "trigger",
+ "header",
+ "default",
+ "footer"
+ ],
+ "events": [
+ "open",
+ "close",
+ "cancel"
+ ],
"profiled": true
},
{
@@ -500,8 +639,19 @@
"purpose": "Open an accessible anchored menu with keyboard navigation, item selection, actions, and responsive placement.",
"demoCount": 3,
"propCount": 17,
- "slots": ["trigger", "header", "default", "footer"],
- "events": ["toggle", "open", "close", "select", "action"],
+ "slots": [
+ "trigger",
+ "header",
+ "default",
+ "footer"
+ ],
+ "events": [
+ "toggle",
+ "open",
+ "close",
+ "select",
+ "action"
+ ],
"profiled": true
},
{
@@ -512,7 +662,12 @@
"purpose": "Present one linked feature or service with media, icon, badge, description, and action.",
"demoCount": 3,
"propCount": 28,
- "slots": ["media", "icon", "default", "footer"],
+ "slots": [
+ "media",
+ "icon",
+ "default",
+ "footer"
+ ],
"events": [],
"profiled": true
},
@@ -524,7 +679,9 @@
"purpose": "Arrange feature cards, services, solutions, or benefits in a responsive equal-height grid.",
"demoCount": 3,
"propCount": 14,
- "slots": ["default"],
+ "slots": [
+ "default"
+ ],
"events": [],
"profiled": true
},
@@ -536,7 +693,10 @@
"purpose": "Present a compact feature or benefit with a styled icon, title, description, badge, and optional link.",
"demoCount": 3,
"propCount": 14,
- "slots": ["default", "footer"],
+ "slots": [
+ "default",
+ "footer"
+ ],
"events": [],
"profiled": true
},
@@ -549,19 +709,15 @@
"demoCount": 3,
"propCount": 21,
"slots": [],
- "events": ["input", "change", "focus", "blur", "select", "clear", "invalid"],
- "profiled": false
- },
- {
- "name": "FileUpload",
- "mount": "FileUpload",
- "slug": "file-upload",
- "category": "integrations",
- "purpose": "Theme-aware, responsive file upload component.",
- "demoCount": 3,
- "propCount": 7,
- "slots": ["default"],
- "events": ["select", "upload", "progress", "success", "error", "cancel", "remove"],
+ "events": [
+ "input",
+ "change",
+ "focus",
+ "blur",
+ "select",
+ "clear",
+ "invalid"
+ ],
"profiled": false
},
{
@@ -573,7 +729,11 @@
"demoCount": 3,
"propCount": 13,
"slots": [],
- "events": ["cancel", "retry", "complete"],
+ "events": [
+ "cancel",
+ "retry",
+ "complete"
+ ],
"profiled": false
},
{
@@ -584,8 +744,16 @@
"purpose": "Render structured responsive footer navigation, pre and post content, copyright content, links, and public events.",
"demoCount": 3,
"propCount": 8,
- "slots": ["pre-footer", "post-footer", "copyright-left", "copyright-right"],
- "events": ["select", "action"],
+ "slots": [
+ "pre-footer",
+ "post-footer",
+ "copyright-left",
+ "copyright-right"
+ ],
+ "events": [
+ "select",
+ "action"
+ ],
"profiled": true
},
{
@@ -596,7 +764,9 @@
"purpose": "Arrange arbitrary content in a responsive configurable CSS grid with stable columns, gaps, alignment, and width.",
"demoCount": 3,
"propCount": 7,
- "slots": ["default"],
+ "slots": [
+ "default"
+ ],
"events": [],
"profiled": true
},
@@ -608,7 +778,14 @@
"purpose": "Build a full-width responsive hero with constrained content, actions, trust signals, and a structured or custom visual panel.",
"demoCount": 3,
"propCount": 38,
- "slots": ["eyebrow", "actions", "trust", "default", "visual", "footer"],
+ "slots": [
+ "eyebrow",
+ "actions",
+ "trust",
+ "default",
+ "visual",
+ "footer"
+ ],
"events": [],
"profiled": true
},
@@ -620,7 +797,9 @@
"purpose": "Group hero and campaign actions with consistent alignment, orientation, sizing, and responsive mobile stacking.",
"demoCount": 3,
"propCount": 8,
- "slots": ["default"],
+ "slots": [
+ "default"
+ ],
"events": [],
"profiled": true
},
@@ -632,7 +811,9 @@
"purpose": "Render a responsive image with explicit dimensions, loading behavior, alternative text, sizing, and rounded treatment.",
"demoCount": 3,
"propCount": 10,
- "slots": ["default"],
+ "slots": [
+ "default"
+ ],
"events": [],
"profiled": true
},
@@ -645,7 +826,15 @@
"demoCount": 3,
"propCount": 28,
"slots": [],
- "events": ["input", "change", "focus", "blur", "invalid", "keydown", "keyup"],
+ "events": [
+ "input",
+ "change",
+ "focus",
+ "blur",
+ "invalid",
+ "keydown",
+ "keyup"
+ ],
"profiled": false
},
{
@@ -657,7 +846,14 @@
"demoCount": 3,
"propCount": 23,
"slots": [],
- "events": ["input", "change", "focus", "blur", "submit", "action"],
+ "events": [
+ "input",
+ "change",
+ "focus",
+ "blur",
+ "submit",
+ "action"
+ ],
"profiled": false
},
{
@@ -669,7 +865,12 @@
"demoCount": 12,
"propCount": 40,
"slots": [],
- "events": ["input", "change", "increment", "decrement"],
+ "events": [
+ "input",
+ "change",
+ "increment",
+ "decrement"
+ ],
"profiled": false
},
{
@@ -680,7 +881,9 @@
"purpose": "Theme-aware, responsive kbd component.",
"demoCount": 3,
"propCount": 4,
- "slots": ["default"],
+ "slots": [
+ "default"
+ ],
"events": [],
"profiled": false
},
@@ -692,8 +895,14 @@
"purpose": "Theme-aware, responsive layout splitter component.",
"demoCount": 2,
"propCount": 7,
- "slots": ["start", "end", "default"],
- "events": ["sizeChange"],
+ "slots": [
+ "start",
+ "end",
+ "default"
+ ],
+ "events": [
+ "sizeChange"
+ ],
"profiled": true
},
{
@@ -704,8 +913,13 @@
"purpose": "Theme-aware, responsive legend indicator component.",
"demoCount": 3,
"propCount": 7,
- "slots": ["default"],
- "events": ["toggle", "select"],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "toggle",
+ "select"
+ ],
"profiled": false
},
{
@@ -716,7 +930,9 @@
"purpose": "Render an accessible internal or external link with target, relation, size, color, and public focus or click events.",
"demoCount": 3,
"propCount": 9,
- "slots": ["default"],
+ "slots": [
+ "default"
+ ],
"events": [],
"profiled": true
},
@@ -728,8 +944,12 @@
"purpose": "Present structured responsive linked or status items with icons, descriptions, actions, and selection events.",
"demoCount": 3,
"propCount": 7,
- "slots": ["default"],
- "events": [],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "select"
+ ],
"profiled": true
},
{
@@ -740,8 +960,13 @@
"purpose": "Theme-aware, responsive list group component.",
"demoCount": 3,
"propCount": 7,
- "slots": ["default"],
- "events": ["select", "change"],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "select",
+ "change"
+ ],
"profiled": false
},
{
@@ -752,8 +977,14 @@
"purpose": "Present responsive location information and markers with map-ready metadata and movement or marker events.",
"demoCount": 3,
"propCount": 7,
- "slots": ["default"],
- "events": [],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "markerClick",
+ "select",
+ "zoom"
+ ],
"profiled": true
},
{
@@ -764,7 +995,11 @@
"purpose": "Introduce marketing content with an eyebrow, title, description, and optional linked action.",
"demoCount": 3,
"propCount": 12,
- "slots": ["icon", "actions", "default"],
+ "slots": [
+ "icon",
+ "actions",
+ "default"
+ ],
"events": [],
"profiled": true
},
@@ -776,8 +1011,13 @@
"purpose": "Continuously present responsive labels, partners, notices, or capabilities with pause and resume behavior.",
"demoCount": 3,
"propCount": 7,
- "slots": ["default"],
- "events": [],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "pause",
+ "resume"
+ ],
"profiled": true
},
{
@@ -788,8 +1028,14 @@
"purpose": "Theme-aware, responsive mega menu component.",
"demoCount": 2,
"propCount": 8,
- "slots": ["default"],
- "events": ["open", "close", "select"],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "open",
+ "close",
+ "select"
+ ],
"profiled": true
},
{
@@ -800,8 +1046,14 @@
"purpose": "Display one operational metric with value, suffix, description, icon, trend, progress, and optional action.",
"demoCount": 3,
"propCount": 28,
- "slots": ["default", "footer"],
- "events": ["select", "action"],
+ "slots": [
+ "default",
+ "footer"
+ ],
+ "events": [
+ "select",
+ "action"
+ ],
"profiled": true
},
{
@@ -812,8 +1064,13 @@
"purpose": "Arrange operational metrics, KPIs, public statistics, or service indicators in a responsive equal-height grid.",
"demoCount": 3,
"propCount": 13,
- "slots": ["default"],
- "events": ["select", "action"],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "select",
+ "action"
+ ],
"profiled": true
},
{
@@ -824,8 +1081,18 @@
"purpose": "Present an accessible modal dialog with focus management, confirmation, cancellation, slots, and responsive sizing.",
"demoCount": 3,
"propCount": 29,
- "slots": ["trigger", "header", "default", "footer"],
- "events": ["open", "close", "cancel", "confirm"],
+ "slots": [
+ "trigger",
+ "header",
+ "default",
+ "footer"
+ ],
+ "events": [
+ "open",
+ "close",
+ "cancel",
+ "confirm"
+ ],
"profiled": true
},
{
@@ -836,8 +1103,12 @@
"purpose": "Theme-aware, responsive nav component.",
"demoCount": 3,
"propCount": 9,
- "slots": ["default"],
- "events": ["select"],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "select"
+ ],
"profiled": true
},
{
@@ -848,8 +1119,17 @@
"purpose": "Theme-aware, responsive navbar component.",
"demoCount": 3,
"propCount": 13,
- "slots": ["topbar", "actions"],
- "events": ["toggle", "open", "close", "select", "action"],
+ "slots": [
+ "topbar",
+ "actions"
+ ],
+ "events": [
+ "toggle",
+ "open",
+ "close",
+ "select",
+ "action"
+ ],
"profiled": true
},
{
@@ -860,7 +1140,11 @@
"purpose": "Introduce an internal or public page with breadcrumbs, icon, title, description, and primary or secondary actions.",
"demoCount": 3,
"propCount": 25,
- "slots": ["meta", "actions", "default"],
+ "slots": [
+ "meta",
+ "actions",
+ "default"
+ ],
"events": [],
"profiled": true
},
@@ -872,8 +1156,14 @@
"purpose": "Theme-aware, responsive pagination component.",
"demoCount": 3,
"propCount": 12,
- "slots": ["default"],
- "events": ["change", "previous", "next"],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "change",
+ "previous",
+ "next"
+ ],
"profiled": true
},
{
@@ -885,7 +1175,14 @@
"demoCount": 16,
"propCount": 26,
"slots": [],
- "events": ["input", "change", "complete", "paste", "clear", "error"],
+ "events": [
+ "input",
+ "change",
+ "complete",
+ "paste",
+ "clear",
+ "error"
+ ],
"profiled": false
},
{
@@ -896,8 +1193,18 @@
"purpose": "Display anchored supporting content with configurable trigger, placement, responsive sizing, and open or close events.",
"demoCount": 3,
"propCount": 23,
- "slots": ["trigger", "header", "default", "footer"],
- "events": ["toggle", "open", "close", "action"],
+ "slots": [
+ "trigger",
+ "header",
+ "default",
+ "footer"
+ ],
+ "events": [
+ "toggle",
+ "open",
+ "close",
+ "action"
+ ],
"profiled": true
},
{
@@ -908,8 +1215,13 @@
"purpose": "Reusable portal dashboard component.",
"demoCount": 3,
"propCount": 14,
- "slots": ["hero-action"],
- "events": ["action", "navigate"],
+ "slots": [
+ "hero-action"
+ ],
+ "events": [
+ "action",
+ "navigate"
+ ],
"profiled": false
},
{
@@ -921,7 +1233,11 @@
"demoCount": 3,
"propCount": 9,
"slots": [],
- "events": ["theme", "color", "language"],
+ "events": [
+ "theme",
+ "color",
+ "language"
+ ],
"profiled": false
},
{
@@ -944,7 +1260,11 @@
"purpose": "Provide the outer responsive structure, width, background, slots, overflow, and minimum-height behavior for public pages.",
"demoCount": 3,
"propCount": 10,
- "slots": ["before", "default", "after"],
+ "slots": [
+ "before",
+ "default",
+ "after"
+ ],
"events": [],
"profiled": true
},
@@ -957,7 +1277,13 @@
"demoCount": 3,
"propCount": 25,
"slots": [],
- "events": ["input", "change", "focus", "blur", "invalid"],
+ "events": [
+ "input",
+ "change",
+ "focus",
+ "blur",
+ "invalid"
+ ],
"profiled": false
},
{
@@ -969,7 +1295,12 @@
"demoCount": 3,
"propCount": 26,
"slots": [],
- "events": ["input", "change", "focus", "blur"],
+ "events": [
+ "input",
+ "change",
+ "focus",
+ "blur"
+ ],
"profiled": false
},
{
@@ -980,8 +1311,13 @@
"purpose": "Theme-aware, responsive rating component.",
"demoCount": 3,
"propCount": 7,
- "slots": ["default"],
- "events": ["input", "change"],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "input",
+ "change"
+ ],
"profiled": false
},
{
@@ -992,8 +1328,12 @@
"purpose": "Theme-aware, responsive scrollspy component.",
"demoCount": 2,
"propCount": 7,
- "slots": ["default"],
- "events": ["change"],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "change"
+ ],
"profiled": true
},
{
@@ -1005,7 +1345,10 @@
"demoCount": 3,
"propCount": 13,
"slots": [],
- "events": [],
+ "events": [
+ "search",
+ "clear"
+ ],
"profiled": true
},
{
@@ -1016,7 +1359,9 @@
"purpose": "Create a responsive themed page section with controlled spacing, width, borders, and surface treatment.",
"demoCount": 3,
"propCount": 10,
- "slots": ["default"],
+ "slots": [
+ "default"
+ ],
"events": [],
"profiled": true
},
@@ -1028,7 +1373,11 @@
"purpose": "Introduce a section with an eyebrow, title, description, alignment, and responsive heading hierarchy.",
"demoCount": 3,
"propCount": 10,
- "slots": ["icon", "default", "actions"],
+ "slots": [
+ "icon",
+ "default",
+ "actions"
+ ],
"events": [],
"profiled": true
},
@@ -1041,7 +1390,15 @@
"demoCount": 3,
"propCount": 22,
"slots": [],
- "events": ["input", "change", "focus", "blur", "open", "close", "invalid"],
+ "events": [
+ "input",
+ "change",
+ "focus",
+ "blur",
+ "open",
+ "close",
+ "invalid"
+ ],
"profiled": false
},
{
@@ -1052,8 +1409,16 @@
"purpose": "Theme-aware, responsive sidebar component.",
"demoCount": 2,
"propCount": 8,
- "slots": ["default", "drawer"],
- "events": ["toggle", "open", "close", "select"],
+ "slots": [
+ "default",
+ "drawer"
+ ],
+ "events": [
+ "toggle",
+ "open",
+ "close",
+ "select"
+ ],
"profiled": true
},
{
@@ -1088,7 +1453,12 @@
"purpose": "Build a responsive two-column introduction balancing descriptive content with a visual, image, or structured data panel.",
"demoCount": 3,
"propCount": 31,
- "slots": ["default", "actions", "trust", "visual"],
+ "slots": [
+ "default",
+ "actions",
+ "trust",
+ "visual"
+ ],
"events": [],
"profiled": true
},
@@ -1112,8 +1482,18 @@
"purpose": "Theme-aware, responsive stepper component.",
"demoCount": 5,
"propCount": 16,
- "slots": ["step-{index}", "panel-{index}", "default"],
- "events": ["change", "back", "next", "skip", "finish"],
+ "slots": [
+ "step-{index}",
+ "panel-{index}",
+ "default"
+ ],
+ "events": [
+ "change",
+ "back",
+ "next",
+ "skip",
+ "finish"
+ ],
"profiled": true
},
{
@@ -1125,7 +1505,11 @@
"demoCount": 6,
"propCount": 27,
"slots": [],
- "events": ["input", "change", "strength"],
+ "events": [
+ "input",
+ "change",
+ "strength"
+ ],
"profiled": false
},
{
@@ -1136,7 +1520,9 @@
"purpose": "Theme-aware, responsive styled icon component.",
"demoCount": 3,
"propCount": 7,
- "slots": ["default"],
+ "slots": [
+ "default"
+ ],
"events": [],
"profiled": false
},
@@ -1149,7 +1535,12 @@
"demoCount": 3,
"propCount": 20,
"slots": [],
- "events": ["input", "change", "focus", "blur"],
+ "events": [
+ "input",
+ "change",
+ "focus",
+ "blur"
+ ],
"profiled": false
},
{
@@ -1160,8 +1551,14 @@
"purpose": "Switch between related responsive content panels with horizontal or vertical orientation and selection events.",
"demoCount": 4,
"propCount": 9,
- "slots": ["panel-{valueOf(item, index)}", "default"],
- "events": ["change", "select"],
+ "slots": [
+ "panel-{valueOf(item, index)}",
+ "default"
+ ],
+ "events": [
+ "change",
+ "select"
+ ],
"profiled": true
},
{
@@ -1173,7 +1570,11 @@
"demoCount": 3,
"propCount": 14,
"slots": [],
- "events": ["click", "focus", "blur"],
+ "events": [
+ "click",
+ "focus",
+ "blur"
+ ],
"profiled": true
},
{
@@ -1185,7 +1586,13 @@
"demoCount": 3,
"propCount": 23,
"slots": [],
- "events": ["input", "change", "focus", "blur", "invalid"],
+ "events": [
+ "input",
+ "change",
+ "focus",
+ "blur",
+ "invalid"
+ ],
"profiled": false
},
{
@@ -1197,7 +1604,15 @@
"demoCount": 3,
"propCount": 26,
"slots": [],
- "events": ["input", "change", "focus", "blur", "open", "close", "invalid"],
+ "events": [
+ "input",
+ "change",
+ "focus",
+ "blur",
+ "open",
+ "close",
+ "invalid"
+ ],
"profiled": false
},
{
@@ -1208,34 +1623,14 @@
"purpose": "Present responsive chronological activity, milestones, or workflow status with rich item metadata.",
"demoCount": 3,
"propCount": 7,
- "slots": ["default"],
- "events": [],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "select"
+ ],
"profiled": true
},
- {
- "name": "Toast",
- "mount": "Toast",
- "slug": "toast",
- "category": "base",
- "purpose": "Theme-aware, responsive toast component.",
- "demoCount": 3,
- "propCount": 7,
- "slots": ["default"],
- "events": ["dismiss", "action"],
- "profiled": false
- },
- {
- "name": "ToastNotifications",
- "mount": "ToastNotifications",
- "slug": "toast-notifications",
- "category": "integrations",
- "purpose": "Theme-aware, responsive toast notifications component.",
- "demoCount": 3,
- "propCount": 7,
- "slots": ["default"],
- "events": ["add", "dismiss", "clear", "action"],
- "profiled": false
- },
{
"name": "Toaster",
"mount": "Toaster",
@@ -1245,7 +1640,11 @@
"demoCount": 1,
"propCount": 15,
"slots": [],
- "events": ["show", "dismiss", "action"],
+ "events": [
+ "show",
+ "dismiss",
+ "action"
+ ],
"profiled": true
},
{
@@ -1257,7 +1656,10 @@
"demoCount": 3,
"propCount": 23,
"slots": [],
- "events": ["change", "toggle"],
+ "events": [
+ "change",
+ "toggle"
+ ],
"profiled": false
},
{
@@ -1269,7 +1671,11 @@
"demoCount": 10,
"propCount": 24,
"slots": [],
- "events": ["input", "change", "toggle"],
+ "events": [
+ "input",
+ "change",
+ "toggle"
+ ],
"profiled": false
},
{
@@ -1280,8 +1686,15 @@
"purpose": "Show concise accessible contextual help on hover, focus, click, or controlled open state.",
"demoCount": 3,
"propCount": 17,
- "slots": ["trigger", "default"],
- "events": ["toggle", "open", "close"],
+ "slots": [
+ "trigger",
+ "default"
+ ],
+ "events": [
+ "toggle",
+ "open",
+ "close"
+ ],
"profiled": true
},
{
@@ -1291,9 +1704,16 @@
"category": "base",
"purpose": "Theme-aware, responsive tree view component.",
"demoCount": 3,
- "propCount": 7,
- "slots": ["default"],
- "events": ["select", "toggle", "expand", "collapse"],
+ "propCount": 10,
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "select",
+ "toggle",
+ "expand",
+ "collapse"
+ ],
"profiled": false
},
{
@@ -1304,7 +1724,9 @@
"purpose": "Apply consistent readable responsive typography, widths, columns, spacing, and editorial hierarchy.",
"demoCount": 3,
"propCount": 6,
- "slots": ["default"],
+ "slots": [
+ "default"
+ ],
"events": [],
"profiled": true
},
@@ -1316,8 +1738,15 @@
"purpose": "Theme-aware, responsive wysiwyg editor component.",
"demoCount": 3,
"propCount": 7,
- "slots": ["default"],
- "events": ["input", "change", "focus", "blur"],
+ "slots": [
+ "default"
+ ],
+ "events": [
+ "input",
+ "change",
+ "focus",
+ "blur"
+ ],
"profiled": false
}
]
diff --git a/packages/compiler/test/compiler.test.ts b/packages/compiler/test/compiler.test.ts
index 06e6acb0..43bec4e1 100644
--- a/packages/compiler/test/compiler.test.ts
+++ b/packages/compiler/test/compiler.test.ts
@@ -1499,3 +1499,24 @@ test("a boolean attribute bound to a loop variable binds on the client", () => {
expect(code).not.toContain('__wireBooleanAttr("checked"');
expect(code).toContain("data-wrn-bind-");
});
+
+test("block comments inside props report the authoring restriction", () => {
+ expect(() =>
+ compileWireFile(`component Example {
+ props {
+ /* use a line comment */
+ label: string = "Example"
+ }
+ view {
{label} }
+ }`),
+ ).toThrow("Block comments are not allowed inside props {}; use // line comments instead");
+});
+
+test("state page reports its collision with the page keyword", () => {
+ expect(() =>
+ compileWireFile(`page Example {
+ state page = 1
+ view {
{page} }
+ }`),
+ ).toThrow("State name 'page' collides with the WRN 'page' keyword");
+});
diff --git a/packages/syntax/src/parser.ts b/packages/syntax/src/parser.ts
index 7b53b2e8..c5ce52bf 100644
--- a/packages/syntax/src/parser.ts
+++ b/packages/syntax/src/parser.ts
@@ -439,7 +439,14 @@ export function parse(source: string): PageAst {
// props { name: Type =
; @event name = function }
lx.next();
expect("lbrace");
- while (lx.peek().type !== "rbrace") {
+ while (true) {
+ if (lx.startsWithBlockComment()) {
+ throw new ParseError(
+ "Block comments are not allowed inside props {}; use // line comments instead",
+ "WRN-PROPS-BLOCK-COMMENT",
+ );
+ }
+ if (lx.peek().type === "rbrace") break;
const t = lx.peek();
if (t.type === "eof") throw new ParseError("Unexpected end of input inside props");
if (t.type === "at") {
@@ -829,6 +836,13 @@ export function parse(source: string): PageAst {
const declaredStates = new Set(states.map((state) => state.name));
+ if (declaredStates.has("page")) {
+ throw new ParseError(
+ "State name 'page' collides with the WRN 'page' keyword; choose another state name",
+ "WRN-STATE-RESERVED-NAME",
+ );
+ }
+
for (const watcher of watches) {
if (!declaredStates.has(watcher.state)) {
throw new ParseError(`Cannot watch undeclared state '${watcher.state}'`);
diff --git a/packages/syntax/src/tokenizer.ts b/packages/syntax/src/tokenizer.ts
index c3f2b58e..2ee3e713 100644
--- a/packages/syntax/src/tokenizer.ts
+++ b/packages/syntax/src/tokenizer.ts
@@ -55,6 +55,12 @@ export class Lexer {
}
}
+ /** True when the next non-trivia characters open a block comment. */
+ startsWithBlockComment(): boolean {
+ this.skipTrivia();
+ return this.src[this.pos] === "/" && this.src[this.pos + 1] === "*";
+ }
+
/** Read and consume the next structural token. */
next(): Token {
this.skipTrivia();