@santi020k/lumen 3.0.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +207 -3
- package/dist/cli.js +49 -5
- package/dist/consumer-upgrade-audit.d.ts +10 -0
- package/dist/consumer-upgrade-audit.d.ts.map +1 -0
- package/dist/consumer-upgrade-audit.js +52 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/installer.d.ts.map +1 -1
- package/dist/installer.js +16 -0
- package/dist/integration-diagnostics.d.ts.map +1 -1
- package/dist/integration-diagnostics.js +199 -3
- package/dist/registry-component-name.d.ts +2 -0
- package/dist/registry-component-name.d.ts.map +1 -0
- package/dist/registry-component-name.js +53 -0
- package/dist/registry-data.d.ts +339 -18
- package/dist/registry-data.d.ts.map +1 -1
- package/dist/registry-data.js +789 -3
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +11 -9
- package/dist/source-script-ranges.d.ts +3 -0
- package/dist/source-script-ranges.d.ts.map +1 -0
- package/dist/source-script-ranges.js +41 -0
- package/dist/v2-migration.d.ts +38 -0
- package/dist/v2-migration.d.ts.map +1 -1
- package/dist/v2-migration.js +26 -14
- package/dist/v4-migration.d.ts +26 -0
- package/dist/v4-migration.d.ts.map +1 -0
- package/dist/v4-migration.js +272 -0
- package/dist/version-migration-dependencies.d.ts +8 -0
- package/dist/version-migration-dependencies.d.ts.map +1 -0
- package/dist/version-migration-dependencies.js +10 -0
- package/dist/version-migration-source.d.ts +4 -0
- package/dist/version-migration-source.d.ts.map +1 -0
- package/dist/version-migration-source.js +281 -0
- package/dist/version-migration.d.ts +34 -0
- package/dist/version-migration.d.ts.map +1 -0
- package/dist/version-migration.js +158 -0
- package/native-components.json +563 -16
- package/package.json +26 -11
- package/release-manifest.json +22 -17
- package/styles/critical.css +634 -61
- package/styles/motion.css +61 -0
- package/styles/world-map.css +30 -0
- package/styles.css +1736 -455
- package/templates/astro/advanced-fields/src/lumen/advanced-fields.astro +35 -0
- package/templates/astro/ai-docs/llms.txt +3 -0
- package/templates/astro/analytics-dashboard/src/lumen/analytics-dashboard.astro +110 -0
- package/templates/astro/auth-onboarding/src/lumen/auth-onboarding.astro +107 -0
- package/templates/astro/command-center/src/lumen/command-center.astro +34 -0
- package/templates/astro/commerce-dashboard/src/lumen/commerce-dashboard.astro +108 -0
- package/templates/astro/content-flow-actions/src/lumen/content-flow-actions.astro +10 -0
- package/templates/astro/content-flow-header/src/lumen/content-flow-header.astro +14 -0
- package/templates/astro/content-flow-list/src/lumen/content-flow-list.astro +13 -0
- package/templates/astro/content-flow-settings/src/lumen/content-flow-settings.astro +17 -0
- package/templates/astro/data-collections/src/lumen/data-collections.astro +52 -0
- package/templates/astro/feature-preview/src/lumen/feature-preview.astro +32 -0
- package/templates/astro/guided-onboarding/src/lumen/guided-onboarding.astro +35 -0
- package/templates/astro/interactive-pricing/src/lumen/interactive-pricing.astro +32 -0
- package/templates/astro/media-workspace/src/lumen/adjustment-controls.astro +89 -0
- package/templates/astro/media-workspace/src/lumen/media-processing.astro +47 -0
- package/templates/astro/media-workspace/src/lumen/media-workspace.astro +77 -0
- package/templates/astro/page-header/src/lumen/page-header.astro +41 -0
- package/templates/astro/project-workspace/src/lumen/project-workspace.astro +103 -0
- package/templates/astro/rich-text-editor/src/lumen/rich-text-editor.astro +21 -0
- package/templates/astro/saas-admin/src/lumen/saas-admin.astro +110 -0
- package/templates/astro/scheduler/src/lumen/scheduler.astro +36 -0
- package/templates/astro/section-header/src/lumen/section-header.astro +35 -0
- package/templates/astro/theme-builder/src/lumen/theme-builder.astro +28 -0
- package/templates/elements/advanced-fields/src/lumen/advanced-fields.html +25 -0
- package/templates/elements/analytics-dashboard/src/lumen/analytics-dashboard.html +28 -0
- package/templates/elements/auth-onboarding/src/lumen/auth-onboarding.html +79 -0
- package/templates/elements/command-center/src/lumen/command-center.html +15 -0
- package/templates/elements/commerce-dashboard/src/lumen/commerce-dashboard.html +24 -0
- package/templates/elements/content-flow-actions/src/lumen/content-flow-actions.html +11 -0
- package/templates/elements/content-flow-header/src/lumen/content-flow-header.html +15 -0
- package/templates/elements/content-flow-list/src/lumen/content-flow-list.html +14 -0
- package/templates/elements/content-flow-settings/src/lumen/content-flow-settings.html +18 -0
- package/templates/elements/data-collections/src/lumen/data-collections.html +31 -0
- package/templates/elements/feature-preview/src/lumen/feature-preview.html +13 -0
- package/templates/elements/guided-onboarding/src/lumen/guided-onboarding.html +16 -0
- package/templates/elements/interactive-pricing/src/lumen/interactive-pricing.html +13 -0
- package/templates/elements/media-workspace/src/lumen/media-workspace.html +57 -0
- package/templates/elements/media-workspace/src/lumen/media-workspace.ts +163 -0
- package/templates/elements/page-header/src/lumen/page-header.html +20 -0
- package/templates/elements/project-workspace/src/lumen/project-workspace.html +17 -0
- package/templates/elements/rich-text-editor/src/lumen/rich-text-editor.html +17 -0
- package/templates/elements/saas-admin/src/lumen/saas-admin.html +18 -0
- package/templates/elements/scheduler/src/lumen/scheduler.html +27 -0
- package/templates/elements/section-header/src/lumen/section-header.html +21 -0
- package/templates/elements/theme-builder/src/lumen/theme-builder.html +59 -0
- package/templates/react/advanced-fields/src/lumen/advanced-fields.tsx +37 -0
- package/templates/react/analytics-dashboard/src/lumen/analytics-dashboard.tsx +143 -0
- package/templates/react/auth-onboarding/src/lumen/auth-onboarding.tsx +129 -0
- package/templates/react/command-center/src/lumen/command-center.tsx +85 -0
- package/templates/react/commerce-dashboard/src/lumen/commerce-dashboard.tsx +148 -0
- package/templates/react/content-flow-actions/src/lumen/content-flow-actions.tsx +11 -0
- package/templates/react/content-flow-header/src/lumen/content-flow-header.tsx +14 -0
- package/templates/react/content-flow-list/src/lumen/content-flow-list.tsx +19 -0
- package/templates/react/content-flow-settings/src/lumen/content-flow-settings.tsx +26 -0
- package/templates/react/data-collections/src/lumen/data-collections.tsx +60 -0
- package/templates/react/feature-preview/src/lumen/feature-preview.tsx +42 -0
- package/templates/react/guided-onboarding/src/lumen/guided-onboarding.tsx +100 -0
- package/templates/react/import-review/src/lumen/import-review.tsx +150 -0
- package/templates/react/interactive-pricing/src/lumen/interactive-pricing.tsx +60 -0
- package/templates/react/media-workspace/src/lumen/adjustment-controls.tsx +61 -0
- package/templates/react/media-workspace/src/lumen/media-processing.tsx +43 -0
- package/templates/react/media-workspace/src/lumen/media-workspace.tsx +100 -0
- package/templates/react/operational-records/src/lumen/operational-records.tsx +92 -0
- package/templates/react/page-header/src/lumen/page-header.tsx +41 -0
- package/templates/react/project-workspace/src/lumen/project-workspace.tsx +112 -0
- package/templates/react/record-workspace/src/lumen/record-workspace.tsx +67 -0
- package/templates/react/review-workflow/src/lumen/review-workflow.tsx +202 -0
- package/templates/react/rich-text-editor/src/lumen/rich-text-editor.tsx +33 -0
- package/templates/react/saas-admin/src/lumen/saas-admin.tsx +119 -0
- package/templates/react/scheduler/src/lumen/scheduler.tsx +45 -0
- package/templates/react/section-header/src/lumen/section-header.tsx +33 -0
- package/templates/react/styles.d.ts +1 -0
- package/templates/react/theme-builder/src/lumen/theme-builder.tsx +57 -0
- package/templates/react/tsconfig.json +14 -0
- package/templates/react/validated-form/src/lumen/validated-form.tsx +166 -0
- package/templates/shared/common/src/lumen/lumen-template.css +247 -0
- package/templates/shared/media-workspace/src/lumen/media-workspace.css +14 -0
- package/templates/shared/visual-blocks/src/lumen/product-blocks.ts +224 -0
- package/v4-migration.json +447 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<link rel="stylesheet" href="./lumen-template.css" />
|
|
2
|
+
|
|
3
|
+
<script type="module">
|
|
4
|
+
import { defineLumenElements } from '@santi020k/lumen-elements/define'
|
|
5
|
+
|
|
6
|
+
defineLumenElements()
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<main class="lumen-template lumen-template__form-shell">
|
|
10
|
+
<lumen-card class="lumen-template__form">
|
|
11
|
+
<lumen-stepper role="list" aria-label="Setup steps">
|
|
12
|
+
<div class="ui-stepper__step" data-state="complete" role="listitem">
|
|
13
|
+
<span class="ui-stepper__marker">1</span>
|
|
14
|
+
<span class="ui-stepper__content"><span class="ui-stepper__title">Account</span></span>
|
|
15
|
+
</div>
|
|
16
|
+
<div aria-current="step" class="ui-stepper__step" data-state="current" role="listitem">
|
|
17
|
+
<span class="ui-stepper__marker">2</span>
|
|
18
|
+
<span class="ui-stepper__content"><span class="ui-stepper__title">Workspace</span></span>
|
|
19
|
+
</div>
|
|
20
|
+
<div class="ui-stepper__step" data-state="upcoming" role="listitem">
|
|
21
|
+
<span class="ui-stepper__marker">3</span>
|
|
22
|
+
<span class="ui-stepper__content"><span class="ui-stepper__title">Preferences</span></span>
|
|
23
|
+
</div>
|
|
24
|
+
<div class="ui-stepper__step" data-state="upcoming" role="listitem">
|
|
25
|
+
<span class="ui-stepper__marker">4</span>
|
|
26
|
+
<span class="ui-stepper__content"><span class="ui-stepper__title">Invite</span></span>
|
|
27
|
+
</div>
|
|
28
|
+
</lumen-stepper>
|
|
29
|
+
<header><p class="lumen-template__muted">Step 2 of 4</p><h1>Create your workspace</h1><p class="lumen-template__muted">We’ll prepare the right starting point.</p></header>
|
|
30
|
+
<form class="lumen-template__form">
|
|
31
|
+
<lumen-field class="lumen-template__field"><label for="workspace-name">Workspace name</label><lumen-input id="workspace-name" name="workspace" placeholder="Northstar Labs" required></lumen-input></lumen-field>
|
|
32
|
+
<lumen-field class="lumen-template__field"><label for="work-email">Work email</label><lumen-input aria-invalid="true" id="work-email" name="email" type="email" value="maya@example" required></lumen-input><lumen-alert role="alert" variant="destructive">Enter a complete email address.</lumen-alert></lumen-field>
|
|
33
|
+
<fieldset class="lumen-template__choices"><legend>What are you setting up?</legend><label class="lumen-template__choice"><input checked name="intent" type="radio" value="team" /> A team workspace</label><label class="lumen-template__choice"><input name="intent" type="radio" value="personal" /> A personal workspace</label></fieldset>
|
|
34
|
+
<label><lumen-checkbox checked name="updates" value="updates"></lumen-checkbox> Send occasional onboarding tips</label>
|
|
35
|
+
<div><div class="lumen-template__section-header"><span>Setup progress</span><strong>50%</strong></div><lumen-progress aria-label="Setup is 50% complete" value="50"></lumen-progress></div>
|
|
36
|
+
<div class="lumen-template__actions"><lumen-button variant="ghost">Back</lumen-button><lumen-button type="submit">Continue</lumen-button></div>
|
|
37
|
+
</form>
|
|
38
|
+
</lumen-card>
|
|
39
|
+
<section class="lumen-login-examples" aria-labelledby="login-examples-title">
|
|
40
|
+
<header>
|
|
41
|
+
<p>Returning members</p>
|
|
42
|
+
<h2 id="login-examples-title">A familiar way back in.</h2>
|
|
43
|
+
<p>Email codes and passkeys, composed with Lumen. These visual examples do not send codes or sign you in.</p>
|
|
44
|
+
</header>
|
|
45
|
+
<lumen-grid class="lumen-login-examples__grid">
|
|
46
|
+
<lumen-card class="lumen-login-examples__card">
|
|
47
|
+
<h3>Welcome back</h3>
|
|
48
|
+
<p>Use a saved passkey or receive a code by email.</p>
|
|
49
|
+
<lumen-button disabled type="button">Sign in with a passkey</lumen-button>
|
|
50
|
+
<lumen-field>
|
|
51
|
+
<label for="login-email">Email address</label>
|
|
52
|
+
<lumen-input autocomplete="email" id="login-email" name="login-email" readonly type="email" value="member@example.com"></lumen-input>
|
|
53
|
+
</lumen-field>
|
|
54
|
+
<lumen-button disabled type="button">Send sign-in code</lumen-button>
|
|
55
|
+
<p>No password to remember.</p>
|
|
56
|
+
</lumen-card>
|
|
57
|
+
<lumen-card class="lumen-login-examples__card">
|
|
58
|
+
<h3>Check your inbox</h3>
|
|
59
|
+
<p>If this address can sign in, a code will arrive shortly.</p>
|
|
60
|
+
<lumen-field>
|
|
61
|
+
<label for="login-code">Email code</label>
|
|
62
|
+
<lumen-input aria-describedby="login-code-hint" autocomplete="one-time-code" id="login-code" inputmode="numeric" name="login-code" placeholder="Enter your code" readonly></lumen-input>
|
|
63
|
+
<p id="login-code-hint">Paste the complete code from your email.</p>
|
|
64
|
+
</lumen-field>
|
|
65
|
+
<lumen-button disabled type="button">Verify and continue</lumen-button>
|
|
66
|
+
<lumen-button disabled type="button" variant="outline">Resend code</lumen-button>
|
|
67
|
+
<p>Entered the wrong address? Return to email sign-in.</p>
|
|
68
|
+
</lumen-card>
|
|
69
|
+
<lumen-card class="lumen-login-examples__card">
|
|
70
|
+
<h3>Try another way</h3>
|
|
71
|
+
<lumen-alert variant="destructive">Passkey sign-in was canceled. You can try again or request a code by email.</lumen-alert>
|
|
72
|
+
<p>You can still use email when your passkey is unavailable.</p>
|
|
73
|
+
<lumen-button disabled type="button">Try passkey again</lumen-button>
|
|
74
|
+
<lumen-button disabled type="button" variant="outline">Use an email code</lumen-button>
|
|
75
|
+
<p>Your existing account and workspace stay the same.</p>
|
|
76
|
+
</lumen-card>
|
|
77
|
+
</lumen-grid>
|
|
78
|
+
</section>
|
|
79
|
+
</main>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<section data-product-block="command" aria-label="Workspace commands">
|
|
2
|
+
<lumen-typography><h2>What would you like to do?</h2><p>Search with the keyboard, then choose a command.</p></lumen-typography>
|
|
3
|
+
<lumen-command><lumen-input type="search" aria-label="Search workspace commands" placeholder="Search commands…" ></lumen-input>
|
|
4
|
+
<button data-ui-command-item data-workspace-command="search" type="button">Search project documentation</button>
|
|
5
|
+
<button data-ui-command-item data-workspace-command="create" type="button">Create a task draft</button>
|
|
6
|
+
<button data-ui-command-item data-workspace-command="review" type="button">Review pending proposals</button>
|
|
7
|
+
</lumen-command><p role="status" data-block-status>Choose a command.</p>
|
|
8
|
+
</section>
|
|
9
|
+
<script type="module">
|
|
10
|
+
import { defineLumenElements } from '@santi020k/lumen-elements'
|
|
11
|
+
import { mountProductBlocks } from './product-blocks.js'
|
|
12
|
+
defineLumenElements()
|
|
13
|
+
const cleanup = mountProductBlocks(document)
|
|
14
|
+
window.addEventListener('pagehide', cleanup, { once: true })
|
|
15
|
+
</script>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<link rel="stylesheet" href="./lumen-template.css" />
|
|
2
|
+
|
|
3
|
+
<script type="module">
|
|
4
|
+
import { defineLumenElements } from '@santi020k/lumen-elements/define'
|
|
5
|
+
|
|
6
|
+
defineLumenElements()
|
|
7
|
+
|
|
8
|
+
const sales = document.querySelector('#commerce-sales')
|
|
9
|
+
const sources = document.querySelector('#commerce-sources')
|
|
10
|
+
|
|
11
|
+
if (sales) sales.series = [{ data: [{ x: 'Mon', y: 11200 }, { x: 'Tue', y: 13800 }, { x: 'Wed', y: 12600 }, { x: 'Thu', y: 15400 }, { x: 'Fri', y: 16800 }], id: 'sales', label: 'Sales', tone: 'brand' }]
|
|
12
|
+
if (sources) sources.series = { data: [{ x: 'Online', y: 812 }, { x: 'Marketplace', y: 286 }, { x: 'POS', y: 186 }], id: 'orders', label: 'Orders' }
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<div class="lumen-template lumen-template__shell">
|
|
16
|
+
<lumen-sidebar class="lumen-template__sidebar"><strong>Mercury Commerce</strong><nav aria-label="Commerce"><a aria-current="page" href="#overview">Overview</a><a href="#orders">Orders</a><a href="#inventory">Inventory</a></nav></lumen-sidebar>
|
|
17
|
+
<main class="lumen-template__main" id="overview">
|
|
18
|
+
<header class="lumen-template__header"><div><lumen-badge variant="outline">Store overview</lumen-badge><h1>Commerce command center</h1><p>Sales, fulfillment, and inventory risk.</p></div><lumen-button>Add product</lumen-button></header>
|
|
19
|
+
<section class="lumen-template__metrics" aria-label="Commerce metrics"><lumen-card class="lumen-template__metric"><lumen-stat label="Gross sales" value="$92,840"></lumen-stat><lumen-badge variant="success">+18.6%</lumen-badge></lumen-card><lumen-card class="lumen-template__metric"><lumen-stat label="Orders" value="1,284"></lumen-stat><lumen-badge variant="success">+7.4%</lumen-badge></lumen-card><lumen-card class="lumen-template__metric"><lumen-stat label="Average order" value="$72.31"></lumen-stat><lumen-badge variant="success">+$6.20</lumen-badge></lumen-card><lumen-card class="lumen-template__metric"><lumen-stat label="Return rate" value="2.1%"></lumen-stat><lumen-badge variant="success">-0.4%</lumen-badge></lumen-card></section>
|
|
20
|
+
<section class="lumen-template__grid"><lumen-bar-chart heading="Sales this week" id="commerce-sales"></lumen-bar-chart><lumen-pie-chart center-label="orders" center-value="1,284" heading="Order sources" id="commerce-sources"></lumen-pie-chart></section>
|
|
21
|
+
<section class="lumen-template__grid" id="inventory"><lumen-card class="lumen-template__panel"><h2>Fulfillment</h2><lumen-stat label="Orders ready" value="42"></lumen-stat><lumen-progress aria-label="42 of 58 orders fulfilled" max="58" value="42"></lumen-progress></lumen-card><lumen-card class="lumen-template__panel"><h2>Inventory signals</h2><ul class="lumen-template__list"><li>3 products below safety stock</li><li>8 transfers arriving this week</li><li>94% inventory accuracy</li></ul></lumen-card></section>
|
|
22
|
+
<lumen-card class="lumen-template__panel" id="orders"><div class="lumen-template__section-header"><h2>Recent orders</h2><lumen-button variant="ghost">View all</lumen-button></div><lumen-table class="lumen-template__table"><table><thead><tr><th>Order</th><th>Customer</th><th>Status</th><th>Total</th></tr></thead><tbody><tr><td>#10482</td><td>Nora Singh</td><td><lumen-badge variant="success">Completed</lumen-badge></td><td>$148.00</td></tr><tr><td>#10481</td><td>Theo Martin</td><td><lumen-badge variant="warning">Pending</lumen-badge></td><td>$84.50</td></tr></tbody></table></lumen-table></lumen-card>
|
|
23
|
+
</main>
|
|
24
|
+
</div>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script type="module">
|
|
2
|
+
import { defineLumenElements } from '@santi020k/lumen-elements/define'
|
|
3
|
+
defineLumenElements(['Stack', 'Button'])
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<lumen-stack role="group" aria-label="Changes" gap="related">
|
|
7
|
+
<p role="status">You have unsaved changes.</p>
|
|
8
|
+
<lumen-stack direction="horizontal" gap="related" wrap>
|
|
9
|
+
<lumen-button>Save changes</lumen-button><lumen-button variant="secondary">Discard changes</lumen-button>
|
|
10
|
+
</lumen-stack>
|
|
11
|
+
</lumen-stack>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script type="module">
|
|
2
|
+
import { defineLumenElements } from '@santi020k/lumen-elements/define'
|
|
3
|
+
defineLumenElements(['Stack', 'Typography', 'Button'])
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<lumen-stack gap="group" role="region" aria-labelledby="workspace-heading">
|
|
7
|
+
<lumen-typography>
|
|
8
|
+
<h1 id="workspace-heading">Workspace settings</h1>
|
|
9
|
+
<p>Manage your team’s access and notification preferences.</p>
|
|
10
|
+
</lumen-typography>
|
|
11
|
+
<lumen-stack direction="horizontal" gap="related" wrap>
|
|
12
|
+
<lumen-button>Invite a teammate</lumen-button>
|
|
13
|
+
<lumen-button variant="secondary">View activity</lumen-button>
|
|
14
|
+
</lumen-stack>
|
|
15
|
+
</lumen-stack>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<script type="module">
|
|
2
|
+
import { defineLumenElements } from '@santi020k/lumen-elements/define'
|
|
3
|
+
defineLumenElements(['Card', 'CardHeader', 'CardTitle', 'CardContent', 'Stack', 'Badge'])
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<lumen-card role="region" aria-labelledby="members-heading">
|
|
7
|
+
<lumen-card-header><lumen-card-title id="members-heading" role="heading" aria-level="2">Team members</lumen-card-title></lumen-card-header>
|
|
8
|
+
<lumen-card-content>
|
|
9
|
+
<lumen-stack role="list" gap="group">
|
|
10
|
+
<lumen-stack role="listitem" direction="horizontal" align="center" justify="between" gap="related" wrap><span>Alex Morgan — Workspace owner</span><lumen-badge>Active</lumen-badge></lumen-stack>
|
|
11
|
+
<lumen-stack role="listitem" direction="horizontal" align="center" justify="between" gap="related" wrap><span>Jamie Lee — Design and operations</span><lumen-badge variant="secondary">Invited</lumen-badge></lumen-stack>
|
|
12
|
+
</lumen-stack>
|
|
13
|
+
</lumen-card-content>
|
|
14
|
+
</lumen-card>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<script type="module">
|
|
2
|
+
import { defineLumenElements } from '@santi020k/lumen-elements/define'
|
|
3
|
+
defineLumenElements(['Card', 'CardHeader', 'CardTitle', 'CardDescription', 'CardContent', 'CardFooter', 'Stack', 'Field', 'Label', 'Input', 'Button'])
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<lumen-card role="region" aria-labelledby="notification-heading">
|
|
7
|
+
<lumen-card-header>
|
|
8
|
+
<lumen-card-title id="notification-heading" role="heading" aria-level="2">Notifications</lumen-card-title>
|
|
9
|
+
<lumen-card-description>Choose where your team receives updates.</lumen-card-description>
|
|
10
|
+
</lumen-card-header>
|
|
11
|
+
<lumen-card-content>
|
|
12
|
+
<lumen-stack gap="group">
|
|
13
|
+
<lumen-field><lumen-label id="team-name-label">Team name</lumen-label><lumen-input id="team-name" name="team" aria-labelledby="team-name-label" autocomplete="organization"></lumen-input></lumen-field>
|
|
14
|
+
<lumen-field><lumen-label id="team-email-label">Team email</lumen-label><lumen-input id="team-email" name="email" aria-labelledby="team-email-label" type="email" autocomplete="email"></lumen-input></lumen-field>
|
|
15
|
+
</lumen-stack>
|
|
16
|
+
</lumen-card-content>
|
|
17
|
+
<lumen-card-footer><lumen-button>Save preferences</lumen-button><lumen-button variant="secondary">Discard changes</lumen-button></lumen-card-footer>
|
|
18
|
+
</lumen-card>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<script type="module">
|
|
2
|
+
import { defineLumenElements } from '@santi020k/lumen-elements/define'
|
|
3
|
+
|
|
4
|
+
defineLumenElements()
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<section class="lumen-recipe lumen-recipe--data-collections">
|
|
8
|
+
<lumen-command>
|
|
9
|
+
<input type="search" placeholder="Filter records" />
|
|
10
|
+
<button data-ui-command-item type="button">Open docs</button>
|
|
11
|
+
</lumen-command>
|
|
12
|
+
<lumen-data-table>
|
|
13
|
+
<table>
|
|
14
|
+
<thead><tr><th>Name</th><th>Status</th></tr></thead>
|
|
15
|
+
<tbody><tr><td>Docs</td><td>Ready</td></tr></tbody>
|
|
16
|
+
</table>
|
|
17
|
+
</lumen-data-table>
|
|
18
|
+
<lumen-tree aria-label="Files">
|
|
19
|
+
<div role="treeitem" aria-expanded="true">src</div>
|
|
20
|
+
<div role="treeitem">index.ts</div>
|
|
21
|
+
</lumen-tree>
|
|
22
|
+
<lumen-tree-grid aria-label="Project status">
|
|
23
|
+
<div role="row"><span role="gridcell">Docs</span><span role="gridcell">Ready</span></div>
|
|
24
|
+
</lumen-tree-grid>
|
|
25
|
+
<lumen-virtual-list data-ui-item-size="44" style="--ui-list-height: 12rem">
|
|
26
|
+
<div>Row 1</div>
|
|
27
|
+
<div>Row 2</div>
|
|
28
|
+
<div>Row 3</div>
|
|
29
|
+
</lumen-virtual-list>
|
|
30
|
+
<lumen-pagination><a href="?page=1">Previous</a><a href="?page=2">Next</a></lumen-pagination>
|
|
31
|
+
</section>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<section data-product-block="feature" aria-label="Feature preview">
|
|
2
|
+
<lumen-typography><h2>From idea to delivery</h2></lumen-typography>
|
|
3
|
+
<lumen-stack direction="horizontal" gap="related" role="group" aria-label="Preview a workflow stage"><lumen-button data-feature="plan" aria-pressed="true">Plan</lumen-button><lumen-button data-feature="review" aria-pressed="false">Review</lumen-button><lumen-button data-feature="ship" aria-pressed="false">Ship</lumen-button></lumen-stack>
|
|
4
|
+
<lumen-motion-group><lumen-card data-ui-motion-key="plan" data-feature-panel="plan"><lumen-visual-effect variant="mesh"><lumen-typography><h3>Plan</h3><p>Bring the next three tasks into focus.</p></lumen-typography></lumen-visual-effect></lumen-card><lumen-card hidden data-ui-motion-key="review" data-feature-panel="review"><lumen-visual-effect variant="mesh"><lumen-typography><h3>Review</h3><p>Compare a proposal before deciding.</p></lumen-typography></lumen-visual-effect></lumen-card><lumen-card hidden data-ui-motion-key="ship" data-feature-panel="ship"><lumen-visual-effect variant="mesh"><lumen-typography><h3>Ship</h3><p>Check the release evidence before publishing.</p></lumen-typography></lumen-visual-effect></lumen-card></lumen-motion-group>
|
|
5
|
+
<p role="status" data-block-status>Previewing plan.</p>
|
|
6
|
+
</section>
|
|
7
|
+
<script type="module">
|
|
8
|
+
import { defineLumenElements } from '@santi020k/lumen-elements'
|
|
9
|
+
import { mountProductBlocks } from './product-blocks.js'
|
|
10
|
+
defineLumenElements()
|
|
11
|
+
const cleanup = mountProductBlocks(document)
|
|
12
|
+
window.addEventListener('pagehide', cleanup, { once: true })
|
|
13
|
+
</script>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<section data-product-block="onboarding" aria-label="Workspace setup">
|
|
2
|
+
<lumen-card><lumen-stack gap="group"><lumen-typography><h2>Prepare your workspace</h2><p>This draft stays local until your application handles completion.</p></lumen-typography>
|
|
3
|
+
<form method="post"><lumen-stack gap="group">
|
|
4
|
+
<section data-onboarding-step="0"><lumen-typography><h3 tabindex="-1">Workspace</h3></lumen-typography><lumen-label id="workspace-draft-name-label">Workspace name</lumen-label><lumen-input id="workspace-draft-name" aria-labelledby="workspace-draft-name-label" name="workspace" data-workspace-name required maxlength="80" ></lumen-input></section>
|
|
5
|
+
<section data-onboarding-step="1" hidden><lumen-typography><h3 tabindex="-1">Review your draft</h3><p>Workspace: <span data-workspace-review></span></p></lumen-typography></section>
|
|
6
|
+
<section data-onboarding-step="2" hidden><lumen-typography><h3 tabindex="-1">Ready</h3><p>Workspace draft completed.</p></lumen-typography><lumen-button data-onboarding-edit type="button">Edit draft</lumen-button></section>
|
|
7
|
+
<lumen-stack direction="horizontal" gap="related"><lumen-button data-onboarding-back type="button" hidden variant="secondary">Back</lumen-button><lumen-button data-onboarding-next disabled type="submit">Continue</lumen-button></lumen-stack>
|
|
8
|
+
</lumen-stack></form><p role="status" data-block-status>Step 1 of 3.</p></lumen-stack></lumen-card>
|
|
9
|
+
</section>
|
|
10
|
+
<script type="module">
|
|
11
|
+
import { defineLumenElements } from '@santi020k/lumen-elements'
|
|
12
|
+
import { mountProductBlocks } from './product-blocks.js'
|
|
13
|
+
defineLumenElements()
|
|
14
|
+
const cleanup = mountProductBlocks(document)
|
|
15
|
+
window.addEventListener('pagehide', cleanup, { once: true })
|
|
16
|
+
</script>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<section data-product-block="pricing" aria-label="Example pricing">
|
|
2
|
+
<lumen-typography><h2>A plan for your next project</h2><p>Illustrative prices. Connect selections to your own checkout.</p></lumen-typography>
|
|
3
|
+
<lumen-stack direction="horizontal" gap="related" role="group" aria-label="Billing period"><lumen-button data-billing="monthly" aria-pressed="true">Monthly</lumen-button><lumen-button data-billing="annual" aria-pressed="false">Annual</lumen-button></lumen-stack>
|
|
4
|
+
<lumen-grid columns="auto"><lumen-card><lumen-visual-effect variant="border"><lumen-typography><h3>Starter</h3><p data-monthly="10" data-annual="96">$10 / month</p></lumen-typography><lumen-button data-plan="starter">Choose starter</lumen-button></lumen-visual-effect></lumen-card><lumen-card><lumen-visual-effect variant="mesh"><lumen-typography><h3>Team</h3><p data-monthly="24" data-annual="240">$24 / month</p></lumen-typography><lumen-button data-plan="team">Choose team</lumen-button></lumen-visual-effect></lumen-card></lumen-grid>
|
|
5
|
+
<p role="status" data-block-status>Select a plan to compare billing.</p>
|
|
6
|
+
</section>
|
|
7
|
+
<script type="module">
|
|
8
|
+
import { defineLumenElements } from '@santi020k/lumen-elements'
|
|
9
|
+
import { mountProductBlocks } from './product-blocks.js'
|
|
10
|
+
defineLumenElements()
|
|
11
|
+
const cleanup = mountProductBlocks(document)
|
|
12
|
+
window.addEventListener('pagehide', cleanup, { once: true })
|
|
13
|
+
</script>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<!-- Load @santi020k/lumen-elements/styles.css, register its elements, and import media-workspace.css once. -->
|
|
2
|
+
<section class="lumen-media-workspace" data-media-workspace data-lumen-preset="studio" aria-label="Photo workspace">
|
|
3
|
+
<h2>Photo workspace</h2>
|
|
4
|
+
<div class="lumen-media-workspace__layout">
|
|
5
|
+
<div class="lumen-media-workspace__preview" role="group" aria-label="Image preview">
|
|
6
|
+
<lumen-image-comparison label="Compare the treatment" before-label="Original" after-label="Adjusted" mode="reveal" ratio="1.6">
|
|
7
|
+
<img slot="before" src="/original.jpg" alt="Original photo" width="960" height="600">
|
|
8
|
+
<img slot="after" src="/adjusted.jpg" alt="Adjusted photo" width="960" height="600">
|
|
9
|
+
</lumen-image-comparison>
|
|
10
|
+
<lumen-media-viewport label="Inspect the photo" ratio="1.6" hidden>
|
|
11
|
+
<img src="/adjusted.jpg" alt="Adjusted photo" width="960" height="600">
|
|
12
|
+
</lumen-media-viewport>
|
|
13
|
+
</div>
|
|
14
|
+
<lumen-card class="lumen-media-workspace__inspector" aria-label="Image adjustments">
|
|
15
|
+
<lumen-field data-media-adjustment="exposure" data-default-value="0">
|
|
16
|
+
<lumen-label for="media-exposure">Exposure</lumen-label>
|
|
17
|
+
<output id="media-exposure-output" for="media-exposure">0 EV</output>
|
|
18
|
+
<lumen-badge data-adjustment-modified hidden>Modified</lumen-badge>
|
|
19
|
+
<lumen-slider id="media-exposure" aria-label="Exposure" aria-describedby="media-exposure-output" aria-valuetext="0 EV" min="-1" max="1" step="0.1" value="0"></lumen-slider>
|
|
20
|
+
<lumen-button variant="ghost" data-adjustment-reset disabled>Reset exposure</lumen-button>
|
|
21
|
+
</lumen-field>
|
|
22
|
+
</lumen-card>
|
|
23
|
+
</div>
|
|
24
|
+
<lumen-card glass="subtle" class="lumen-media-workspace__tools">
|
|
25
|
+
<lumen-toolbar aria-label="Preview tools">
|
|
26
|
+
<lumen-button variant="outline" data-comparison-mode="reveal" aria-pressed="true">Reveal</lumen-button>
|
|
27
|
+
<lumen-button variant="outline" data-comparison-mode="side-by-side" aria-pressed="false">Side by side</lumen-button>
|
|
28
|
+
<lumen-button variant="outline" data-comparison-mode="before" aria-pressed="false">Original</lumen-button>
|
|
29
|
+
<lumen-button variant="outline" data-comparison-mode="after" aria-pressed="false">Adjusted</lumen-button>
|
|
30
|
+
<lumen-button variant="outline" data-inspect aria-pressed="false">Inspect details</lumen-button>
|
|
31
|
+
</lumen-toolbar>
|
|
32
|
+
</lumen-card>
|
|
33
|
+
<lumen-media-filmstrip label="Photo collection" selection-label="1 photo selected">
|
|
34
|
+
<li data-media-item="photo-1">
|
|
35
|
+
<lumen-media-thumbnail label="Landscape" media-id="photo-1" selected order="1"><img src="/adjusted.jpg" alt="" width="960" height="600"></lumen-media-thumbnail>
|
|
36
|
+
<lumen-button variant="outline" data-media-move="earlier" data-media-id="photo-1" disabled>Move earlier</lumen-button>
|
|
37
|
+
<lumen-button variant="outline" data-media-move="later" data-media-id="photo-1">Move later</lumen-button>
|
|
38
|
+
</li>
|
|
39
|
+
<li data-media-item="photo-2">
|
|
40
|
+
<lumen-media-thumbnail label="Original landscape" media-id="photo-2" order="2"><img src="/original.jpg" alt="" width="960" height="600"></lumen-media-thumbnail>
|
|
41
|
+
<lumen-button variant="outline" data-media-move="earlier" data-media-id="photo-2">Move earlier</lumen-button>
|
|
42
|
+
<lumen-button variant="outline" data-media-move="later" data-media-id="photo-2" disabled>Move later</lumen-button>
|
|
43
|
+
</li>
|
|
44
|
+
</lumen-media-filmstrip>
|
|
45
|
+
<lumen-card class="lumen-media-workspace__bottom" data-media-processing>
|
|
46
|
+
<p role="status" data-processing-message>Ready to prepare a preview.</p>
|
|
47
|
+
<lumen-progress data-processing-progress aria-label="Preview progress" hidden></lumen-progress>
|
|
48
|
+
<lumen-error-state data-processing-error role="status" aria-live="polite" hidden>
|
|
49
|
+
<h3 data-processing-error-title></h3>
|
|
50
|
+
<p data-processing-recovery></p>
|
|
51
|
+
</lumen-error-state>
|
|
52
|
+
<lumen-button data-media-processing-action="start">Prepare preview</lumen-button>
|
|
53
|
+
<lumen-button data-media-processing-action="cancel" variant="outline" hidden>Cancel preparation</lumen-button>
|
|
54
|
+
<lumen-button data-media-processing-action="retry" hidden>Try again</lumen-button>
|
|
55
|
+
</lumen-card>
|
|
56
|
+
</section>
|
|
57
|
+
<script type="module" src="./media-workspace.js"></script>
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// The application accepts requests and renders canonical state; this bridge owns no services.
|
|
2
|
+
const updatePreview = (workspace: HTMLElement, control: HTMLElement) => {
|
|
3
|
+
const comparison = workspace.querySelector<HTMLElement>('lumen-image-comparison')
|
|
4
|
+
const viewport = workspace.querySelector<HTMLElement>('lumen-media-viewport')
|
|
5
|
+
|
|
6
|
+
if (!comparison || !viewport) return
|
|
7
|
+
|
|
8
|
+
const inspect = control.hasAttribute('data-inspect')
|
|
9
|
+
|
|
10
|
+
comparison.hidden = inspect
|
|
11
|
+
|
|
12
|
+
viewport.hidden = !inspect
|
|
13
|
+
|
|
14
|
+
const mode = control.dataset.comparisonMode
|
|
15
|
+
|
|
16
|
+
if (mode) comparison.setAttribute('mode', mode)
|
|
17
|
+
|
|
18
|
+
for (const button of workspace.querySelectorAll<HTMLElement>('[data-comparison-mode], [data-inspect]')) {
|
|
19
|
+
button.setAttribute('aria-pressed', String(button === control))
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const updateAdjustment = (field: HTMLElement, slider: HTMLInputElement, announce: boolean) => {
|
|
24
|
+
const output = field.querySelector('output')
|
|
25
|
+
const badge = field.querySelector<HTMLElement>('[data-adjustment-modified]')
|
|
26
|
+
const reset = field.querySelector<HTMLElement>('[data-adjustment-reset]')
|
|
27
|
+
|
|
28
|
+
if (!output || !badge || !reset) return
|
|
29
|
+
|
|
30
|
+
const value = slider.valueAsNumber
|
|
31
|
+
|
|
32
|
+
if (!Number.isFinite(value)) return
|
|
33
|
+
|
|
34
|
+
output.textContent = `${value} ${field.dataset.unit ?? 'EV'}`
|
|
35
|
+
|
|
36
|
+
slider.ariaValueText = output.textContent
|
|
37
|
+
|
|
38
|
+
badge.hidden = value === Number(field.dataset.defaultValue)
|
|
39
|
+
|
|
40
|
+
reset.toggleAttribute('disabled', slider.disabled || badge.hidden)
|
|
41
|
+
|
|
42
|
+
if (announce) field.dispatchEvent(new CustomEvent('ui:adjustment-change', {
|
|
43
|
+
bubbles: true, detail: { id: field.dataset.mediaAdjustment, value }
|
|
44
|
+
}))
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
for (const workspace of document.querySelectorAll<HTMLElement>('[data-media-workspace]')) {
|
|
48
|
+
workspace.addEventListener('click', event => {
|
|
49
|
+
if (!(event.target instanceof Element)) return
|
|
50
|
+
|
|
51
|
+
const control = event.target.closest<HTMLElement>('lumen-button')
|
|
52
|
+
|
|
53
|
+
if (!control || control.hasAttribute('disabled') || !workspace.contains(control)) return
|
|
54
|
+
|
|
55
|
+
if (control.dataset.comparisonMode || control.hasAttribute('data-inspect')) updatePreview(workspace, control)
|
|
56
|
+
|
|
57
|
+
const direction = control.dataset.mediaMove
|
|
58
|
+
|
|
59
|
+
if (direction) workspace.dispatchEvent(new CustomEvent('ui:media-move-request', {
|
|
60
|
+
bubbles: true, detail: { id: control.dataset.mediaId, direction }
|
|
61
|
+
}))
|
|
62
|
+
|
|
63
|
+
const action = control.dataset.mediaProcessingAction
|
|
64
|
+
|
|
65
|
+
if (action) workspace.dispatchEvent(new CustomEvent('ui:media-processing-request', {
|
|
66
|
+
bubbles: true, detail: { action }
|
|
67
|
+
}))
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
for (const field of workspace.querySelectorAll<HTMLElement>('[data-media-adjustment]')) {
|
|
71
|
+
const reset = field.querySelector<HTMLElement>('[data-adjustment-reset]')
|
|
72
|
+
|
|
73
|
+
field.addEventListener('input', event => {
|
|
74
|
+
if (event.target instanceof HTMLInputElement && !event.target.disabled) {
|
|
75
|
+
updateAdjustment(field, event.target, true)
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
reset?.addEventListener('click', () => {
|
|
80
|
+
const slider = field.querySelector<HTMLInputElement>('input[type="range"]')
|
|
81
|
+
|
|
82
|
+
if (!slider || slider.disabled || reset.hasAttribute('disabled')) return
|
|
83
|
+
|
|
84
|
+
slider.value = field.dataset.defaultValue ?? '0'
|
|
85
|
+
|
|
86
|
+
updateAdjustment(field, slider, true)
|
|
87
|
+
|
|
88
|
+
slider.focus()
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Keep selection canonical and preserve focus by stable media ID after moves. Render job messages
|
|
93
|
+
// through textContent. Keep cancellation pending until acknowledged and ignore stale completions.
|
|
94
|
+
|
|
95
|
+
export type MediaProcessingState =
|
|
96
|
+
| { phase: 'idle' | 'cancelled' | 'success', message: string } |
|
|
97
|
+
{ phase: 'pending', message: string, progress: number | null } |
|
|
98
|
+
{ phase: 'error', message: string, recovery: string }
|
|
99
|
+
|
|
100
|
+
const renderProcessingError = (panel: HTMLElement, state: MediaProcessingState): void => {
|
|
101
|
+
const error = panel.querySelector<HTMLElement>('[data-processing-error]')
|
|
102
|
+
|
|
103
|
+
if (!error) return
|
|
104
|
+
|
|
105
|
+
error.hidden = state.phase !== 'error'
|
|
106
|
+
|
|
107
|
+
const title = error.querySelector('[data-processing-error-title]')
|
|
108
|
+
const recovery = error.querySelector('[data-processing-recovery]')
|
|
109
|
+
|
|
110
|
+
if (title) title.textContent = state.phase === 'error' ? state.message : ''
|
|
111
|
+
|
|
112
|
+
if (recovery) recovery.textContent = state.phase === 'error' ? state.recovery : ''
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const renderProcessingProgress = (panel: HTMLElement, state: MediaProcessingState): void => {
|
|
116
|
+
const progress = panel.querySelector<HTMLElement>('[data-processing-progress]')
|
|
117
|
+
|
|
118
|
+
if (!progress) return
|
|
119
|
+
|
|
120
|
+
const value = state.phase === 'pending' ? state.progress : null
|
|
121
|
+
const known = value !== null && Number.isFinite(value)
|
|
122
|
+
|
|
123
|
+
progress.hidden = !known
|
|
124
|
+
|
|
125
|
+
if (known) progress.setAttribute('value', String(Math.min(100, Math.max(0, value))))
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const processingActionVisible = (action: string | undefined, phase: MediaProcessingState['phase']): boolean => {
|
|
129
|
+
if (action === 'cancel') return phase === 'pending'
|
|
130
|
+
|
|
131
|
+
if (action === 'retry') return phase === 'error'
|
|
132
|
+
|
|
133
|
+
return action === 'start' && phase !== 'pending' && phase !== 'error'
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Call after a host transition. The bridge neither starts jobs nor acknowledges cancellation. */
|
|
137
|
+
export const renderMediaProcessing = (workspace: HTMLElement, state: MediaProcessingState): void => {
|
|
138
|
+
const panel = workspace.querySelector<HTMLElement>('[data-media-processing]')
|
|
139
|
+
|
|
140
|
+
if (!panel) return
|
|
141
|
+
|
|
142
|
+
panel.dataset.phase = state.phase
|
|
143
|
+
|
|
144
|
+
const message = panel.querySelector<HTMLElement>('[data-processing-message]')
|
|
145
|
+
|
|
146
|
+
if (message) {
|
|
147
|
+
message.textContent = state.message
|
|
148
|
+
|
|
149
|
+
message.hidden = state.phase === 'error'
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
renderProcessingError(panel, state)
|
|
153
|
+
|
|
154
|
+
renderProcessingProgress(panel, state)
|
|
155
|
+
|
|
156
|
+
for (const button of panel.querySelectorAll<HTMLElement>('[data-media-processing-action]')) {
|
|
157
|
+
const visible = processingActionVisible(button.dataset.mediaProcessingAction, state.phase)
|
|
158
|
+
|
|
159
|
+
button.hidden = !visible
|
|
160
|
+
|
|
161
|
+
button.toggleAttribute('disabled', !visible)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script type="module">
|
|
2
|
+
import { defineLumenElements } from '@santi020k/lumen-elements/define'
|
|
3
|
+
defineLumenElements(['Badge', 'Breadcrumb', 'Button', 'Link', 'Stack', 'Typography'])
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<header aria-labelledby="page-heading">
|
|
7
|
+
<lumen-stack gap="group">
|
|
8
|
+
<lumen-breadcrumb><nav aria-label="Breadcrumb"><ol><li><lumen-link><a href="/">Workspace</a></lumen-link></li><li aria-current="page">Portfolio operations</li></ol></nav></lumen-breadcrumb>
|
|
9
|
+
<lumen-stack direction="horizontal" align="start" justify="between" gap="group" wrap>
|
|
10
|
+
<lumen-stack gap="related" style="flex: 1 1 20rem; min-width: 0; overflow-wrap: anywhere">
|
|
11
|
+
<lumen-typography><h1 id="page-heading">Portfolio operations</h1><p>Review activity and keep your workspace up to date.</p></lumen-typography>
|
|
12
|
+
<lumen-badge variant="outline" style="align-self: flex-start">Active</lumen-badge>
|
|
13
|
+
</lumen-stack>
|
|
14
|
+
<lumen-stack direction="horizontal" align="center" gap="related" wrap role="group" aria-label="Page actions">
|
|
15
|
+
<lumen-button type="button">Export report</lumen-button>
|
|
16
|
+
<lumen-button type="button">Create record</lumen-button>
|
|
17
|
+
</lumen-stack>
|
|
18
|
+
</lumen-stack>
|
|
19
|
+
</lumen-stack>
|
|
20
|
+
</header>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<link rel="stylesheet" href="./lumen-template.css" />
|
|
2
|
+
|
|
3
|
+
<script type="module">
|
|
4
|
+
import { defineLumenElements } from '@santi020k/lumen-elements/define'
|
|
5
|
+
|
|
6
|
+
defineLumenElements()
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<div class="lumen-template lumen-template__shell">
|
|
10
|
+
<lumen-sidebar class="lumen-template__sidebar"><strong>Relay Projects</strong><nav aria-label="Projects"><a aria-current="page" href="#overview">Overview</a><a href="#projects">Projects</a><a href="#activity">Activity</a></nav></lumen-sidebar>
|
|
11
|
+
<main class="lumen-template__main" id="overview">
|
|
12
|
+
<header class="lumen-template__header"><div><lumen-badge variant="outline">Team delivery</lumen-badge><h1>Team workspace</h1><p>Priorities, delivery health, and next decisions.</p></div><lumen-button>New project</lumen-button></header>
|
|
13
|
+
<section class="lumen-template__metrics" aria-label="Delivery metrics"><lumen-card class="lumen-template__metric"><lumen-stat label="Open tasks" value="42"></lumen-stat><lumen-badge variant="warning">6 due soon</lumen-badge></lumen-card><lumen-card class="lumen-template__metric"><lumen-stat label="Milestones reached" value="18"></lumen-stat><lumen-badge variant="success">+4</lumen-badge></lumen-card><lumen-card class="lumen-template__metric"><lumen-stat label="At-risk projects" value="2"></lumen-stat><lumen-badge variant="destructive">Needs help</lumen-badge></lumen-card><lumen-card class="lumen-template__metric"><lumen-stat label="Delivery velocity" value="46 pts"></lumen-stat><lumen-badge variant="success">+6.4%</lumen-badge></lumen-card></section>
|
|
14
|
+
<section class="lumen-template__grid"><lumen-card class="lumen-template__panel"><h2>Active workstreams</h2><p>Mobile checkout · 72%</p><lumen-progress aria-label="Mobile checkout is 72% complete" value="72"></lumen-progress><p>Billing migration · 54%</p><lumen-progress aria-label="Billing migration is 54% complete" value="54"></lumen-progress></lumen-card><lumen-card class="lumen-template__panel" id="activity"><h2>Recent activity</h2><lumen-timeline><lumen-timeline-item>Amina completed checkout validation</lumen-timeline-item><lumen-timeline-item>Jon reviewed billing retries</lumen-timeline-item><lumen-timeline-item>Nora moved tokens to review</lumen-timeline-item></lumen-timeline></lumen-card></section>
|
|
15
|
+
<lumen-card class="lumen-template__panel" id="projects"><div class="lumen-template__section-header"><h2>Priority projects</h2><lumen-button variant="ghost">View all</lumen-button></div><lumen-table class="lumen-template__table"><table><thead><tr><th>Project</th><th>Owner</th><th>Status</th><th>Progress</th></tr></thead><tbody><tr><td>Mobile checkout</td><td>Amina</td><td><lumen-badge variant="success">Active</lumen-badge></td><td>72%</td></tr><tr><td>Billing migration</td><td>Jon</td><td><lumen-badge variant="destructive">At risk</lumen-badge></td><td>54%</td></tr></tbody></table></lumen-table></lumen-card>
|
|
16
|
+
</main>
|
|
17
|
+
</div>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<script type="module">
|
|
2
|
+
import { defineLumenElements } from '@santi020k/lumen-elements/define'
|
|
3
|
+
|
|
4
|
+
defineLumenElements()
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<lumen-rich-text-editor class="lumen-recipe lumen-recipe--rich-text-editor">
|
|
8
|
+
<div role="toolbar" aria-label="Editor toolbar">
|
|
9
|
+
<lumen-button-group>
|
|
10
|
+
<lumen-button data-ui-editor-command="bold" type="button">Bold</lumen-button>
|
|
11
|
+
<lumen-button data-ui-editor-command="italic" type="button">Italic</lumen-button>
|
|
12
|
+
</lumen-button-group>
|
|
13
|
+
<lumen-toggle-group><button data-ui-editor-command="insertUnorderedList" type="button">List</button></lumen-toggle-group>
|
|
14
|
+
</div>
|
|
15
|
+
<div contenteditable="true">Draft release notes...</div>
|
|
16
|
+
<lumen-textarea name="fallback" placeholder="Plain text fallback"></lumen-textarea>
|
|
17
|
+
</lumen-rich-text-editor>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<link rel="stylesheet" href="./lumen-template.css" />
|
|
2
|
+
|
|
3
|
+
<script type="module">
|
|
4
|
+
import { defineLumenElements } from '@santi020k/lumen-elements/define'
|
|
5
|
+
|
|
6
|
+
defineLumenElements()
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<div class="lumen-template lumen-template__shell">
|
|
10
|
+
<lumen-sidebar class="lumen-template__sidebar"><strong>Orbit Admin</strong><nav aria-label="Administration"><a aria-current="page" href="#overview">Overview</a><a href="#members">Members</a><a href="#billing">Billing</a></nav></lumen-sidebar>
|
|
11
|
+
<main class="lumen-template__main" id="overview">
|
|
12
|
+
<header class="lumen-template__header"><div><lumen-badge variant="outline">Workspace administration</lumen-badge><h1>Good morning, Maya</h1><p>Access, billing, and operational health.</p></div><lumen-button>Invite members</lumen-button></header>
|
|
13
|
+
<lumen-alert><strong>Quarterly access review is ready.</strong> Confirm eight elevated roles before July 12.</lumen-alert>
|
|
14
|
+
<section class="lumen-template__metrics" aria-label="Workspace metrics"><lumen-card class="lumen-template__metric"><lumen-stat label="Workspace members" value="248"></lumen-stat><lumen-badge variant="success">+24</lumen-badge></lumen-card><lumen-card class="lumen-template__metric"><lumen-stat label="Seat activation" value="91%"></lumen-stat><lumen-badge variant="success">Healthy</lumen-badge></lumen-card><lumen-card class="lumen-template__metric"><lumen-stat label="Access reviews" value="8"></lumen-stat><lumen-badge variant="warning">3 pending</lumen-badge></lumen-card><lumen-card class="lumen-template__metric"><lumen-stat label="Availability" value="99.99%"></lumen-stat><lumen-badge variant="success">Normal</lumen-badge></lumen-card></section>
|
|
15
|
+
<section class="lumen-template__grid" id="billing"><lumen-card class="lumen-template__panel"><h2>Plan utilization</h2><lumen-stat label="Seats used" value="248 / 300"></lumen-stat><lumen-progress aria-label="248 of 300 seats used" max="300" value="248"></lumen-progress></lumen-card><lumen-card class="lumen-template__panel"><h2>Security posture</h2><ul class="lumen-template__list"><li>Single sign-on enforced</li><li>Domain verification complete</li><li>3 recovery codes need rotation</li></ul></lumen-card></section>
|
|
16
|
+
<lumen-card class="lumen-template__panel" id="members"><div class="lumen-template__section-header"><h2>Recently active members</h2><lumen-search-field aria-label="Search members" placeholder="Search members"></lumen-search-field></div><lumen-table class="lumen-template__table"><table><thead><tr><th>Member</th><th>Team</th><th>Status</th><th>Role</th></tr></thead><tbody><tr><td>Amina Bello</td><td>Design</td><td><lumen-badge variant="success">Active</lumen-badge></td><td>Admin</td></tr><tr><td>Theo Martin</td><td>Success</td><td><lumen-badge variant="warning">Pending</lumen-badge></td><td>Member</td></tr></tbody></table></lumen-table></lumen-card>
|
|
17
|
+
</main>
|
|
18
|
+
</div>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<script type="module">
|
|
2
|
+
import { defineLumenElements } from '@santi020k/lumen-elements/define'
|
|
3
|
+
|
|
4
|
+
defineLumenElements()
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<section class="lumen-recipe lumen-recipe--scheduler">
|
|
8
|
+
<lumen-calendar aria-label="Choose schedule date"></lumen-calendar>
|
|
9
|
+
<lumen-date-picker aria-label="Jump to date"></lumen-date-picker>
|
|
10
|
+
<lumen-schedule>
|
|
11
|
+
<header><h2>Launch week</h2></header>
|
|
12
|
+
<div data-ui-schedule-grid>
|
|
13
|
+
<section data-ui-schedule-slot="monday">
|
|
14
|
+
<article id="schedule-planning" data-ui-draggable="true" data-ui-schedule-event>Planning</article>
|
|
15
|
+
</section>
|
|
16
|
+
<section data-ui-schedule-slot="friday">
|
|
17
|
+
<article id="schedule-ship" data-ui-draggable="true" data-ui-schedule-event>Ship</article>
|
|
18
|
+
</section>
|
|
19
|
+
</div>
|
|
20
|
+
</lumen-schedule>
|
|
21
|
+
<lumen-agenda>
|
|
22
|
+
<ol>
|
|
23
|
+
<li><strong>Design review</strong><span>10:00</span></li>
|
|
24
|
+
<li><strong>Release notes</strong><span>14:30</span></li>
|
|
25
|
+
</ol>
|
|
26
|
+
</lumen-agenda>
|
|
27
|
+
</section>
|