feat: sync showcase with WRNexusJS 0.8.72 and @wrnexus/ui 0.8.88
- Sync app, public, scripts, test and examples from the framework's component-showcase: redesigned component demos, marketing blocks under /blocks, template and preview galleries, distinct Timeline/Section variants, Chat Bubble receipts, a top-placement Drawer demo, and the playground code panel fix (objects in array props no longer blank out). - Standalone adaptations kept: the generator and tests read component-reference.json from the published @wrnexus/ui, and tests use the published @wrnexus/compiler and @wrnexus/syntax. - Dependencies: every @wrnexus/* package to its latest release (ui 0.8.88, styles 0.8.26, core 0.8.16, cli 0.8.72, ...), happy-dom for the playground tests, Tailwind 4.3; bun.lock and package-lock.json refreshed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
bec9ef2889
commit
c0ac38c572
171 files changed
+21983
-35658
No files matched your search
@@ -253,6 +253,43 @@ const DATATABLE_ROWS =
|
||||
'[{"id": 1, "name": "Northwind", "plan": "Scale", "owner": "A. Okafor", "seats": 6, "status": "Active", "statusHtml": "<span class=\\"showcase-pill showcase-pill--success\\">Active</span>"}, {"id": 2, "name": "Acme Industrial", "plan": "Team", "owner": "R. Silva", "seats": 13, "status": "Trial", "statusHtml": "<span class=\\"showcase-pill showcase-pill--info\\">Trial</span>"}, {"id": 3, "name": "Globex", "plan": "Enterprise", "owner": "M. Chen", "seats": 20, "status": "Past due", "statusHtml": "<span class=\\"showcase-pill showcase-pill--danger\\">Past due</span>"}, {"id": 4, "name": "Initech", "plan": "Starter", "owner": "J. Dubois", "seats": 27, "status": "Active", "statusHtml": "<span class=\\"showcase-pill showcase-pill--success\\">Active</span>"}, {"id": 5, "name": "Umbrella", "plan": "Scale", "owner": "P. Novak", "seats": 34, "status": "Trial", "statusHtml": "<span class=\\"showcase-pill showcase-pill--info\\">Trial</span>"}, {"id": 6, "name": "Stark Labs", "plan": "Team", "owner": "A. Okafor", "seats": 41, "status": "Past due", "statusHtml": "<span class=\\"showcase-pill showcase-pill--danger\\">Past due</span>"}, {"id": 7, "name": "Wayne Foods", "plan": "Enterprise", "owner": "R. Silva", "seats": 48, "status": "Active", "statusHtml": "<span class=\\"showcase-pill showcase-pill--success\\">Active</span>"}, {"id": 8, "name": "Soylent", "plan": "Starter", "owner": "M. Chen", "seats": 55, "status": "Trial", "statusHtml": "<span class=\\"showcase-pill showcase-pill--info\\">Trial</span>"}, {"id": 9, "name": "Hooli", "plan": "Scale", "owner": "J. Dubois", "seats": 62, "status": "Past due", "statusHtml": "<span class=\\"showcase-pill showcase-pill--danger\\">Past due</span>"}, {"id": 10, "name": "Vehement", "plan": "Team", "owner": "P. Novak", "seats": 69, "status": "Active", "statusHtml": "<span class=\\"showcase-pill showcase-pill--success\\">Active</span>"}, {"id": 11, "name": "Massive Dynamic", "plan": "Enterprise", "owner": "A. Okafor", "seats": 76, "status": "Trial", "statusHtml": "<span class=\\"showcase-pill showcase-pill--info\\">Trial</span>"}, {"id": 12, "name": "Cyberdyne", "plan": "Starter", "owner": "R. Silva", "seats": 83, "status": "Past due", "statusHtml": "<span class=\\"showcase-pill showcase-pill--danger\\">Past due</span>"}, {"id": 13, "name": "Tyrell", "plan": "Scale", "owner": "M. Chen", "seats": 90, "status": "Active", "statusHtml": "<span class=\\"showcase-pill showcase-pill--success\\">Active</span>"}, {"id": 14, "name": "Aperture", "plan": "Team", "owner": "J. Dubois", "seats": 97, "status": "Trial", "statusHtml": "<span class=\\"showcase-pill showcase-pill--info\\">Trial</span>"}, {"id": 15, "name": "Black Mesa", "plan": "Enterprise", "owner": "P. Novak", "seats": 104, "status": "Past due", "statusHtml": "<span class=\\"showcase-pill showcase-pill--danger\\">Past due</span>"}]';
|
||||
|
||||
export const componentProfiles = {
|
||||
Accordion: {
|
||||
demos: [
|
||||
standard(
|
||||
"Plain disclosure rows",
|
||||
"Unframed questions with trailing chevrons and aligned answers.",
|
||||
{},
|
||||
),
|
||||
compact("Bordered group", "One shared border with leading indicators.", {}),
|
||||
advanced("Separate panels", "Individually framed rows; multiple answers can stay open.", {}),
|
||||
],
|
||||
},
|
||||
Alert: {
|
||||
demos: [
|
||||
standard("Success message", "A concise confirmation that can be dismissed.", {}),
|
||||
compact("Informational notice", "One useful message without unnecessary actions.", {}),
|
||||
advanced("Action required", "A warning with one relevant next step.", {}),
|
||||
],
|
||||
},
|
||||
Carousel: {
|
||||
demos: [
|
||||
standard(
|
||||
"Full-width, unframed",
|
||||
"An edge-to-edge carousel without a card, border, or outer padding.",
|
||||
{ framed: false },
|
||||
),
|
||||
compact(
|
||||
"Framed gallery",
|
||||
"Opt into a contained gallery when the surrounding layout needs it.",
|
||||
{ framed: true },
|
||||
),
|
||||
advanced("Draggable slides", "Move between slides with dragging, arrows, or pagination.", {
|
||||
framed: false,
|
||||
isDraggable: true,
|
||||
}),
|
||||
],
|
||||
},
|
||||
|
||||
Navbar: {
|
||||
demos: [
|
||||
standard(
|
||||
@@ -378,7 +415,7 @@ export const componentProfiles = {
|
||||
description:
|
||||
"Scroll the page and the marker moves to whichever section is in view. The sections below are real page content, because the runtime observes against the viewport -- a table of contents inside a small scrolling box would have nothing to react to.",
|
||||
before:
|
||||
'<div class="showcase-spy-doc"><section id="overview" class="showcase-spy-section"><h3>Overview</h3><p>Scroll this page and watch the marker in the list move. The runtime observes these sections against the viewport, so the current link follows whatever you are reading.</p></section><section id="installation" class="showcase-spy-section"><h3>Installation</h3><p>Each link points at one of these ids. Nothing is wired up by hand -- the component only renders the links, and the runtime moves aria-current.</p></section><section id="usage" class="showcase-spy-section"><h3>Usage</h3><p>The active link is marked with aria-current="location", which is what a screen reader announces, and styled through data-active.</p></section><section id="api" class="showcase-spy-section"><h3>API</h3><p>Clicking a link jumps to its section and marks it immediately, so the control responds even before the scroll settles.</p></section></div>',
|
||||
'<div class="showcase-spy-doc"><section id="overview" class="showcase-spy-section"><h3>Overview</h3><p>Scroll this page and watch the marker in the list move. The runtime observes these sections against the viewport, so the current link follows whatever you are reading.</p></section><section id="installation" class="showcase-spy-section"><h3>Installation</h3><p>Each link points at one of these ids. Nothing is connected up by hand -- the component only renders the links, and the runtime moves aria-current.</p></section><section id="usage" class="showcase-spy-section"><h3>Usage</h3><p>The active link is marked with aria-current="location", which is what a screen reader announces, and styled through data-active.</p></section><section id="api" class="showcase-spy-section"><h3>API</h3><p>Clicking a link jumps to its section and marks it immediately, so the control responds even before the scroll settles.</p></section></div>',
|
||||
props: {
|
||||
heading: "On this page",
|
||||
items: [
|
||||
@@ -1235,7 +1272,7 @@ export const componentProfiles = {
|
||||
standard(
|
||||
"Standard content section",
|
||||
"Create predictable vertical rhythm around a page section.",
|
||||
{ id: "standard-section", spacing: "lg", maxWidth: "xl" },
|
||||
{ id: "standard-section", spacing: "lg", maxWidth: "xl", variant: "grid" },
|
||||
{ default: '<div class="showcase-content-block">Standard section content</div>' },
|
||||
),
|
||||
compact(
|
||||
@@ -1253,7 +1290,7 @@ export const componentProfiles = {
|
||||
maxWidth: "full",
|
||||
borderTop: true,
|
||||
borderBottom: true,
|
||||
variant: "raised",
|
||||
variant: "solid",
|
||||
},
|
||||
{ default: '<div class="showcase-content-block">Full-width public page section</div>' },
|
||||
),
|
||||
@@ -1261,7 +1298,7 @@ export const componentProfiles = {
|
||||
options: {
|
||||
spacing: ["none", "sm", "md", "lg", "xl"],
|
||||
maxWidth: ["compact", "lg", "xl", "wide", "2xl", "full"],
|
||||
variant: ["default", "soft", "raised", "transparent"],
|
||||
variant: ["default", "soft", "raised", "tinted", "solid", "panel", "grid"],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1941,7 +1978,7 @@ export const componentProfiles = {
|
||||
},
|
||||
),
|
||||
],
|
||||
playground: { items: menuItems, open: false, defaultOpen: false, trigger: "click" },
|
||||
playground: { items: menuItems, open: false, defaultOpen: false, trigger: "contextmenu" },
|
||||
options: {
|
||||
trigger: ["contextmenu", "click", "both", "manual"],
|
||||
placement: ["pointer", "top-start", "top-end", "bottom-start", "bottom-end"],
|
||||
@@ -2056,6 +2093,24 @@ export const componentProfiles = {
|
||||
'<div class="showcase-overlay-content showcase-overlay-content--tall"><p>Long scrollable content</p><p>Filters, navigation, details, and forms can be composed here.</p></div>',
|
||||
},
|
||||
),
|
||||
compact(
|
||||
"Top notice drawer",
|
||||
"Slide a panel down from the top edge for announcements, search, or quick settings.",
|
||||
{
|
||||
open: false,
|
||||
defaultOpen: false,
|
||||
triggerLabel: "Open top drawer",
|
||||
triggerIcon: "icon-[lucide--panel-top-open]",
|
||||
title: "Scheduled maintenance",
|
||||
description: "The workspace will be read-only on Sunday from 02:00 to 03:00 UTC.",
|
||||
placement: "top",
|
||||
size: "sm",
|
||||
},
|
||||
{
|
||||
default:
|
||||
'<div class="showcase-overlay-content"><p>Save your work before the window starts.</p></div>',
|
||||
},
|
||||
),
|
||||
],
|
||||
playground: {
|
||||
open: false,
|
||||
@@ -2411,13 +2466,13 @@ export const componentProfiles = {
|
||||
{ default: '<strong class="showcase-card-value">38</strong>' },
|
||||
),
|
||||
advanced(
|
||||
"Raised interactive card",
|
||||
"Use a stronger visual treatment for featured content.",
|
||||
"Featured resource",
|
||||
"Keep the description and next action together in a single surface.",
|
||||
{
|
||||
title: "Featured guide",
|
||||
description: "A complete guide to public safety and emergency readiness.",
|
||||
size: "spacious",
|
||||
variant: "raised",
|
||||
size: "lg",
|
||||
variant: "default",
|
||||
},
|
||||
{ default: '<a href="#guide" class="showcase-action">Read guide</a>' },
|
||||
),
|
||||
@@ -2785,7 +2840,7 @@ export const componentProfiles = {
|
||||
{ title: "Document uploaded", time: "3 days ago" },
|
||||
],
|
||||
size: "sm",
|
||||
variant: "soft",
|
||||
variant: "compact",
|
||||
},
|
||||
),
|
||||
advanced(
|
||||
@@ -2814,11 +2869,11 @@ export const componentProfiles = {
|
||||
},
|
||||
],
|
||||
size: "lg",
|
||||
variant: "raised",
|
||||
variant: "alternate",
|
||||
},
|
||||
),
|
||||
],
|
||||
options: { size: ["sm", "default", "lg"], variant: ["default", "soft", "raised", "outline"] },
|
||||
options: { size: ["sm", "default", "lg"], variant: ["default", "soft", "raised", "outline", "minimal", "compact", "alternate"] },
|
||||
},
|
||||
|
||||
Typography: {
|
||||
@@ -2903,6 +2958,30 @@ const genericEventDescriptions = {
|
||||
toggle: "Fires when the component changes between open and closed or on and off states.",
|
||||
};
|
||||
|
||||
|
||||
componentProfiles.Card.demos.push(
|
||||
standard("Image with footer", "A cover image, concise body, and separate footer.", {title:"Design your next chapter",description:"A practical guide to building thoughtful products.",imageSrc:"/showcase-images/green-hero.svg",imageAlt:"Green abstract cover",footer:"6 min read",actionLabel:"Read guide",actionHref:"#guide"}),
|
||||
compact("Without a header", "Body content with an optional footer; no reserved heading space.", {title:"",description:"Your workspace is ready. Invite your teammates to get started.",footer:"Updated just now"}, {default:""}),
|
||||
advanced("Image-only card", "A simple image surface without header or footer chrome.", {title:"",description:"",imageSrc:"/showcase-images/blue-mountain.svg",imageAlt:"Blue geometric landscape"}, {default:""}),
|
||||
);
|
||||
componentProfiles.Map = { demos:[
|
||||
standard("OpenStreetMap", "A real interactive geographic map. Set latitude, longitude and zoomLevel; no API key is needed.", {title:"Bengaluru",description:"Pan and zoom to explore the city",provider:"openstreetmap",latitude:12.9716,longitude:77.5946,zoomLevel:13,imageSrc:"",items:[]}),
|
||||
compact("Google Maps", "Pass your restricted Maps Embed API key and a place query to show Google Maps.", {title:"Google Maps",provider:"google",apiKey:"",query:"Bengaluru",imageSrc:"",items:[]}),
|
||||
], playground:{title:"Bengaluru",description:"Interactive geographic map",provider:"openstreetmap",latitude:12.9716,longitude:77.5946,zoomLevel:13,imageSrc:"",items:[]}, options:{provider:["openstreetmap","google"]} };
|
||||
componentProfiles.Rating = {demos:[standard("Whole stars", "Choose a rating from zero to five with step 1.",{title:"Rate your experience",value:3,step:1}),compact("Half stars", "Click a half star or use the precise slider and arrow keys.",{title:"Half-star rating",value:3.5,step:0.5}),advanced("Fine increments", "Use increments of 0.2 for a more precise rating.",{title:"Detailed score",value:4.2,step:0.2})]};
|
||||
componentProfiles.LegendIndicator = {demos:[standard("Chart legend", "Toggle a series and handle @toggle to update your chart.",{title:"Traffic sources",description:"Select a source to toggle its visibility.",items:[{label:"Direct",color:"#8b5cf6",value:"42%"},{label:"Search",color:"#14b8a6",value:"35%"},{label:"Referral",color:"#f59e0b",value:"23%"}]})]};
|
||||
componentProfiles.Chart = {demos:[standard("Bar chart", "Pass an array of label/value objects through data.",{title:"Weekly signups",type:"bar",data:[{label:"Mon",value:24},{label:"Tue",value:38},{label:"Wed",value:29},{label:"Thu",value:52},{label:"Fri",value:45}],items:[],showLegend:false}),compact("Line chart", "Use type=line to compare a trend over time.",{title:"Monthly revenue",type:"line",data:[{label:"Jan",value:20},{label:"Feb",value:35},{label:"Mar",value:28},{label:"Apr",value:55}],items:[],showLegend:false})],options:{type:["bar","line"]}};
|
||||
componentProfiles.DatePicker = { demos:[
|
||||
standard("Date picker", "An anchored calendar that does not move surrounding content.", {label:"Start date",name:"start-date",type:"date"}),
|
||||
compact("Date and time", "Choose a calendar date and a time in one field.", {label:"Schedule for",name:"schedule",type:"datetime-local",value:"2026-09-20T09:30"}),
|
||||
advanced("Disabled date", "A read-only scheduled date.", {label:"Scheduled date",readonly:true}),
|
||||
], options:{type:["date","datetime-local"]} };
|
||||
componentProfiles.TimePicker = { demos:[standard("Time picker", "Choose an hour and minute in an anchored panel.", {label:"Meeting time",name:"meeting-time",value:"09:30"})] };
|
||||
componentProfiles.Modal.demos.push(
|
||||
advanced("Custom header and footer", "Supply your own header, body, and footer actions.", {title:"",description:"",cancelLabel:"",confirmLabel:"",triggerLabel:"Open custom dialog"}, {header:'<h2>Invite a teammate</h2>',default:'<p>Give your teammate access to your workspace.</p>',footer:`<button type="button" class="showcase-action" data-modal-close="true">Done</button>`}),
|
||||
compact("Centered content", "Omit the standard header and footer for a fully custom composition.", {showHeader:false,showFooter:false,title:"",description:"",icon:"",size:"sm",triggerLabel:"Open centered dialog"}, {default:`<div style="text-align:center;padding:2rem"><h2>You are all set</h2><p>Your preferences have been saved.</p><button type="button" class="showcase-action" data-modal-close="true">Continue</button></div>`}),
|
||||
);
|
||||
|
||||
export function profileFor(name) {
|
||||
return componentProfiles[name] ?? null;
|
||||
}
|
||||
@@ -2912,3 +2991,9 @@ export function eventDescriptionFor(_componentName, eventName) {
|
||||
genericEventDescriptions[eventName] ?? `Fires when the component emits the ${eventName} event.`
|
||||
);
|
||||
}
|
||||
|
||||
componentProfiles.Card.demos.push(advanced("Custom slots", "Supply arbitrary header, body, and footer content. Use showHeader and showFooter to hide either region.", {title:"",description:"",showHeader:true,showFooter:true,footer:"",actionLabel:""}, {header:"<strong>Team invitation</strong>",default:'<Input label="Email" placeholder="name@company.com" />',footer:'<Button label="Send invitation" />'}));
|
||||
componentProfiles.RangeSlider = { demos: [compact("Fractional steps", "Use step=0.2 for precise increments with buttons, dragging, or arrow keys.", {label:"Scale",min:0,max:5,value:2.4,step:0.2})] };
|
||||
|
||||
|
||||
componentProfiles.FileInput = {demos:[standard("Choose a document", "Select a PDF or image. The selected filename replaces the placeholder.", {label:"Attachment",name:"attachment",value:"",accept:".pdf,image/*",helperText:"PDF or image",placeholder:"Choose a file"}),compact("Multiple attachments", "Select several files; each filename is shown in the control.",{label:"Attachments",name:"attachments",value:"",multiple:true,placeholder:"Choose files"}),advanced("Disabled upload", "A disabled control cannot open the file chooser.",{label:"Attachment",name:"disabled-file",value:"",disabled:true,placeholder:"Uploads unavailable"})]};
|
||||
Reference in new issue
Block a user