release: WRNexusJS 0.6.0
This commit is contained in:
@@ -81,6 +81,11 @@
|
|||||||
"category": "base",
|
"category": "base",
|
||||||
"purpose": "Theme-aware, responsive button group component."
|
"purpose": "Theme-aware, responsive button group component."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "CTASection",
|
||||||
|
"category": "marketing",
|
||||||
|
"purpose": "Close a page or major section with conversion-focused copy, actions, and optional supporting visual content."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Card",
|
"name": "Card",
|
||||||
"category": "base",
|
"category": "base",
|
||||||
@@ -151,11 +156,6 @@
|
|||||||
"category": "advanced-forms",
|
"category": "advanced-forms",
|
||||||
"purpose": "Theme-aware, responsive copy markup component."
|
"purpose": "Theme-aware, responsive copy markup component."
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "CTASection",
|
|
||||||
"category": "marketing",
|
|
||||||
"purpose": "Close a page or major section with conversion-focused copy, actions, and optional supporting visual content."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "CustomScrollbar",
|
"name": "CustomScrollbar",
|
||||||
"category": "layout",
|
"category": "layout",
|
||||||
@@ -481,26 +481,26 @@
|
|||||||
"category": "navigation",
|
"category": "navigation",
|
||||||
"purpose": "Switch between related responsive content panels with horizontal or vertical orientation and selection events."
|
"purpose": "Switch between related responsive content panels with horizontal or vertical orientation and selection events."
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Textarea",
|
|
||||||
"category": "forms",
|
|
||||||
"purpose": "Theme-aware, responsive textarea component."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "TextLink",
|
"name": "TextLink",
|
||||||
"category": "marketing",
|
"category": "marketing",
|
||||||
"purpose": "Render an accessible text action with optional icon, arrow, underline, external state, and semantic styling."
|
"purpose": "Render an accessible text action with optional icon, arrow, underline, external state, and semantic styling."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Timeline",
|
"name": "Textarea",
|
||||||
"category": "base",
|
"category": "forms",
|
||||||
"purpose": "Present responsive chronological activity, milestones, or workflow status with rich item metadata."
|
"purpose": "Theme-aware, responsive textarea component."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "TimePicker",
|
"name": "TimePicker",
|
||||||
"category": "forms",
|
"category": "forms",
|
||||||
"purpose": "Theme-aware, responsive time picker component."
|
"purpose": "Theme-aware, responsive time picker component."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Timeline",
|
||||||
|
"category": "base",
|
||||||
|
"purpose": "Present responsive chronological activity, milestones, or workflow status with rich item metadata."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Toast",
|
"name": "Toast",
|
||||||
"category": "base",
|
"category": "base",
|
||||||
|
|||||||
@@ -2278,6 +2278,193 @@
|
|||||||
"events": ["click", "select", "change"],
|
"events": ["click", "select", "change"],
|
||||||
"source": "components/ButtonGroup.wrn"
|
"source": "components/ButtonGroup.wrn"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "CTASection",
|
||||||
|
"mount": "CTASection",
|
||||||
|
"category": "marketing",
|
||||||
|
"purpose": "Close a page or major section with conversion-focused copy, actions, and optional supporting visual content.",
|
||||||
|
"props": [
|
||||||
|
{
|
||||||
|
"name": "eyebrow",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "title",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"Ready to get started?\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "description",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "icon",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "align",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"center\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "size",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "color",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"primary\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "variant",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"solid\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "primaryLabel",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"Get started\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "primaryHref",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"#\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "primaryIcon",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "secondaryLabel",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "secondaryHref",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "secondaryIcon",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "backgroundImage",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "visualImage",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "visualAlt",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "visualIcon",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "visualTitle",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "visualDescription",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "visualItems",
|
||||||
|
"type": "unknown[]",
|
||||||
|
"required": false,
|
||||||
|
"default": "[]",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "visualPosition",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"right\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "maxWidth",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"xl\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fullBleed",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "class",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"slots": ["default", "actions", "visual", "footer"],
|
||||||
|
"outputs": [],
|
||||||
|
"events": [],
|
||||||
|
"source": "components/CTASection.wrn"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Card",
|
"name": "Card",
|
||||||
"mount": "Card",
|
"mount": "Card",
|
||||||
@@ -4250,193 +4437,6 @@
|
|||||||
"events": ["copy", "success", "error"],
|
"events": ["copy", "success", "error"],
|
||||||
"source": "components/CopyMarkup.wrn"
|
"source": "components/CopyMarkup.wrn"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "CTASection",
|
|
||||||
"mount": "CTASection",
|
|
||||||
"category": "marketing",
|
|
||||||
"purpose": "Close a page or major section with conversion-focused copy, actions, and optional supporting visual content.",
|
|
||||||
"props": [
|
|
||||||
{
|
|
||||||
"name": "eyebrow",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "title",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"Ready to get started?\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "description",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "icon",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "align",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"center\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "size",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"default\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "color",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"primary\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "variant",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"solid\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "primaryLabel",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"Get started\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "primaryHref",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"#\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "primaryIcon",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "secondaryLabel",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "secondaryHref",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "secondaryIcon",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "backgroundImage",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "visualImage",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "visualAlt",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "visualIcon",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "visualTitle",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "visualDescription",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "visualItems",
|
|
||||||
"type": "unknown[]",
|
|
||||||
"required": false,
|
|
||||||
"default": "[]",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "visualPosition",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"right\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "maxWidth",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"xl\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "fullBleed",
|
|
||||||
"type": "boolean",
|
|
||||||
"required": false,
|
|
||||||
"default": "false",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "class",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"slots": ["default", "actions", "visual", "footer"],
|
|
||||||
"outputs": [],
|
|
||||||
"events": [],
|
|
||||||
"source": "components/CTASection.wrn"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "CustomScrollbar",
|
"name": "CustomScrollbar",
|
||||||
"mount": "CustomScrollbar",
|
"mount": "CustomScrollbar",
|
||||||
@@ -12144,6 +12144,129 @@
|
|||||||
"events": [],
|
"events": [],
|
||||||
"source": "components/Tabs.wrn"
|
"source": "components/Tabs.wrn"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "TextLink",
|
||||||
|
"mount": "TextLink",
|
||||||
|
"category": "marketing",
|
||||||
|
"purpose": "Render an accessible text action with optional icon, arrow, underline, external state, and semantic styling.",
|
||||||
|
"props": [
|
||||||
|
{
|
||||||
|
"name": "label",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"Learn more\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "href",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"#\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "target",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "rel",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "external",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "icon",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "iconPosition",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"start\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "showArrow",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "true",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "underline",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "size",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "color",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"primary\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "variant",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "disabled",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "class",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"slots": [],
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "click",
|
||||||
|
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "focus",
|
||||||
|
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "blur",
|
||||||
|
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"events": ["click", "focus", "blur"],
|
||||||
|
"source": "components/TextLink.wrn"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Textarea",
|
"name": "Textarea",
|
||||||
"mount": "Textarea",
|
"mount": "Textarea",
|
||||||
@@ -12338,190 +12461,6 @@
|
|||||||
"events": ["input", "change", "focus", "blur", "invalid"],
|
"events": ["input", "change", "focus", "blur", "invalid"],
|
||||||
"source": "components/Textarea.wrn"
|
"source": "components/Textarea.wrn"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "TextLink",
|
|
||||||
"mount": "TextLink",
|
|
||||||
"category": "marketing",
|
|
||||||
"purpose": "Render an accessible text action with optional icon, arrow, underline, external state, and semantic styling.",
|
|
||||||
"props": [
|
|
||||||
{
|
|
||||||
"name": "label",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"Learn more\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "href",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"#\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "target",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "rel",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "external",
|
|
||||||
"type": "boolean",
|
|
||||||
"required": false,
|
|
||||||
"default": "false",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "icon",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "iconPosition",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"start\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "showArrow",
|
|
||||||
"type": "boolean",
|
|
||||||
"required": false,
|
|
||||||
"default": "true",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "underline",
|
|
||||||
"type": "boolean",
|
|
||||||
"required": false,
|
|
||||||
"default": "false",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "size",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"default\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "color",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"primary\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "variant",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"default\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "disabled",
|
|
||||||
"type": "boolean",
|
|
||||||
"required": false,
|
|
||||||
"default": "false",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "class",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"slots": [],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "click",
|
|
||||||
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "focus",
|
|
||||||
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "blur",
|
|
||||||
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"events": ["click", "focus", "blur"],
|
|
||||||
"source": "components/TextLink.wrn"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Timeline",
|
|
||||||
"mount": "Timeline",
|
|
||||||
"category": "base",
|
|
||||||
"purpose": "Present responsive chronological activity, milestones, or workflow status with rich item metadata.",
|
|
||||||
"props": [
|
|
||||||
{
|
|
||||||
"name": "size",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"default\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "color",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"primary\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "title",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"Timeline\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "description",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "items",
|
|
||||||
"type": "unknown[]",
|
|
||||||
"required": false,
|
|
||||||
"default": "[]",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "variant",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"default\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "class",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"slots": ["default"],
|
|
||||||
"outputs": [],
|
|
||||||
"events": [],
|
|
||||||
"source": "components/Timeline.wrn"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "TimePicker",
|
"name": "TimePicker",
|
||||||
"mount": "TimePicker",
|
"mount": "TimePicker",
|
||||||
@@ -12745,6 +12684,67 @@
|
|||||||
"events": ["input", "change", "focus", "blur", "open", "close", "invalid"],
|
"events": ["input", "change", "focus", "blur", "open", "close", "invalid"],
|
||||||
"source": "components/TimePicker.wrn"
|
"source": "components/TimePicker.wrn"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Timeline",
|
||||||
|
"mount": "Timeline",
|
||||||
|
"category": "base",
|
||||||
|
"purpose": "Present responsive chronological activity, milestones, or workflow status with rich item metadata.",
|
||||||
|
"props": [
|
||||||
|
{
|
||||||
|
"name": "size",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "color",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"primary\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "title",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"Timeline\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "description",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "items",
|
||||||
|
"type": "unknown[]",
|
||||||
|
"required": false,
|
||||||
|
"default": "[]",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "variant",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "class",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"slots": ["default"],
|
||||||
|
"outputs": [],
|
||||||
|
"events": [],
|
||||||
|
"source": "components/Timeline.wrn"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Toast",
|
"name": "Toast",
|
||||||
"mount": "Toast",
|
"mount": "Toast",
|
||||||
|
|||||||
@@ -399,3 +399,9 @@ Comparison base: `WRNexusJS(4).zip`. Dependency directories, `.git`, and `.wrnex
|
|||||||
- Corrected the compiler regression test export-stripping regex from an over-escaped literal `\\s` match to the intended whitespace `\s` match.
|
- Corrected the compiler regression test export-stripping regex from an over-escaped literal `\\s` match to the intended whitespace `\s` match.
|
||||||
- Confirmed the generated peer-function browser module executes and updates shared state from `0` to `1`.
|
- Confirmed the generated peer-function browser module executes and updates shared state from `0` to `1`.
|
||||||
- Added a release validator guard for the exact test source regression.
|
- Added a release validator guard for the exact test source regression.
|
||||||
|
|
||||||
|
## R12 release reference gate
|
||||||
|
|
||||||
|
- Fixed false stale component-reference failures on Windows/autocrlf checkouts.
|
||||||
|
- The release gate now uses canonical Git diffs and validates all three generated UI reference files.
|
||||||
|
- Component-reference ordering is deterministic across operating systems and locales.
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# R12 release reference gate fix
|
||||||
|
|
||||||
|
## Failure
|
||||||
|
|
||||||
|
`bun run scripts/release.ts publish` could stop with:
|
||||||
|
|
||||||
|
```text
|
||||||
|
UI component reference is stale.
|
||||||
|
M packages/ui/component-reference.json
|
||||||
|
```
|
||||||
|
|
||||||
|
even when the generated content was current.
|
||||||
|
|
||||||
|
## Root cause
|
||||||
|
|
||||||
|
The release gate used `git status --short` immediately after the generator ran. On Windows, generated files are written with LF while an `autocrlf` checkout may use CRLF. Git status can report the worktree file as modified even when its canonical Git content is unchanged.
|
||||||
|
|
||||||
|
The generator also writes `component-catalog.json`, but that file was not part of the release gate. Component ordering used `localeCompare`, which can vary by operating-system locale.
|
||||||
|
|
||||||
|
## Fix
|
||||||
|
|
||||||
|
- Compare generated files with `git diff --quiet`, which applies Git text normalization.
|
||||||
|
- Show real differences with `git diff --name-status`.
|
||||||
|
- Include all generated UI reference files:
|
||||||
|
- `packages/ui/component-catalog.json`
|
||||||
|
- `packages/ui/component-reference.json`
|
||||||
|
- `packages/ui/COMPONENTS.md`
|
||||||
|
- Replace locale-dependent sorting with a deterministic ASCII comparator.
|
||||||
|
- Add validation guards for the complete release gate.
|
||||||
|
|
||||||
|
## Expected result
|
||||||
|
|
||||||
|
A line-ending-only rewrite does not block publication. A real component-reference, catalog, or documentation difference still blocks publication and prints the exact changed files.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"releaseReferenceGate": {
|
||||||
|
"deterministicGeneration": true,
|
||||||
|
"lineEndingOnlyDiffIgnored": true,
|
||||||
|
"regeneratedReferenceClean": true,
|
||||||
|
"realContentDifferenceDetected": true,
|
||||||
|
"generatedFiles": [
|
||||||
|
"packages/ui/component-catalog.json",
|
||||||
|
"packages/ui/component-reference.json",
|
||||||
|
"packages/ui/COMPONENTS.md"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"validation": {
|
||||||
|
"passes": 20,
|
||||||
|
"warnings": 1,
|
||||||
|
"failures": 0,
|
||||||
|
"warning": "Bun is unavailable in the packaging environment; run the full Bun check locally."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,3 +36,7 @@ This archive also includes the focused fixes for generated browser identifier sa
|
|||||||
- Nested peer calls no longer have their state changes overwritten by stale outer aliases.
|
- Nested peer calls no longer have their state changes overwritten by stale outer aliases.
|
||||||
- Synchronous, asynchronous, and throwing peer calls refresh shared state correctly.
|
- Synchronous, asynchronous, and throwing peer calls refresh shared state correctly.
|
||||||
- Added an executable `validate:0.6` regression probe for the exact compiler failure.
|
- Added an executable `validate:0.6` regression probe for the exact compiler failure.
|
||||||
|
|
||||||
|
### R12 release workflow correction
|
||||||
|
|
||||||
|
The private publish workflow now compares generated UI reference files using canonical Git diffs, includes the component catalog, and uses platform-independent generator ordering. This prevents line-ending-only rewrites from being reported as stale references on Windows.
|
||||||
|
|||||||
@@ -100,3 +100,9 @@ The complete `bun run check` command remains the authoritative local release gat
|
|||||||
- Nested peer calls no longer have their state changes overwritten by stale outer aliases.
|
- Nested peer calls no longer have their state changes overwritten by stale outer aliases.
|
||||||
- Synchronous, asynchronous, and throwing peer calls refresh shared state correctly.
|
- Synchronous, asynchronous, and throwing peer calls refresh shared state correctly.
|
||||||
- Added an executable `validate:0.6` regression probe for the exact compiler failure.
|
- Added an executable `validate:0.6` regression probe for the exact compiler failure.
|
||||||
|
|
||||||
|
## R12 release-reference validation
|
||||||
|
|
||||||
|
- Release verification uses `git diff --quiet` instead of `git status --short` for generated UI references.
|
||||||
|
- `component-catalog.json`, `component-reference.json`, and `COMPONENTS.md` are all covered.
|
||||||
|
- Generator ordering no longer depends on `localeCompare`.
|
||||||
|
|||||||
+69
-324
@@ -145,51 +145,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||||||
exports.generateBrowserModule = generateBrowserModule;
|
exports.generateBrowserModule = generateBrowserModule;
|
||||||
const syntax_1 = require("@wrnexus/syntax");
|
const syntax_1 = require("@wrnexus/syntax");
|
||||||
const RESERVED_BINDINGS = new Set([
|
const RESERVED_BINDINGS = new Set([
|
||||||
"await",
|
"await", "break", "case", "catch", "class", "const", "continue", "debugger",
|
||||||
"break",
|
"default", "delete", "do", "else", "enum", "export", "extends", "false",
|
||||||
"case",
|
"finally", "for", "function", "if", "implements", "import", "in",
|
||||||
"catch",
|
"instanceof", "interface", "let", "new", "null", "package", "private",
|
||||||
"class",
|
"protected", "public", "return", "static", "super", "switch", "this",
|
||||||
"const",
|
"throw", "true", "try", "typeof", "var", "void", "while", "with",
|
||||||
"continue",
|
|
||||||
"debugger",
|
|
||||||
"default",
|
|
||||||
"delete",
|
|
||||||
"do",
|
|
||||||
"else",
|
|
||||||
"enum",
|
|
||||||
"export",
|
|
||||||
"extends",
|
|
||||||
"false",
|
|
||||||
"finally",
|
|
||||||
"for",
|
|
||||||
"function",
|
|
||||||
"if",
|
|
||||||
"implements",
|
|
||||||
"import",
|
|
||||||
"in",
|
|
||||||
"instanceof",
|
|
||||||
"interface",
|
|
||||||
"let",
|
|
||||||
"new",
|
|
||||||
"null",
|
|
||||||
"package",
|
|
||||||
"private",
|
|
||||||
"protected",
|
|
||||||
"public",
|
|
||||||
"return",
|
|
||||||
"static",
|
|
||||||
"super",
|
|
||||||
"switch",
|
|
||||||
"this",
|
|
||||||
"throw",
|
|
||||||
"true",
|
|
||||||
"try",
|
|
||||||
"typeof",
|
|
||||||
"var",
|
|
||||||
"void",
|
|
||||||
"while",
|
|
||||||
"with",
|
|
||||||
"yield",
|
"yield",
|
||||||
]);
|
]);
|
||||||
const RUNTIME_BINDINGS = new Set([
|
const RUNTIME_BINDINGS = new Set([
|
||||||
@@ -231,7 +192,9 @@ function functionEntry(ast, fn, availableFunctions) {
|
|||||||
: "";
|
: "";
|
||||||
const stateAliases = stateNames.length ? `let { ${stateNames.join(", ")} } = context.state;` : "";
|
const stateAliases = stateNames.length ? `let { ${stateNames.join(", ")} } = context.state;` : "";
|
||||||
const propAliases = propNames.length ? `const { ${propNames.join(", ")} } = context.props;` : "";
|
const propAliases = propNames.length ? `const { ${propNames.join(", ")} } = context.props;` : "";
|
||||||
const syncStateToContext = stateNames.map((name) => `context.state.${name} = ${name};`).join(" ");
|
const syncStateToContext = stateNames
|
||||||
|
.map((name) => `context.state.${name} = ${name};`)
|
||||||
|
.join(" ");
|
||||||
const syncStateFromContext = stateNames
|
const syncStateFromContext = stateNames
|
||||||
.map((name) => `${name} = context.state.${name};`)
|
.map((name) => `${name} = context.state.${name};`)
|
||||||
.join(" ");
|
.join(" ");
|
||||||
@@ -267,9 +230,7 @@ function functionEntry(ast, fn, availableFunctions) {
|
|||||||
!parameterNames.has("server") ? "const server = context.server;" : "",
|
!parameterNames.has("server") ? "const server = context.server;" : "",
|
||||||
!parameterNames.has("props") ? "const props = context.props;" : "",
|
!parameterNames.has("props") ? "const props = context.props;" : "",
|
||||||
!parameterNames.has("refs") ? "const refs = context.refs;" : "",
|
!parameterNames.has("refs") ? "const refs = context.refs;" : "",
|
||||||
]
|
].filter(Boolean).join("\n ");
|
||||||
.filter(Boolean)
|
|
||||||
.join("\n ");
|
|
||||||
return `${JSON.stringify(fn.name)}: ${fn.async ? "async " : ""}function(context${parameters ? `, ${parameters}` : ""}) {
|
return `${JSON.stringify(fn.name)}: ${fn.async ? "async " : ""}function(context${parameters ? `, ${parameters}` : ""}) {
|
||||||
${initialStateSnapshot}
|
${initialStateSnapshot}
|
||||||
${stateAliases}
|
${stateAliases}
|
||||||
@@ -287,19 +248,18 @@ function generateBrowserModule(ast) {
|
|||||||
const functions = ast.runtimeFunctions.filter((fn) => ["legacy", "client", "shared"].includes(fn.runtime));
|
const functions = ast.runtimeFunctions.filter((fn) => ["legacy", "client", "shared"].includes(fn.runtime));
|
||||||
const functionNames = functions.map((fn) => fn.name);
|
const functionNames = functions.map((fn) => fn.name);
|
||||||
const state = ast.states.filter((entry) => entry.runtime !== "server").map((entry) => entry.name);
|
const state = ast.states.filter((entry) => entry.runtime !== "server").map((entry) => entry.name);
|
||||||
const storeImports = ast.structuredImports.filter((entry) => !entry.typeOnly && entry.source.endsWith(".wrn") && /(?:^|\/)stores?\//.test(entry.source));
|
const storeImports = ast.structuredImports
|
||||||
|
.filter((entry) => !entry.typeOnly && entry.source.endsWith(".wrn") && /(?:^|\/)stores?\//.test(entry.source));
|
||||||
const imports = ast.structuredImports
|
const imports = ast.structuredImports
|
||||||
.filter((entry) => !entry.typeOnly)
|
.filter((entry) => !entry.typeOnly)
|
||||||
.filter((entry) => !entry.source.endsWith(".wrn") || /(?:^|\/)stores?\//.test(entry.source))
|
.filter((entry) => !entry.source.endsWith(".wrn") || /(?:^|\/)stores?\//.test(entry.source))
|
||||||
.map((entry) => entry.raw)
|
.map((entry) => entry.raw)
|
||||||
.join("\n");
|
.join("\n");
|
||||||
const importedBindings = storeImports
|
const importedBindings = storeImports.flatMap((entry) => [
|
||||||
.flatMap((entry) => [
|
|
||||||
...(entry.defaultImport ? [entry.defaultImport] : []),
|
...(entry.defaultImport ? [entry.defaultImport] : []),
|
||||||
...(entry.namespaceImport ? [entry.namespaceImport] : []),
|
...(entry.namespaceImport ? [entry.namespaceImport] : []),
|
||||||
...entry.namedImports.map((item) => item.local),
|
...entry.namedImports.map((item) => item.local),
|
||||||
])
|
]).filter(safeIdentifier);
|
||||||
.filter(safeIdentifier);
|
|
||||||
return `// generated WRNexusJS browser module for ${ast.name}
|
return `// generated WRNexusJS browser module for ${ast.name}
|
||||||
${imports}
|
${imports}
|
||||||
export const __wrnexusClientFunctions = {
|
export const __wrnexusClientFunctions = {
|
||||||
@@ -994,12 +954,7 @@ function targetFunctions(ast, target) {
|
|||||||
.join("\n\n");
|
.join("\n\n");
|
||||||
}
|
}
|
||||||
function publicOutputNames(ast) {
|
function publicOutputNames(ast) {
|
||||||
return [
|
return [...new Set([...ast.outputs.map((output) => output.name), ...ast.events.map((event) => event.name)])];
|
||||||
...new Set([
|
|
||||||
...ast.outputs.map((output) => output.name),
|
|
||||||
...ast.events.map((event) => event.name),
|
|
||||||
]),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
function generate(ast) {
|
function generate(ast) {
|
||||||
if (ast.kind === "global-store" || ast.kind === "page-store")
|
if (ast.kind === "global-store" || ast.kind === "page-store")
|
||||||
@@ -1700,7 +1655,9 @@ function generateComponent(ast) {
|
|||||||
};
|
};
|
||||||
const ctx = {
|
const ctx = {
|
||||||
stateNames,
|
stateNames,
|
||||||
functionNames: new Set(ast.runtimeFunctions.filter((fn) => fn.runtime !== "server").map((fn) => fn.name)),
|
functionNames: new Set(ast.runtimeFunctions
|
||||||
|
.filter((fn) => fn.runtime !== "server")
|
||||||
|
.map((fn) => fn.name)),
|
||||||
resolveExpr,
|
resolveExpr,
|
||||||
eventNames: publicOutputNames(ast),
|
eventNames: publicOutputNames(ast),
|
||||||
};
|
};
|
||||||
@@ -2067,11 +2024,7 @@ exports.createComponentContract = createComponentContract;
|
|||||||
function unionOptions(type) {
|
function unionOptions(type) {
|
||||||
if (!type || !type.includes("|"))
|
if (!type || !type.includes("|"))
|
||||||
return undefined;
|
return undefined;
|
||||||
const values = type
|
const values = type.split("|").map((part) => part.trim()).filter((part) => /^(?:"[^"]*"|'[^']*')$/.test(part)).map((part) => part.slice(1, -1));
|
||||||
.split("|")
|
|
||||||
.map((part) => part.trim())
|
|
||||||
.filter((part) => /^(?:"[^"]*"|'[^']*')$/.test(part))
|
|
||||||
.map((part) => part.slice(1, -1));
|
|
||||||
return values.length ? values : undefined;
|
return values.length ? values : undefined;
|
||||||
}
|
}
|
||||||
function createComponentContract(ast) {
|
function createComponentContract(ast) {
|
||||||
@@ -2087,32 +2040,17 @@ function createComponentContract(ast) {
|
|||||||
})),
|
})),
|
||||||
outputs: ast.outputs.map((output) => ({
|
outputs: ast.outputs.map((output) => ({
|
||||||
name: output.name,
|
name: output.name,
|
||||||
...(output.payload
|
...(output.payload ? { payloadName: output.payload.name, payloadType: output.payload.valueType } : {}),
|
||||||
? { payloadName: output.payload.name, payloadType: output.payload.valueType }
|
|
||||||
: {}),
|
|
||||||
})),
|
})),
|
||||||
functions: ast.runtimeFunctions.map((fn) => ({
|
functions: ast.runtimeFunctions.map((fn) => ({
|
||||||
name: fn.name,
|
name: fn.name,
|
||||||
runtime: fn.runtime,
|
runtime: fn.runtime,
|
||||||
async: fn.async,
|
async: fn.async,
|
||||||
parameters: fn.parameters.map((param) => ({
|
parameters: fn.parameters.map((param) => ({ name: param.name, type: param.valueType ?? "unknown", optional: param.optional })),
|
||||||
name: param.name,
|
|
||||||
type: param.valueType ?? "unknown",
|
|
||||||
optional: param.optional,
|
|
||||||
})),
|
|
||||||
returnType: fn.returnType ?? (fn.async ? "Promise<unknown>" : "unknown"),
|
returnType: fn.returnType ?? (fn.async ? "Promise<unknown>" : "unknown"),
|
||||||
})),
|
})),
|
||||||
states: ast.states.map((state) => ({
|
states: ast.states.map((state) => ({ name: state.name, runtime: state.runtime, type: state.valueType ?? "unknown", initializer: state.expr })),
|
||||||
name: state.name,
|
computed: ast.computed.map((entry) => ({ name: entry.name, type: entry.valueType ?? "unknown", expression: entry.expr })),
|
||||||
runtime: state.runtime,
|
|
||||||
type: state.valueType ?? "unknown",
|
|
||||||
initializer: state.expr,
|
|
||||||
})),
|
|
||||||
computed: ast.computed.map((entry) => ({
|
|
||||||
name: entry.name,
|
|
||||||
type: entry.valueType ?? "unknown",
|
|
||||||
expression: entry.expr,
|
|
||||||
})),
|
|
||||||
imports: ast.structuredImports.map((entry) => ({
|
imports: ast.structuredImports.map((entry) => ({
|
||||||
source: entry.source,
|
source: entry.source,
|
||||||
typeOnly: entry.typeOnly,
|
typeOnly: entry.typeOnly,
|
||||||
@@ -2131,37 +2069,19 @@ exports.resolveWrnImports = resolveWrnImports;
|
|||||||
const node_fs_1 = require("node:fs");
|
const node_fs_1 = require("node:fs");
|
||||||
const node_path_1 = require("node:path");
|
const node_path_1 = require("node:path");
|
||||||
function candidates(path) {
|
function candidates(path) {
|
||||||
return (0, node_path_1.extname)(path)
|
return (0, node_path_1.extname)(path) ? [path] : [path, `${path}.wrn`, `${path}.ts`, `${path}.d.ts`, (0, node_path_1.join)(path, "index.wrn"), (0, node_path_1.join)(path, "index.ts")];
|
||||||
? [path]
|
|
||||||
: [
|
|
||||||
path,
|
|
||||||
`${path}.wrn`,
|
|
||||||
`${path}.ts`,
|
|
||||||
`${path}.d.ts`,
|
|
||||||
(0, node_path_1.join)(path, "index.wrn"),
|
|
||||||
(0, node_path_1.join)(path, "index.ts"),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
function resolveWrnImport(declaration, importer, options) {
|
function resolveWrnImport(declaration, importer, options) {
|
||||||
const source = declaration.source;
|
const source = declaration.source;
|
||||||
if (!source.startsWith(".") && !source.startsWith("@/"))
|
if (!source.startsWith(".") && !source.startsWith("@/"))
|
||||||
return { declaration, resolved: source };
|
return { declaration, resolved: source };
|
||||||
const aliasRoot = options.aliases?.["@"] ?? "./app";
|
const aliasRoot = options.aliases?.["@"] ?? "./app";
|
||||||
const base = source.startsWith("@/")
|
const base = source.startsWith("@/") ? (0, node_path_1.resolve)(options.appRoot, aliasRoot, source.slice(2)) : (0, node_path_1.resolve)((0, node_path_1.dirname)(importer), source);
|
||||||
? (0, node_path_1.resolve)(options.appRoot, aliasRoot, source.slice(2))
|
|
||||||
: (0, node_path_1.resolve)((0, node_path_1.dirname)(importer), source);
|
|
||||||
const found = candidates(base).find(node_fs_1.existsSync);
|
const found = candidates(base).find(node_fs_1.existsSync);
|
||||||
if (found)
|
if (found)
|
||||||
return { declaration, resolved: (0, node_fs_1.realpathSync)(found) };
|
return { declaration, resolved: (0, node_fs_1.realpathSync)(found) };
|
||||||
const severity = (options.mode ?? "compatible") === "explicit" ? "error" : "warning";
|
const severity = (options.mode ?? "compatible") === "explicit" ? "error" : "warning";
|
||||||
return {
|
return { declaration, diagnostic: { code: "WRN-IMPORT-NOT-FOUND", message: `Cannot resolve import '${source}' from ${importer}`, severity } };
|
||||||
declaration,
|
|
||||||
diagnostic: {
|
|
||||||
code: "WRN-IMPORT-NOT-FOUND",
|
|
||||||
message: `Cannot resolve import '${source}' from ${importer}`,
|
|
||||||
severity,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
function resolveWrnImports(declarations, importer, options) {
|
function resolveWrnImports(declarations, importer, options) {
|
||||||
return declarations.map((declaration) => resolveWrnImport(declaration, importer, options));
|
return declarations.map((declaration) => resolveWrnImport(declaration, importer, options));
|
||||||
@@ -2585,12 +2505,7 @@ exports.createWrnSourceMap = createWrnSourceMap;
|
|||||||
function createWrnSourceMap(source, generated) {
|
function createWrnSourceMap(source, generated) {
|
||||||
const sourceLines = source.split(/\r?\n/).length;
|
const sourceLines = source.split(/\r?\n/).length;
|
||||||
const generatedLines = generated.split(/\r?\n/).length;
|
const generatedLines = generated.split(/\r?\n/).length;
|
||||||
const mappings = Array.from({ length: Math.min(sourceLines, generatedLines) }, (_, index) => ({
|
const mappings = Array.from({ length: Math.min(sourceLines, generatedLines) }, (_, index) => ({ generatedLine: index + 1, sourceLine: index + 1, sourceColumn: 1, kind: "line" }));
|
||||||
generatedLine: index + 1,
|
|
||||||
sourceLine: index + 1,
|
|
||||||
sourceColumn: 1,
|
|
||||||
kind: "line",
|
|
||||||
}));
|
|
||||||
return { version: 1, source, generated, mappings };
|
return { version: 1, source, generated, mappings };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2604,52 +2519,12 @@ const syntax_1 = require("@wrnexus/syntax");
|
|||||||
const type_codegen_ts_1 = require("./type-codegen.js");
|
const type_codegen_ts_1 = require("./type-codegen.js");
|
||||||
const server_codegen_ts_1 = require("./server-codegen.js");
|
const server_codegen_ts_1 = require("./server-codegen.js");
|
||||||
const RESERVED_BINDINGS = new Set([
|
const RESERVED_BINDINGS = new Set([
|
||||||
"await",
|
"await", "break", "case", "catch", "class", "const", "continue", "debugger",
|
||||||
"break",
|
"default", "delete", "do", "else", "enum", "export", "extends", "false",
|
||||||
"case",
|
"finally", "for", "function", "if", "implements", "import", "in",
|
||||||
"catch",
|
"instanceof", "interface", "let", "new", "null", "package", "private",
|
||||||
"class",
|
"protected", "public", "return", "static", "super", "switch", "this",
|
||||||
"const",
|
"throw", "true", "try", "typeof", "var", "void", "while", "with", "yield",
|
||||||
"continue",
|
|
||||||
"debugger",
|
|
||||||
"default",
|
|
||||||
"delete",
|
|
||||||
"do",
|
|
||||||
"else",
|
|
||||||
"enum",
|
|
||||||
"export",
|
|
||||||
"extends",
|
|
||||||
"false",
|
|
||||||
"finally",
|
|
||||||
"for",
|
|
||||||
"function",
|
|
||||||
"if",
|
|
||||||
"implements",
|
|
||||||
"import",
|
|
||||||
"in",
|
|
||||||
"instanceof",
|
|
||||||
"interface",
|
|
||||||
"let",
|
|
||||||
"new",
|
|
||||||
"null",
|
|
||||||
"package",
|
|
||||||
"private",
|
|
||||||
"protected",
|
|
||||||
"public",
|
|
||||||
"return",
|
|
||||||
"static",
|
|
||||||
"super",
|
|
||||||
"switch",
|
|
||||||
"this",
|
|
||||||
"throw",
|
|
||||||
"true",
|
|
||||||
"try",
|
|
||||||
"typeof",
|
|
||||||
"var",
|
|
||||||
"void",
|
|
||||||
"while",
|
|
||||||
"with",
|
|
||||||
"yield",
|
|
||||||
]);
|
]);
|
||||||
function safeBinding(name) {
|
function safeBinding(name) {
|
||||||
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) && !RESERVED_BINDINGS.has(name);
|
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) && !RESERVED_BINDINGS.has(name);
|
||||||
@@ -2722,8 +2597,7 @@ function generateStoreModule(ast) {
|
|||||||
const lifecycle = lifecycleSource(ast, stateNames, false);
|
const lifecycle = lifecycleSource(ast, stateNames, false);
|
||||||
const manifest = (0, server_codegen_ts_1.rpcManifest)(ast);
|
const manifest = (0, server_codegen_ts_1.rpcManifest)(ast);
|
||||||
const remoteFunctions = manifest.map((entry) => entry.function);
|
const remoteFunctions = manifest.map((entry) => entry.function);
|
||||||
const rpcWrappers = remoteFunctions
|
const rpcWrappers = remoteFunctions.map((name) => `${JSON.stringify(name)}: async (...received) => {
|
||||||
.map((name) => `${JSON.stringify(name)}: async (...received) => {
|
|
||||||
const rpcContext = received.pop();
|
const rpcContext = received.pop();
|
||||||
if (!rpcContext || !rpcContext.request) throw new Error("WRN-RPC-CONTEXT: request context is required");
|
if (!rpcContext || !rpcContext.request) throw new Error("WRN-RPC-CONTEXT: request context is required");
|
||||||
let container = __wrnexusRpcContainers.get(rpcContext.request);
|
let container = __wrnexusRpcContainers.get(rpcContext.request);
|
||||||
@@ -2736,8 +2610,7 @@ function generateStoreModule(ast) {
|
|||||||
const action = store.actions[${JSON.stringify(name)}];
|
const action = store.actions[${JSON.stringify(name)}];
|
||||||
if (typeof action !== "function") throw new Error(${JSON.stringify(`WRN-RPC-FUNCTION: store action '${name}' is unavailable on the server`)});
|
if (typeof action !== "function") throw new Error(${JSON.stringify(`WRN-RPC-FUNCTION: store action '${name}' is unavailable on the server`)});
|
||||||
return action(...received);
|
return action(...received);
|
||||||
}`)
|
}`).join(",\n");
|
||||||
.join(",\n");
|
|
||||||
return `${ast.imports.join("\n")}\nimport { defineStore } from "@wrnexus/store";\nimport { createRequestStoreContainer } from "@wrnexus/store/server";\n\n${ast.types.join("\n\n")}\n\nexport const ${ast.name} = defineStore({\n name: ${JSON.stringify(ast.name)},\n kind: ${JSON.stringify(ast.storeKind)},\n createSharedState: () => (${stateObject(ast, "shared")}),\n createClientState: () => (${stateObject(ast, "client")}),\n createServerState: () => (${stateObject(ast, "server")}),\n computed: { ${computed} },\n actions: { ${actions} },\n persist: ${persistence},\n lifecycle: { ${lifecycle} },\n});\n\nexport default ${ast.name};\n\nconst __wrnexusRpcContainers = new WeakMap();\nexport const __wrnexusServerFunctions = {\n${rpcWrappers}\n};\nexport const __wrnexusRpcManifest = ${JSON.stringify(manifest, null, 2)};\n\n${(0, type_codegen_ts_1.generateDeclarations)(ast)}\n`;
|
return `${ast.imports.join("\n")}\nimport { defineStore } from "@wrnexus/store";\nimport { createRequestStoreContainer } from "@wrnexus/store/server";\n\n${ast.types.join("\n\n")}\n\nexport const ${ast.name} = defineStore({\n name: ${JSON.stringify(ast.name)},\n kind: ${JSON.stringify(ast.storeKind)},\n createSharedState: () => (${stateObject(ast, "shared")}),\n createClientState: () => (${stateObject(ast, "client")}),\n createServerState: () => (${stateObject(ast, "server")}),\n computed: { ${computed} },\n actions: { ${actions} },\n persist: ${persistence},\n lifecycle: { ${lifecycle} },\n});\n\nexport default ${ast.name};\n\nconst __wrnexusRpcContainers = new WeakMap();\nexport const __wrnexusServerFunctions = {\n${rpcWrappers}\n};\nexport const __wrnexusRpcManifest = ${JSON.stringify(manifest, null, 2)};\n\n${(0, type_codegen_ts_1.generateDeclarations)(ast)}\n`;
|
||||||
}
|
}
|
||||||
/** Standalone browser artifact for an imported `.wrn` store. */
|
/** Standalone browser artifact for an imported `.wrn` store. */
|
||||||
@@ -2989,12 +2862,8 @@ const type_codegen_ts_1 = require("./type-codegen.js");
|
|||||||
const store_codegen_ts_1 = require("./store-codegen.js");
|
const store_codegen_ts_1 = require("./store-codegen.js");
|
||||||
function generateTargets(ast) {
|
function generateTargets(ast) {
|
||||||
return {
|
return {
|
||||||
server: ast.kind === "global-store" || ast.kind === "page-store"
|
server: ast.kind === "global-store" || ast.kind === "page-store" ? (0, store_codegen_ts_1.generateStoreModule)(ast) : (0, server_codegen_ts_1.generateServerFunctionsModule)(ast),
|
||||||
? (0, store_codegen_ts_1.generateStoreModule)(ast)
|
browser: ast.kind === "global-store" || ast.kind === "page-store" ? (0, store_codegen_ts_1.generateStoreBrowserModule)(ast) : (0, client_codegen_ts_1.generateBrowserModule)(ast),
|
||||||
: (0, server_codegen_ts_1.generateServerFunctionsModule)(ast),
|
|
||||||
browser: ast.kind === "global-store" || ast.kind === "page-store"
|
|
||||||
? (0, store_codegen_ts_1.generateStoreBrowserModule)(ast)
|
|
||||||
: (0, client_codegen_ts_1.generateBrowserModule)(ast),
|
|
||||||
declarations: (0, type_codegen_ts_1.generateDeclarations)(ast),
|
declarations: (0, type_codegen_ts_1.generateDeclarations)(ast),
|
||||||
contract: (0, component_contract_ts_1.createComponentContract)(ast),
|
contract: (0, component_contract_ts_1.createComponentContract)(ast),
|
||||||
rpc: (0, server_codegen_ts_1.rpcManifest)(ast),
|
rpc: (0, server_codegen_ts_1.rpcManifest)(ast),
|
||||||
@@ -3027,47 +2896,22 @@ __exportStar(require("@wrnexus/syntax/tokenizer"), exports);
|
|||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.generateDeclarations = generateDeclarations;
|
exports.generateDeclarations = generateDeclarations;
|
||||||
function member(name) {
|
function member(name) { return /^[A-Za-z_$][\w$]*$/.test(name) ? name : JSON.stringify(name); }
|
||||||
return /^[A-Za-z_$][\w$]*$/.test(name) ? name : JSON.stringify(name);
|
|
||||||
}
|
|
||||||
function params(astParams) {
|
function params(astParams) {
|
||||||
return astParams
|
return astParams.map((param) => `${member(param.name)}${param.optional ? "?" : ""}: ${param.valueType ?? "unknown"}`).join(", ");
|
||||||
.map((param) => `${member(param.name)}${param.optional ? "?" : ""}: ${param.valueType ?? "unknown"}`)
|
|
||||||
.join(", ");
|
|
||||||
}
|
}
|
||||||
function generateDeclarations(ast) {
|
function generateDeclarations(ast) {
|
||||||
const inline = ast.types
|
const inline = ast.types.map((body) => body.trim()).filter(Boolean).join("\n\n");
|
||||||
.map((body) => body.trim())
|
|
||||||
.filter(Boolean)
|
|
||||||
.join("\n\n");
|
|
||||||
if (ast.kind === "global-store" || ast.kind === "page-store") {
|
if (ast.kind === "global-store" || ast.kind === "page-store") {
|
||||||
const state = ast.states
|
const state = ast.states.filter((entry) => entry.runtime !== "server").map((entry) => ` readonly ${member(entry.name)}: ${entry.valueType ?? "unknown"};`).join("\n");
|
||||||
.filter((entry) => entry.runtime !== "server")
|
const computed = ast.computed.map((entry) => ` readonly ${member(entry.name)}: ${entry.valueType ?? "unknown"};`).join("\n");
|
||||||
.map((entry) => ` readonly ${member(entry.name)}: ${entry.valueType ?? "unknown"};`)
|
const actions = ast.runtimeFunctions.filter((fn) => fn.runtime !== "server").map((fn) => ` ${member(fn.name)}(${params(fn.parameters)}): ${fn.returnType ?? (fn.async ? "Promise<unknown>" : "unknown")};`).join("\n");
|
||||||
.join("\n");
|
|
||||||
const computed = ast.computed
|
|
||||||
.map((entry) => ` readonly ${member(entry.name)}: ${entry.valueType ?? "unknown"};`)
|
|
||||||
.join("\n");
|
|
||||||
const actions = ast.runtimeFunctions
|
|
||||||
.filter((fn) => fn.runtime !== "server")
|
|
||||||
.map((fn) => ` ${member(fn.name)}(${params(fn.parameters)}): ${fn.returnType ?? (fn.async ? "Promise<unknown>" : "unknown")};`)
|
|
||||||
.join("\n");
|
|
||||||
return `${inline ? `${inline}\n\n` : ""}export interface ${ast.name}State {\n${state}\n}\n\nexport interface ${ast.name}Computed {\n${computed}\n}\n\nexport interface ${ast.name}Actions {\n${actions}\n}\n\nexport interface ${ast.name}Instance extends ${ast.name}State, ${ast.name}Computed, ${ast.name}Actions {\n reset(): void;\n snapshot(): Readonly<${ast.name}State>;\n}\n\ndeclare const store: ${ast.name}Instance;\nexport default store;\n`;
|
return `${inline ? `${inline}\n\n` : ""}export interface ${ast.name}State {\n${state}\n}\n\nexport interface ${ast.name}Computed {\n${computed}\n}\n\nexport interface ${ast.name}Actions {\n${actions}\n}\n\nexport interface ${ast.name}Instance extends ${ast.name}State, ${ast.name}Computed, ${ast.name}Actions {\n reset(): void;\n snapshot(): Readonly<${ast.name}State>;\n}\n\ndeclare const store: ${ast.name}Instance;\nexport default store;\n`;
|
||||||
}
|
}
|
||||||
const props = ast.props
|
const props = ast.props.map((prop) => ` readonly ${member(prop.name)}${prop.required ? "" : "?"}: ${prop.valueType ?? "unknown"};`).join("\n");
|
||||||
.map((prop) => ` readonly ${member(prop.name)}${prop.required ? "" : "?"}: ${prop.valueType ?? "unknown"};`)
|
const outputs = ast.outputs.map((output) => ` ${member(output.name)}(${output.payload ? `${member(output.payload.name)}${output.payload.optional ? "?" : ""}: ${output.payload.valueType}` : ""}): void;`).join("\n");
|
||||||
.join("\n");
|
const clientFunctions = ast.runtimeFunctions.filter((fn) => fn.runtime === "client" || fn.runtime === "shared" || fn.runtime === "legacy").map((fn) => ` ${member(fn.name)}(${params(fn.parameters)}): ${fn.returnType ?? (fn.async ? "Promise<unknown>" : "unknown")};`).join("\n");
|
||||||
const outputs = ast.outputs
|
const serverFunctions = ast.runtimeFunctions.filter((fn) => fn.runtime === "server").map((fn) => ` ${member(fn.name)}(${params(fn.parameters)}): Promise<Awaited<${fn.returnType ?? "unknown"}>>;`).join("\n");
|
||||||
.map((output) => ` ${member(output.name)}(${output.payload ? `${member(output.payload.name)}${output.payload.optional ? "?" : ""}: ${output.payload.valueType}` : ""}): void;`)
|
|
||||||
.join("\n");
|
|
||||||
const clientFunctions = ast.runtimeFunctions
|
|
||||||
.filter((fn) => fn.runtime === "client" || fn.runtime === "shared" || fn.runtime === "legacy")
|
|
||||||
.map((fn) => ` ${member(fn.name)}(${params(fn.parameters)}): ${fn.returnType ?? (fn.async ? "Promise<unknown>" : "unknown")};`)
|
|
||||||
.join("\n");
|
|
||||||
const serverFunctions = ast.runtimeFunctions
|
|
||||||
.filter((fn) => fn.runtime === "server")
|
|
||||||
.map((fn) => ` ${member(fn.name)}(${params(fn.parameters)}): Promise<Awaited<${fn.returnType ?? "unknown"}>>;`)
|
|
||||||
.join("\n");
|
|
||||||
return `${inline ? `${inline}\n\n` : ""}export interface ${ast.name}Props {\n${props}\n}\n\nexport interface ${ast.name}Outputs {\n${outputs}\n}\n\nexport interface ${ast.name}ClientFunctions {\n${clientFunctions}\n}\n\nexport interface ${ast.name}ServerCalls {\n${serverFunctions}\n}\n`;
|
return `${inline ? `${inline}\n\n` : ""}export interface ${ast.name}Props {\n${props}\n}\n\nexport interface ${ast.name}Outputs {\n${outputs}\n}\n\nexport interface ${ast.name}ClientFunctions {\n${clientFunctions}\n}\n\nexport interface ${ast.name}ServerCalls {\n${serverFunctions}\n}\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3315,88 +3159,38 @@ function astDiagnostics(ast, options) {
|
|||||||
for (const call of fn.body.matchAll(/\boutput\.([A-Za-z_$][\w$]*)\s*\(/g)) {
|
for (const call of fn.body.matchAll(/\boutput\.([A-Za-z_$][\w$]*)\s*\(/g)) {
|
||||||
const outputName = call[1];
|
const outputName = call[1];
|
||||||
if (fn.runtime === "server") {
|
if (fn.runtime === "server") {
|
||||||
diagnostics.push({
|
diagnostics.push({ code: "WRN-OUTPUT-SERVER-CALL", severity: "error", message: `Server function '${fn.name}' cannot call output.${outputName}().`, hint: "Return a typed value to the browser and call the output from a client function.", file: options.file });
|
||||||
code: "WRN-OUTPUT-SERVER-CALL",
|
|
||||||
severity: "error",
|
|
||||||
message: `Server function '${fn.name}' cannot call output.${outputName}().`,
|
|
||||||
hint: "Return a typed value to the browser and call the output from a client function.",
|
|
||||||
file: options.file,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
else if (!outputs.has(outputName)) {
|
else if (!outputs.has(outputName)) {
|
||||||
diagnostics.push({
|
diagnostics.push({ code: "WRN-OUTPUT-UNKNOWN", severity: "error", message: `Unknown output '${outputName}' called from '${fn.name}'.`, hint: `Declare ${outputName}(payload) inside outputs { ... }.`, file: options.file });
|
||||||
code: "WRN-OUTPUT-UNKNOWN",
|
|
||||||
severity: "error",
|
|
||||||
message: `Unknown output '${outputName}' called from '${fn.name}'.`,
|
|
||||||
hint: `Declare ${outputName}(payload) inside outputs { ... }.`,
|
|
||||||
file: options.file,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fn.runtime === "client" && /\b(?:process|Bun|Deno|__dirname|require)\b/.test(fn.body)) {
|
if (fn.runtime === "client" && /\b(?:process|Bun|Deno|__dirname|require)\b/.test(fn.body)) {
|
||||||
diagnostics.push({
|
diagnostics.push({ code: "WRN-CLIENT-SERVER-API", severity: "error", message: `Client function '${fn.name}' references a server-only API.`, hint: "Move that operation into a server function and call it through server.name(...).", file: options.file });
|
||||||
code: "WRN-CLIENT-SERVER-API",
|
|
||||||
severity: "error",
|
|
||||||
message: `Client function '${fn.name}' references a server-only API.`,
|
|
||||||
hint: "Move that operation into a server function and call it through server.name(...).",
|
|
||||||
file: options.file,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
if (fn.runtime === "server" &&
|
if (fn.runtime === "server" && /\b(?:window|document|localStorage|sessionStorage|navigator)\b/.test(fn.body)) {
|
||||||
/\b(?:window|document|localStorage|sessionStorage|navigator)\b/.test(fn.body)) {
|
diagnostics.push({ code: "WRN-SERVER-BROWSER-API", severity: "error", message: `Server function '${fn.name}' references a browser-only API.`, hint: "Move that code into a client function.", file: options.file });
|
||||||
diagnostics.push({
|
|
||||||
code: "WRN-SERVER-BROWSER-API",
|
|
||||||
severity: "error",
|
|
||||||
message: `Server function '${fn.name}' references a browser-only API.`,
|
|
||||||
hint: "Move that code into a client function.",
|
|
||||||
file: options.file,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
const parameterNames = new Set(fn.parameters.map((parameter) => parameter.name));
|
const parameterNames = new Set(fn.parameters.map((parameter) => parameter.name));
|
||||||
for (const prop of ast.props) {
|
for (const prop of ast.props) {
|
||||||
if (containsReadonlyPropMutation(fn.body, prop.name, parameterNames)) {
|
if (containsReadonlyPropMutation(fn.body, prop.name, parameterNames)) {
|
||||||
diagnostics.push({
|
diagnostics.push({ code: "WRN-PROP-READONLY", severity: "error", message: `Function '${fn.name}' attempts to mutate readonly prop '${prop.name}'.`, hint: "Copy the prop into state before mutating it.", file: options.file });
|
||||||
code: "WRN-PROP-READONLY",
|
|
||||||
severity: "error",
|
|
||||||
message: `Function '${fn.name}' attempts to mutate readonly prop '${prop.name}'.`,
|
|
||||||
hint: "Copy the prop into state before mutating it.",
|
|
||||||
file: options.file,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const state of ast.states) {
|
for (const state of ast.states) {
|
||||||
if (state.runtime === "shared" &&
|
if (state.runtime === "shared" && /^(?:new\s+(?:Map|Set|WeakMap|WeakSet)|(?:async\s+)?function\b|.*=>)/.test(state.expr.trim())) {
|
||||||
/^(?:new\s+(?:Map|Set|WeakMap|WeakSet)|(?:async\s+)?function\b|.*=>)/.test(state.expr.trim())) {
|
diagnostics.push({ code: "WRN-STATE-NON-SERIALIZABLE", severity: "error", message: `Shared state '${state.name}' is not safely serializable.`, hint: "Use JSON-compatible data or move the value into client/server state.", file: options.file });
|
||||||
diagnostics.push({
|
|
||||||
code: "WRN-STATE-NON-SERIALIZABLE",
|
|
||||||
severity: "error",
|
|
||||||
message: `Shared state '${state.name}' is not safely serializable.`,
|
|
||||||
hint: "Use JSON-compatible data or move the value into client/server state.",
|
|
||||||
file: options.file,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ast.persist) {
|
if (ast.persist) {
|
||||||
const stateNames = new Set(ast.states.filter((state) => state.runtime !== "server").map((state) => state.name));
|
const stateNames = new Set(ast.states.filter((state) => state.runtime !== "server").map((state) => state.name));
|
||||||
for (const name of ast.persist.include)
|
for (const name of ast.persist.include)
|
||||||
if (!stateNames.has(name))
|
if (!stateNames.has(name))
|
||||||
diagnostics.push({
|
diagnostics.push({ code: "WRN-PERSIST-UNKNOWN-FIELD", severity: "error", message: `Persist include references unknown or server-only state '${name}'.`, hint: "Persist only declared shared/client state fields.", file: options.file });
|
||||||
code: "WRN-PERSIST-UNKNOWN-FIELD",
|
|
||||||
severity: "error",
|
|
||||||
message: `Persist include references unknown or server-only state '${name}'.`,
|
|
||||||
hint: "Persist only declared shared/client state fields.",
|
|
||||||
file: options.file,
|
|
||||||
});
|
|
||||||
for (const name of ast.persist.include)
|
for (const name of ast.persist.include)
|
||||||
if (/token|password|secret|otp|api.?key/i.test(name))
|
if (/token|password|secret|otp|api.?key/i.test(name))
|
||||||
diagnostics.push({
|
diagnostics.push({ code: "WRN-PERSIST-SENSITIVE", severity: "error", message: `Sensitive field '${name}' cannot be persisted.`, hint: "Remove secrets, tokens, passwords, OTPs, and API keys from persistence.", file: options.file });
|
||||||
code: "WRN-PERSIST-SENSITIVE",
|
|
||||||
severity: "error",
|
|
||||||
message: `Sensitive field '${name}' cannot be persisted.`,
|
|
||||||
hint: "Remove secrets, tokens, passwords, OTPs, and API keys from persistence.",
|
|
||||||
file: options.file,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return diagnostics;
|
return diagnostics;
|
||||||
}
|
}
|
||||||
@@ -3623,8 +3417,7 @@ function parse(source) {
|
|||||||
try {
|
try {
|
||||||
// A file may contain a page, component, layout, global store, or page store.
|
// A file may contain a page, component, layout, global store, or page store.
|
||||||
const opener = lx.next();
|
const opener = lx.next();
|
||||||
if (opener.type !== "ident" ||
|
if (opener.type !== "ident" || !["page", "component", "layout", "global"].includes(opener.value)) {
|
||||||
!["page", "component", "layout", "global"].includes(opener.value)) {
|
|
||||||
throw new ParseError(`Expected 'page', 'component', 'layout', 'global store', or 'page store' but got '${opener.value || opener.type}' at offset ${opener.pos}`);
|
throw new ParseError(`Expected 'page', 'component', 'layout', 'global store', or 'page store' but got '${opener.value || opener.type}' at offset ${opener.pos}`);
|
||||||
}
|
}
|
||||||
let kind;
|
let kind;
|
||||||
@@ -3636,9 +3429,7 @@ function parse(source) {
|
|||||||
storeKind = "global";
|
storeKind = "global";
|
||||||
name = expect("ident").value;
|
name = expect("ident").value;
|
||||||
}
|
}
|
||||||
else if (opener.value === "page" &&
|
else if (opener.value === "page" && lx.peek().type === "ident" && lx.peek().value === "store") {
|
||||||
lx.peek().type === "ident" &&
|
|
||||||
lx.peek().value === "store") {
|
|
||||||
lx.next();
|
lx.next();
|
||||||
kind = "page-store";
|
kind = "page-store";
|
||||||
storeKind = "page";
|
storeKind = "page";
|
||||||
@@ -3753,12 +3544,7 @@ function parse(source) {
|
|||||||
hasDefault = true;
|
hasDefault = true;
|
||||||
}
|
}
|
||||||
const defaultValue = hasDefault ? lx.readPropInitializer() : "undefined";
|
const defaultValue = hasDefault ? lx.readPropInitializer() : "undefined";
|
||||||
props.push({
|
props.push({ name: pName, valueType, required: !hasDefault && !optional, default: defaultValue });
|
||||||
name: pName,
|
|
||||||
valueType,
|
|
||||||
required: !hasDefault && !optional,
|
|
||||||
default: defaultValue,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
expect("rbrace");
|
expect("rbrace");
|
||||||
break;
|
break;
|
||||||
@@ -3782,12 +3568,7 @@ function parse(source) {
|
|||||||
else {
|
else {
|
||||||
expect("eq");
|
expect("eq");
|
||||||
}
|
}
|
||||||
states.push({
|
states.push({ name: sName, valueType, expr: lx.readPropInitializer(), runtime: "shared" });
|
||||||
name: sName,
|
|
||||||
valueType,
|
|
||||||
expr: lx.readPropInitializer(),
|
|
||||||
runtime: "shared",
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "computed": {
|
case "computed": {
|
||||||
@@ -3892,9 +3673,7 @@ function parse(source) {
|
|||||||
const rawMode = kw.value;
|
const rawMode = kw.value;
|
||||||
const mode = rawMode === "client" ? "client" : "ssr";
|
const mode = rawMode === "client" ? "client" : "ssr";
|
||||||
lx.next();
|
lx.next();
|
||||||
if ((rawMode === "client" || rawMode === "server") &&
|
if ((rawMode === "client" || rawMode === "server") && lx.peek().type === "ident" && lx.peek().value === "state") {
|
||||||
lx.peek().type === "ident" &&
|
|
||||||
lx.peek().value === "state") {
|
|
||||||
lx.next();
|
lx.next();
|
||||||
if (lx.peek().type !== "lbrace")
|
if (lx.peek().type !== "lbrace")
|
||||||
throw new ParseError(`Expected a grouped ${rawMode} state block`);
|
throw new ParseError(`Expected a grouped ${rawMode} state block`);
|
||||||
@@ -4440,13 +4219,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||||||
exports.WRN_DIAGNOSTIC_CODES = exports.WRN_RUNTIME_TARGETS = exports.WRN_HYDRATION_STRATEGIES = exports.WRN_ROOT_MEMBERS = exports.WRN_ROOT_KINDS = exports.WRN_LANGUAGE_VERSION = void 0;
|
exports.WRN_DIAGNOSTIC_CODES = exports.WRN_RUNTIME_TARGETS = exports.WRN_HYDRATION_STRATEGIES = exports.WRN_ROOT_MEMBERS = exports.WRN_ROOT_KINDS = exports.WRN_LANGUAGE_VERSION = void 0;
|
||||||
/** Canonical, machine-readable WRN language capabilities. */
|
/** Canonical, machine-readable WRN language capabilities. */
|
||||||
exports.WRN_LANGUAGE_VERSION = "0.6";
|
exports.WRN_LANGUAGE_VERSION = "0.6";
|
||||||
exports.WRN_ROOT_KINDS = [
|
exports.WRN_ROOT_KINDS = ["page", "component", "layout", "global-store", "page-store"];
|
||||||
"page",
|
|
||||||
"component",
|
|
||||||
"layout",
|
|
||||||
"global-store",
|
|
||||||
"page-store",
|
|
||||||
];
|
|
||||||
exports.WRN_ROOT_MEMBERS = [
|
exports.WRN_ROOT_MEMBERS = [
|
||||||
"layout",
|
"layout",
|
||||||
"runtime",
|
"runtime",
|
||||||
@@ -5009,9 +4782,7 @@ function findTopLevelChar(input, wanted) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
function parseParameters(source) {
|
function parseParameters(source) {
|
||||||
return splitTopLevel(source)
|
return splitTopLevel(source).filter(Boolean).map((entry) => {
|
||||||
.filter(Boolean)
|
|
||||||
.map((entry) => {
|
|
||||||
const eq = findTopLevelChar(entry, "=");
|
const eq = findTopLevelChar(entry, "=");
|
||||||
const declaration = (eq >= 0 ? entry.slice(0, eq) : entry).trim();
|
const declaration = (eq >= 0 ? entry.slice(0, eq) : entry).trim();
|
||||||
const defaultValue = eq >= 0 ? entry.slice(eq + 1).trim() : undefined;
|
const defaultValue = eq >= 0 ? entry.slice(eq + 1).trim() : undefined;
|
||||||
@@ -5020,12 +4791,7 @@ function parseParameters(source) {
|
|||||||
const optional = rawName.endsWith("?");
|
const optional = rawName.endsWith("?");
|
||||||
const name = optional ? rawName.slice(0, -1).trim() : rawName;
|
const name = optional ? rawName.slice(0, -1).trim() : rawName;
|
||||||
const valueType = colon >= 0 ? declaration.slice(colon + 1).trim() : undefined;
|
const valueType = colon >= 0 ? declaration.slice(colon + 1).trim() : undefined;
|
||||||
return {
|
return { name, optional, ...(valueType ? { valueType } : {}), ...(defaultValue ? { default: defaultValue } : {}) };
|
||||||
name,
|
|
||||||
optional,
|
|
||||||
...(valueType ? { valueType } : {}),
|
|
||||||
...(defaultValue ? { default: defaultValue } : {}),
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function skipTrivia(source, start) {
|
function skipTrivia(source, start) {
|
||||||
@@ -5203,15 +4969,7 @@ function parseOutputs(source) {
|
|||||||
throw new Error(`Output '${nameToken.word}' payload requires a type`);
|
throw new Error(`Output '${nameToken.word}' payload requires a type`);
|
||||||
out.push({
|
out.push({
|
||||||
name: nameToken.word,
|
name: nameToken.word,
|
||||||
...(payload
|
...(payload ? { payload: { name: payload.name, valueType: payload.valueType, optional: payload.optional } } : {}),
|
||||||
? {
|
|
||||||
payload: {
|
|
||||||
name: payload.name,
|
|
||||||
valueType: payload.valueType,
|
|
||||||
optional: payload.optional,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
: {}),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
@@ -5244,11 +5002,7 @@ function parseStructuredImports(imports) {
|
|||||||
const localTypeOnly = /^type\s+/.test(item);
|
const localTypeOnly = /^type\s+/.test(item);
|
||||||
const cleaned = item.replace(/^type\s+/, "").trim();
|
const cleaned = item.replace(/^type\s+/, "").trim();
|
||||||
const [imported, local] = cleaned.split(/\s+as\s+/);
|
const [imported, local] = cleaned.split(/\s+as\s+/);
|
||||||
return {
|
return { imported: imported.trim(), local: (local ?? imported).trim(), typeOnly: typeOnly || localTypeOnly };
|
||||||
imported: imported.trim(),
|
|
||||||
local: (local ?? imported).trim(),
|
|
||||||
typeOnly: typeOnly || localTypeOnly,
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return declaration;
|
return declaration;
|
||||||
@@ -5274,12 +5028,7 @@ function parseStateDeclarations(source, runtime) {
|
|||||||
if (eq.type !== "eq")
|
if (eq.type !== "eq")
|
||||||
throw new tokenizer_ts_1.LexError(`Expected '=' after state '${nameToken.value}' at offset ${eq.pos}`);
|
throw new tokenizer_ts_1.LexError(`Expected '=' after state '${nameToken.value}' at offset ${eq.pos}`);
|
||||||
}
|
}
|
||||||
out.push({
|
out.push({ name: nameToken.value, ...(valueType ? { valueType } : {}), expr: lx.readPropInitializer(), runtime });
|
||||||
name: nameToken.value,
|
|
||||||
...(valueType ? { valueType } : {}),
|
|
||||||
expr: lx.readPropInitializer(),
|
|
||||||
runtime,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -5303,11 +5052,7 @@ function parseComputedDeclarations(source) {
|
|||||||
if (eq.type !== "eq")
|
if (eq.type !== "eq")
|
||||||
throw new tokenizer_ts_1.LexError(`Expected '=' after computed '${nameToken.value}' at offset ${eq.pos}`);
|
throw new tokenizer_ts_1.LexError(`Expected '=' after computed '${nameToken.value}' at offset ${eq.pos}`);
|
||||||
}
|
}
|
||||||
out.push({
|
out.push({ name: nameToken.value, ...(valueType ? { valueType } : {}), expr: lx.readPropInitializer() });
|
||||||
name: nameToken.value,
|
|
||||||
...(valueType ? { valueType } : {}),
|
|
||||||
expr: lx.readPropInitializer(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,14 +134,6 @@ export interface Routes {
|
|||||||
"/tables": Record<string, never>;
|
"/tables": Record<string, never>;
|
||||||
"/templates": Record<string, never>;
|
"/templates": Record<string, never>;
|
||||||
"/themes": Record<string, never>;
|
"/themes": Record<string, never>;
|
||||||
"/v06-functions": Record<string, never>;
|
|
||||||
"/v06-imports": Record<string, never>;
|
|
||||||
"/v06-migration": Record<string, never>;
|
|
||||||
"/v06-outputs": Record<string, never>;
|
|
||||||
"/v06-runtime": Record<string, never>;
|
|
||||||
"/v06-state": Record<string, never>;
|
|
||||||
"/v06-stores": Record<string, never>;
|
|
||||||
"/v06-types": Record<string, never>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RoutePath = keyof Routes;
|
export type RoutePath = keyof Routes;
|
||||||
|
|||||||
@@ -81,6 +81,11 @@
|
|||||||
"category": "base",
|
"category": "base",
|
||||||
"purpose": "Theme-aware, responsive button group component."
|
"purpose": "Theme-aware, responsive button group component."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "CTASection",
|
||||||
|
"category": "marketing",
|
||||||
|
"purpose": "Close a page or major section with conversion-focused copy, actions, and optional supporting visual content."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Card",
|
"name": "Card",
|
||||||
"category": "base",
|
"category": "base",
|
||||||
@@ -151,11 +156,6 @@
|
|||||||
"category": "advanced-forms",
|
"category": "advanced-forms",
|
||||||
"purpose": "Theme-aware, responsive copy markup component."
|
"purpose": "Theme-aware, responsive copy markup component."
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "CTASection",
|
|
||||||
"category": "marketing",
|
|
||||||
"purpose": "Close a page or major section with conversion-focused copy, actions, and optional supporting visual content."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "CustomScrollbar",
|
"name": "CustomScrollbar",
|
||||||
"category": "layout",
|
"category": "layout",
|
||||||
@@ -481,26 +481,26 @@
|
|||||||
"category": "navigation",
|
"category": "navigation",
|
||||||
"purpose": "Switch between related responsive content panels with horizontal or vertical orientation and selection events."
|
"purpose": "Switch between related responsive content panels with horizontal or vertical orientation and selection events."
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Textarea",
|
|
||||||
"category": "forms",
|
|
||||||
"purpose": "Theme-aware, responsive textarea component."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "TextLink",
|
"name": "TextLink",
|
||||||
"category": "marketing",
|
"category": "marketing",
|
||||||
"purpose": "Render an accessible text action with optional icon, arrow, underline, external state, and semantic styling."
|
"purpose": "Render an accessible text action with optional icon, arrow, underline, external state, and semantic styling."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Timeline",
|
"name": "Textarea",
|
||||||
"category": "base",
|
"category": "forms",
|
||||||
"purpose": "Present responsive chronological activity, milestones, or workflow status with rich item metadata."
|
"purpose": "Theme-aware, responsive textarea component."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "TimePicker",
|
"name": "TimePicker",
|
||||||
"category": "forms",
|
"category": "forms",
|
||||||
"purpose": "Theme-aware, responsive time picker component."
|
"purpose": "Theme-aware, responsive time picker component."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Timeline",
|
||||||
|
"category": "base",
|
||||||
|
"purpose": "Present responsive chronological activity, milestones, or workflow status with rich item metadata."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Toast",
|
"name": "Toast",
|
||||||
"category": "base",
|
"category": "base",
|
||||||
|
|||||||
@@ -2278,6 +2278,193 @@
|
|||||||
"events": ["click", "select", "change"],
|
"events": ["click", "select", "change"],
|
||||||
"source": "components/ButtonGroup.wrn"
|
"source": "components/ButtonGroup.wrn"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "CTASection",
|
||||||
|
"mount": "CTASection",
|
||||||
|
"category": "marketing",
|
||||||
|
"purpose": "Close a page or major section with conversion-focused copy, actions, and optional supporting visual content.",
|
||||||
|
"props": [
|
||||||
|
{
|
||||||
|
"name": "eyebrow",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "title",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"Ready to get started?\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "description",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "icon",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "align",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"center\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "size",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "color",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"primary\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "variant",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"solid\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "primaryLabel",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"Get started\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "primaryHref",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"#\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "primaryIcon",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "secondaryLabel",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "secondaryHref",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "secondaryIcon",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "backgroundImage",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "visualImage",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "visualAlt",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "visualIcon",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "visualTitle",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "visualDescription",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "visualItems",
|
||||||
|
"type": "unknown[]",
|
||||||
|
"required": false,
|
||||||
|
"default": "[]",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "visualPosition",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"right\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "maxWidth",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"xl\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fullBleed",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "class",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"slots": ["default", "actions", "visual", "footer"],
|
||||||
|
"outputs": [],
|
||||||
|
"events": [],
|
||||||
|
"source": "components/CTASection.wrn"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Card",
|
"name": "Card",
|
||||||
"mount": "Card",
|
"mount": "Card",
|
||||||
@@ -4250,193 +4437,6 @@
|
|||||||
"events": ["copy", "success", "error"],
|
"events": ["copy", "success", "error"],
|
||||||
"source": "components/CopyMarkup.wrn"
|
"source": "components/CopyMarkup.wrn"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "CTASection",
|
|
||||||
"mount": "CTASection",
|
|
||||||
"category": "marketing",
|
|
||||||
"purpose": "Close a page or major section with conversion-focused copy, actions, and optional supporting visual content.",
|
|
||||||
"props": [
|
|
||||||
{
|
|
||||||
"name": "eyebrow",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "title",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"Ready to get started?\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "description",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "icon",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "align",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"center\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "size",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"default\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "color",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"primary\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "variant",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"solid\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "primaryLabel",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"Get started\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "primaryHref",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"#\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "primaryIcon",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "secondaryLabel",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "secondaryHref",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "secondaryIcon",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "backgroundImage",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "visualImage",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "visualAlt",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "visualIcon",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "visualTitle",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "visualDescription",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "visualItems",
|
|
||||||
"type": "unknown[]",
|
|
||||||
"required": false,
|
|
||||||
"default": "[]",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "visualPosition",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"right\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "maxWidth",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"xl\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "fullBleed",
|
|
||||||
"type": "boolean",
|
|
||||||
"required": false,
|
|
||||||
"default": "false",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "class",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"slots": ["default", "actions", "visual", "footer"],
|
|
||||||
"outputs": [],
|
|
||||||
"events": [],
|
|
||||||
"source": "components/CTASection.wrn"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "CustomScrollbar",
|
"name": "CustomScrollbar",
|
||||||
"mount": "CustomScrollbar",
|
"mount": "CustomScrollbar",
|
||||||
@@ -12144,6 +12144,129 @@
|
|||||||
"events": [],
|
"events": [],
|
||||||
"source": "components/Tabs.wrn"
|
"source": "components/Tabs.wrn"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "TextLink",
|
||||||
|
"mount": "TextLink",
|
||||||
|
"category": "marketing",
|
||||||
|
"purpose": "Render an accessible text action with optional icon, arrow, underline, external state, and semantic styling.",
|
||||||
|
"props": [
|
||||||
|
{
|
||||||
|
"name": "label",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"Learn more\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "href",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"#\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "target",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "rel",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "external",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "icon",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "iconPosition",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"start\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "showArrow",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "true",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "underline",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "size",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "color",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"primary\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "variant",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "disabled",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "class",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"slots": [],
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "click",
|
||||||
|
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "focus",
|
||||||
|
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "blur",
|
||||||
|
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"events": ["click", "focus", "blur"],
|
||||||
|
"source": "components/TextLink.wrn"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Textarea",
|
"name": "Textarea",
|
||||||
"mount": "Textarea",
|
"mount": "Textarea",
|
||||||
@@ -12338,190 +12461,6 @@
|
|||||||
"events": ["input", "change", "focus", "blur", "invalid"],
|
"events": ["input", "change", "focus", "blur", "invalid"],
|
||||||
"source": "components/Textarea.wrn"
|
"source": "components/Textarea.wrn"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "TextLink",
|
|
||||||
"mount": "TextLink",
|
|
||||||
"category": "marketing",
|
|
||||||
"purpose": "Render an accessible text action with optional icon, arrow, underline, external state, and semantic styling.",
|
|
||||||
"props": [
|
|
||||||
{
|
|
||||||
"name": "label",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"Learn more\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "href",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"#\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "target",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "rel",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "external",
|
|
||||||
"type": "boolean",
|
|
||||||
"required": false,
|
|
||||||
"default": "false",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "icon",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "iconPosition",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"start\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "showArrow",
|
|
||||||
"type": "boolean",
|
|
||||||
"required": false,
|
|
||||||
"default": "true",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "underline",
|
|
||||||
"type": "boolean",
|
|
||||||
"required": false,
|
|
||||||
"default": "false",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "size",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"default\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "color",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"primary\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "variant",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"default\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "disabled",
|
|
||||||
"type": "boolean",
|
|
||||||
"required": false,
|
|
||||||
"default": "false",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "class",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"slots": [],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "click",
|
|
||||||
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "focus",
|
|
||||||
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "blur",
|
|
||||||
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"events": ["click", "focus", "blur"],
|
|
||||||
"source": "components/TextLink.wrn"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Timeline",
|
|
||||||
"mount": "Timeline",
|
|
||||||
"category": "base",
|
|
||||||
"purpose": "Present responsive chronological activity, milestones, or workflow status with rich item metadata.",
|
|
||||||
"props": [
|
|
||||||
{
|
|
||||||
"name": "size",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"default\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "color",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"primary\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "title",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"Timeline\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "description",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "items",
|
|
||||||
"type": "unknown[]",
|
|
||||||
"required": false,
|
|
||||||
"default": "[]",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "variant",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"default\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "class",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"\"",
|
|
||||||
"options": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"slots": ["default"],
|
|
||||||
"outputs": [],
|
|
||||||
"events": [],
|
|
||||||
"source": "components/Timeline.wrn"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "TimePicker",
|
"name": "TimePicker",
|
||||||
"mount": "TimePicker",
|
"mount": "TimePicker",
|
||||||
@@ -12745,6 +12684,67 @@
|
|||||||
"events": ["input", "change", "focus", "blur", "open", "close", "invalid"],
|
"events": ["input", "change", "focus", "blur", "open", "close", "invalid"],
|
||||||
"source": "components/TimePicker.wrn"
|
"source": "components/TimePicker.wrn"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Timeline",
|
||||||
|
"mount": "Timeline",
|
||||||
|
"category": "base",
|
||||||
|
"purpose": "Present responsive chronological activity, milestones, or workflow status with rich item metadata.",
|
||||||
|
"props": [
|
||||||
|
{
|
||||||
|
"name": "size",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "color",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"primary\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "title",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"Timeline\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "description",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "items",
|
||||||
|
"type": "unknown[]",
|
||||||
|
"required": false,
|
||||||
|
"default": "[]",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "variant",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "class",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"slots": ["default"],
|
||||||
|
"outputs": [],
|
||||||
|
"events": [],
|
||||||
|
"source": "components/Timeline.wrn"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Toast",
|
"name": "Toast",
|
||||||
"mount": "Toast",
|
"mount": "Toast",
|
||||||
|
|||||||
@@ -95,6 +95,10 @@ function words(name) {
|
|||||||
return name.replace(/([a-z0-9])([A-Z])/g, "$1 $2").toLowerCase();
|
return name.replace(/([a-z0-9])([A-Z])/g, "$1 $2").toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function compareText(left, right) {
|
||||||
|
return left < right ? -1 : left > right ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
const sourceEntries = readdirSync(componentsDir)
|
const sourceEntries = readdirSync(componentsDir)
|
||||||
.filter((file) => file.endsWith(".wrn"))
|
.filter((file) => file.endsWith(".wrn"))
|
||||||
.map((file) => {
|
.map((file) => {
|
||||||
@@ -150,7 +154,7 @@ const components = [...sourceByName.values()]
|
|||||||
source: `components/${file}`,
|
source: `components/${file}`,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.sort((left, right) => left.name.localeCompare(right.name));
|
.sort((left, right) => compareText(left.name, right.name));
|
||||||
|
|
||||||
const catalogComponents = components.map((component) => ({
|
const catalogComponents = components.map((component) => ({
|
||||||
name: component.name,
|
name: component.name,
|
||||||
@@ -180,7 +184,9 @@ const lines = [
|
|||||||
`This reference is generated from the ${components.length} packaged \`.wrn\` component sources. Props marked required have no default; all others show their runtime default.`,
|
`This reference is generated from the ${components.length} packaged \`.wrn\` component sources. Props marked required have no default; all others show their runtime default.`,
|
||||||
"",
|
"",
|
||||||
];
|
];
|
||||||
for (const category of [...new Set(components.map((component) => component.category))].sort()) {
|
for (const category of [...new Set(components.map((component) => component.category))].sort(
|
||||||
|
compareText,
|
||||||
|
)) {
|
||||||
lines.push(`## ${category[0].toUpperCase()}${category.slice(1)}`, "");
|
lines.push(`## ${category[0].toUpperCase()}${category.slice(1)}`, "");
|
||||||
for (const component of components.filter((item) => item.category === category)) {
|
for (const component of components.filter((item) => item.category === category)) {
|
||||||
const props = component.props.length
|
const props = component.props.length
|
||||||
|
|||||||
+19
-5
@@ -208,7 +208,11 @@ function prepare(all: PackageInfo[], version: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function verifyUiComponentReference(): void {
|
function verifyUiComponentReference(): void {
|
||||||
const generatedFiles = ["packages/ui/component-reference.json", "packages/ui/COMPONENTS.md"];
|
const generatedFiles = [
|
||||||
|
"packages/ui/component-catalog.json",
|
||||||
|
"packages/ui/component-reference.json",
|
||||||
|
"packages/ui/COMPONENTS.md",
|
||||||
|
];
|
||||||
|
|
||||||
const result = run(
|
const result = run(
|
||||||
process.execPath,
|
process.execPath,
|
||||||
@@ -226,22 +230,32 @@ function verifyUiComponentReference(): void {
|
|||||||
throw new Error(`Failed to generate the UI component reference.${detail ? `\n${detail}` : ""}`);
|
throw new Error(`Failed to generate the UI component reference.${detail ? `\n${detail}` : ""}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const changed = output("git", ["status", "--short", "--", ...generatedFiles], root).trim();
|
// Do not use `git status --short` here. On Windows, the generator writes LF
|
||||||
|
// while an autocrlf checkout may contain CRLF. `git status` can report those
|
||||||
|
// files as modified even when their canonical Git content is identical.
|
||||||
|
// `git diff --quiet` applies Git's normal text conversion and only fails for
|
||||||
|
// a real generated-content difference.
|
||||||
|
const changedStatus = run("git", ["diff", "--quiet", "--", ...generatedFiles], root, {
|
||||||
|
capture: true,
|
||||||
|
allowFailure: true,
|
||||||
|
}).status;
|
||||||
|
|
||||||
if (!changed) {
|
if (changedStatus === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const changed = output("git", ["diff", "--name-status", "--", ...generatedFiles], root);
|
||||||
|
|
||||||
throw new Error(
|
throw new Error(
|
||||||
[
|
[
|
||||||
"UI component reference is stale.",
|
"UI component reference is stale.",
|
||||||
"",
|
"",
|
||||||
changed,
|
changed || generatedFiles.join("\n"),
|
||||||
"",
|
"",
|
||||||
"Run:",
|
"Run:",
|
||||||
" bun run scripts/generate-ui-component-reference.mjs",
|
" bun run scripts/generate-ui-component-reference.mjs",
|
||||||
" bun run format",
|
" bun run format",
|
||||||
" git add packages/ui/component-reference.json packages/ui/COMPONENTS.md",
|
" git add packages/ui/component-catalog.json packages/ui/component-reference.json packages/ui/COMPONENTS.md",
|
||||||
' git commit -m "docs(ui): refresh component reference"',
|
' git commit -m "docs(ui): refresh component reference"',
|
||||||
" git push origin main",
|
" git push origin main",
|
||||||
].join("\n"),
|
].join("\n"),
|
||||||
|
|||||||
@@ -395,6 +395,34 @@ if (!compilerTargetTestSource.includes('targets.browser.replace(/^export\\s+/gm,
|
|||||||
pass("R11 peer-function executable regression test uses the correct export-stripping regex");
|
pass("R11 peer-function executable regression test uses the correct export-stripping regex");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const releaseSource = readFileSync(join(root, "scripts/release.ts"), "utf8");
|
||||||
|
const referenceGeneratorSource = readFileSync(
|
||||||
|
join(root, "scripts/generate-ui-component-reference.mjs"),
|
||||||
|
"utf8",
|
||||||
|
);
|
||||||
|
for (const [label, condition] of [
|
||||||
|
[
|
||||||
|
"canonical generated-reference Git comparison",
|
||||||
|
releaseSource.includes('["diff", "--quiet", "--", ...generatedFiles]') &&
|
||||||
|
releaseSource.includes('["diff", "--name-status", "--", ...generatedFiles]'),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"component catalog included in the release reference gate",
|
||||||
|
releaseSource.includes('"packages/ui/component-catalog.json"'),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"platform-independent component reference ordering",
|
||||||
|
referenceGeneratorSource.includes("function compareText(left, right)") &&
|
||||||
|
referenceGeneratorSource.includes("compareText(left.name, right.name)") &&
|
||||||
|
!referenceGeneratorSource.includes("localeCompare"),
|
||||||
|
],
|
||||||
|
]) {
|
||||||
|
if (!condition) fail(`R12 regression: missing ${label}`);
|
||||||
|
}
|
||||||
|
if (!failures.some((item) => item.startsWith("R12 regression:"))) {
|
||||||
|
pass("R12 release reference gate is canonical, complete, and platform independent");
|
||||||
|
}
|
||||||
|
|
||||||
const showcaseFiles = walk(join(root, "examples/component-showcase/app"), (path) =>
|
const showcaseFiles = walk(join(root, "examples/component-showcase/app"), (path) =>
|
||||||
path.endsWith(".wrn"),
|
path.endsWith(".wrn"),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user