@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,21 @@
|
|
|
1
|
+
<script type="module">
|
|
2
|
+
import { defineLumenElements } from '@santi020k/lumen-elements/define'
|
|
3
|
+
defineLumenElements(['Badge', 'Button', 'Stack', 'Typography'])
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<section aria-labelledby="section-heading">
|
|
7
|
+
<header aria-labelledby="section-heading">
|
|
8
|
+
<lumen-stack direction="horizontal" align="start" justify="between" gap="group" wrap>
|
|
9
|
+
<lumen-stack gap="related" style="flex: 1 1 20rem; min-width: 0; overflow-wrap: anywhere">
|
|
10
|
+
<lumen-stack direction="horizontal" align="center" gap="related" wrap>
|
|
11
|
+
<lumen-typography><h2 id="section-heading">Recent activity</h2></lumen-typography>
|
|
12
|
+
<lumen-badge variant="secondary">0 records</lumen-badge>
|
|
13
|
+
</lumen-stack>
|
|
14
|
+
<lumen-typography><p>Changes made during the selected period.</p></lumen-typography>
|
|
15
|
+
</lumen-stack>
|
|
16
|
+
<lumen-stack direction="horizontal" align="center" gap="related" wrap role="group" aria-label="Section actions">
|
|
17
|
+
<lumen-button type="button">View all activity</lumen-button>
|
|
18
|
+
</lumen-stack>
|
|
19
|
+
</lumen-stack>
|
|
20
|
+
</header>
|
|
21
|
+
</section>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<script type="module">
|
|
2
|
+
import { defineLumenElements } from '@santi020k/lumen-elements/define'
|
|
3
|
+
|
|
4
|
+
defineLumenElements()
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<script type="module">
|
|
8
|
+
const root = document.querySelector('[data-lumen-theme-builder-recipe]')
|
|
9
|
+
const hueInput = root?.querySelector('[data-ui-theme-brand-hue]')
|
|
10
|
+
const preview = root?.querySelector('#lumen-theme-preview')
|
|
11
|
+
const output = root?.querySelector('[data-ui-theme-output]')
|
|
12
|
+
const exportButton = root?.querySelector('[data-ui-theme-export]')
|
|
13
|
+
const tokenNames = ['canvas', 'surface', 'surface-muted', 'surface-strong', 'line', 'ink', 'ink-soft', 'ink-muted', 'brand', 'brand-solid', 'brand-soft', 'accent', 'success', 'warning', 'danger']
|
|
14
|
+
const createTheme = hue => ({
|
|
15
|
+
accent: `${(hue + 150) % 360} 70% 40%`,
|
|
16
|
+
brand: `${hue} 85% 53%`,
|
|
17
|
+
'brand-soft': `${hue} 90% 96%`,
|
|
18
|
+
'brand-solid': `${hue} 85% 45%`,
|
|
19
|
+
canvas: `${hue} 20% 99%`,
|
|
20
|
+
danger: '0 84% 60%',
|
|
21
|
+
ink: `${hue} 40% 11%`,
|
|
22
|
+
'ink-muted': `${hue} 10% 48%`,
|
|
23
|
+
'ink-soft': `${hue} 14% 32%`,
|
|
24
|
+
line: `${hue} 14% 86%`,
|
|
25
|
+
success: '142 71% 36%',
|
|
26
|
+
surface: `${hue} 20% 100%`,
|
|
27
|
+
'surface-muted': `${hue} 16% 96%`,
|
|
28
|
+
'surface-strong': `${hue} 14% 91%`,
|
|
29
|
+
warning: '38 92% 50%'
|
|
30
|
+
})
|
|
31
|
+
const update = () => {
|
|
32
|
+
const hue = Number(hueInput?.value ?? 264)
|
|
33
|
+
const tokens = createTheme(Number.isFinite(hue) ? hue : 264)
|
|
34
|
+
|
|
35
|
+
for (const [token, value] of Object.entries(tokens)) {
|
|
36
|
+
preview?.style.setProperty(`--${token}`, value)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (output) {
|
|
40
|
+
output.value = `:root {\n${tokenNames.map(token => ` --${token}: ${tokens[token]};`).join('\n')}\n}`
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
hueInput?.addEventListener('input', update)
|
|
45
|
+
exportButton?.addEventListener('click', () => navigator.clipboard?.writeText(output?.value ?? ''))
|
|
46
|
+
update()
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<lumen-theme-builder class="lumen-recipe lumen-recipe--theme-builder" data-lumen-theme-builder-recipe>
|
|
50
|
+
<header><h2>Brand theme</h2><lumen-button data-ui-theme-export type="button">Copy CSS</lumen-button></header>
|
|
51
|
+
<lumen-card id="lumen-theme-preview" style="display: flex; gap: 0.5rem;">
|
|
52
|
+
<span data-ui-swatch style="--ui-swatch:hsl(var(--brand))"></span>
|
|
53
|
+
<span data-ui-swatch style="--ui-swatch:hsl(var(--accent))"></span>
|
|
54
|
+
</lumen-card>
|
|
55
|
+
<lumen-card>
|
|
56
|
+
<input class="ui-input" aria-label="Brand hue" data-ui-theme-brand-hue max="359" min="0" type="range" value="264" />
|
|
57
|
+
</lumen-card>
|
|
58
|
+
<textarea data-ui-theme-output aria-label="Theme CSS"></textarea>
|
|
59
|
+
</lumen-theme-builder>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Autocomplete,
|
|
3
|
+
ColorPicker,
|
|
4
|
+
DatePicker,
|
|
5
|
+
DateRangePicker,
|
|
6
|
+
NumberField,
|
|
7
|
+
SearchField,
|
|
8
|
+
TagGroup,
|
|
9
|
+
TimeField
|
|
10
|
+
} from '@santi020k/lumen-react'
|
|
11
|
+
|
|
12
|
+
export const AdvancedFieldsRecipe = () => (
|
|
13
|
+
<form className="lumen-recipe lumen-recipe--advanced-fields">
|
|
14
|
+
<SearchField name="q" placeholder="Search records" />
|
|
15
|
+
<Autocomplete list="assignees" placeholder="Assign to..." />
|
|
16
|
+
<datalist id="assignees">
|
|
17
|
+
<option value="Design" />
|
|
18
|
+
<option value="Engineering" />
|
|
19
|
+
<option value="Operations" />
|
|
20
|
+
</datalist>
|
|
21
|
+
<NumberField aria-label="Seats" min="1" defaultValue="3" />
|
|
22
|
+
<TimeField aria-label="Start time" defaultValue="09:30" />
|
|
23
|
+
<DateRangePicker>
|
|
24
|
+
<DatePicker aria-label="Start date" />
|
|
25
|
+
<DatePicker aria-label="End date" />
|
|
26
|
+
</DateRangePicker>
|
|
27
|
+
<ColorPicker aria-label="Brand color" defaultValue="#2563eb" />
|
|
28
|
+
<TagGroup aria-label="Selected filters">
|
|
29
|
+
<span data-ui-tag role="listitem">
|
|
30
|
+
Active
|
|
31
|
+
<button data-ui-tag-remove type="button">
|
|
32
|
+
Remove
|
|
33
|
+
</button>
|
|
34
|
+
</span>
|
|
35
|
+
</TagGroup>
|
|
36
|
+
</form>
|
|
37
|
+
)
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import './lumen-template.css'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Badge,
|
|
5
|
+
BarChart,
|
|
6
|
+
Button,
|
|
7
|
+
Card,
|
|
8
|
+
LineChart,
|
|
9
|
+
Sidebar,
|
|
10
|
+
Sparkline,
|
|
11
|
+
Stat,
|
|
12
|
+
Table
|
|
13
|
+
} from '@santi020k/lumen-react'
|
|
14
|
+
|
|
15
|
+
const revenue = [
|
|
16
|
+
{
|
|
17
|
+
data: [
|
|
18
|
+
{ x: 'Jan', y: 118 },
|
|
19
|
+
{ x: 'Feb', y: 126 },
|
|
20
|
+
{ x: 'Mar', y: 132 },
|
|
21
|
+
{ x: 'Apr', y: 148 },
|
|
22
|
+
{ x: 'May', y: 162 },
|
|
23
|
+
{ x: 'Jun', y: 184 }
|
|
24
|
+
],
|
|
25
|
+
id: 'revenue',
|
|
26
|
+
label: 'Revenue',
|
|
27
|
+
tone: 'brand' as const
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
const channels = [
|
|
32
|
+
{
|
|
33
|
+
data: [
|
|
34
|
+
{ x: 'Organic', y: 4820 },
|
|
35
|
+
{ x: 'Referral', y: 3180 },
|
|
36
|
+
{ x: 'Paid', y: 2640 }
|
|
37
|
+
],
|
|
38
|
+
id: 'visitors',
|
|
39
|
+
label: 'Visitors',
|
|
40
|
+
tone: 'brand' as const
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
const metrics = [
|
|
45
|
+
{
|
|
46
|
+
change: '+12.4%',
|
|
47
|
+
label: 'Monthly revenue',
|
|
48
|
+
values: [31, 33, 38, 41, 46, 52],
|
|
49
|
+
value: '$184,320'
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
change: '+8.2%',
|
|
53
|
+
label: 'Active accounts',
|
|
54
|
+
values: [40, 42, 45, 49, 53, 57],
|
|
55
|
+
value: '12,480'
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
change: '-1.6%',
|
|
59
|
+
label: 'Customer churn',
|
|
60
|
+
values: [26, 25, 24, 23, 20, 18],
|
|
61
|
+
value: '2.8%'
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
change: '+3.1%',
|
|
65
|
+
label: 'Net retention',
|
|
66
|
+
values: [44, 45, 47, 49, 50, 54],
|
|
67
|
+
value: '116%'
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
export const AnalyticsDashboardTemplate = () => (
|
|
72
|
+
<div className="lumen-template lumen-template__shell">
|
|
73
|
+
<Sidebar className="lumen-template__sidebar">
|
|
74
|
+
<strong>Pulse Analytics</strong>
|
|
75
|
+
<nav aria-label="Analytics">
|
|
76
|
+
<a aria-current="page" href="#overview">
|
|
77
|
+
Overview
|
|
78
|
+
</a>
|
|
79
|
+
<a href="#acquisition">Acquisition</a>
|
|
80
|
+
<a href="#accounts">Accounts</a>
|
|
81
|
+
</nav>
|
|
82
|
+
</Sidebar>
|
|
83
|
+
<main className="lumen-template__main" id="overview">
|
|
84
|
+
<header className="lumen-template__header">
|
|
85
|
+
<div>
|
|
86
|
+
<Badge variant="outline">Jun 1–30</Badge>
|
|
87
|
+
<h1>Growth overview</h1>
|
|
88
|
+
<p>Revenue, retention, and account health.</p>
|
|
89
|
+
</div>
|
|
90
|
+
<Button>Export report</Button>
|
|
91
|
+
</header>
|
|
92
|
+
<section className="lumen-template__metrics" aria-label="Key metrics">
|
|
93
|
+
{metrics.map(metric => (
|
|
94
|
+
<Card className="lumen-template__metric" key={metric.label}>
|
|
95
|
+
<Stat label={metric.label} value={metric.value} />
|
|
96
|
+
<Badge variant="success">{metric.change}</Badge>
|
|
97
|
+
<Sparkline label={`${metric.label} trend`} values={metric.values} />
|
|
98
|
+
</Card>
|
|
99
|
+
))}
|
|
100
|
+
</section>
|
|
101
|
+
<section className="lumen-template__grid" id="acquisition">
|
|
102
|
+
<LineChart area heading="Revenue trajectory" series={revenue} />
|
|
103
|
+
<BarChart heading="Channel performance" series={channels} />
|
|
104
|
+
</section>
|
|
105
|
+
<Card className="lumen-template__panel" id="accounts">
|
|
106
|
+
<div className="lumen-template__section-header">
|
|
107
|
+
<h2>Accounts to watch</h2>
|
|
108
|
+
<Button variant="ghost">View all</Button>
|
|
109
|
+
</div>
|
|
110
|
+
<Table className="lumen-template__table">
|
|
111
|
+
<table>
|
|
112
|
+
<thead>
|
|
113
|
+
<tr>
|
|
114
|
+
<th>Account</th>
|
|
115
|
+
<th>Plan</th>
|
|
116
|
+
<th>Status</th>
|
|
117
|
+
<th>Value</th>
|
|
118
|
+
</tr>
|
|
119
|
+
</thead>
|
|
120
|
+
<tbody>
|
|
121
|
+
<tr>
|
|
122
|
+
<td>Northstar Labs</td>
|
|
123
|
+
<td>Enterprise</td>
|
|
124
|
+
<td>
|
|
125
|
+
<Badge variant="success">Active</Badge>
|
|
126
|
+
</td>
|
|
127
|
+
<td>$18,400</td>
|
|
128
|
+
</tr>
|
|
129
|
+
<tr>
|
|
130
|
+
<td>Arc & Field</td>
|
|
131
|
+
<td>Enterprise</td>
|
|
132
|
+
<td>
|
|
133
|
+
<Badge variant="destructive">At risk</Badge>
|
|
134
|
+
</td>
|
|
135
|
+
<td>$14,780</td>
|
|
136
|
+
</tr>
|
|
137
|
+
</tbody>
|
|
138
|
+
</table>
|
|
139
|
+
</Table>
|
|
140
|
+
</Card>
|
|
141
|
+
</main>
|
|
142
|
+
</div>
|
|
143
|
+
)
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import './lumen-template.css'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Alert,
|
|
5
|
+
Button,
|
|
6
|
+
Card,
|
|
7
|
+
Checkbox,
|
|
8
|
+
Field,
|
|
9
|
+
Grid,
|
|
10
|
+
Input,
|
|
11
|
+
Label,
|
|
12
|
+
Progress,
|
|
13
|
+
Stepper
|
|
14
|
+
} from '@santi020k/lumen-react'
|
|
15
|
+
|
|
16
|
+
export const AuthOnboardingTemplate = () => (
|
|
17
|
+
<main className="lumen-template lumen-template__form-shell">
|
|
18
|
+
<Card className="lumen-template__form">
|
|
19
|
+
<Stepper
|
|
20
|
+
currentStep={1}
|
|
21
|
+
steps={['Account', 'Workspace', 'Preferences', 'Invite']}
|
|
22
|
+
/>
|
|
23
|
+
<header>
|
|
24
|
+
<p className="lumen-template__muted">Step 2 of 4</p>
|
|
25
|
+
<h1>Create your workspace</h1>
|
|
26
|
+
<p className="lumen-template__muted">
|
|
27
|
+
We’ll prepare the right starting point.
|
|
28
|
+
</p>
|
|
29
|
+
</header>
|
|
30
|
+
<form className="lumen-template__form">
|
|
31
|
+
<Field className="lumen-template__field">
|
|
32
|
+
<Label htmlFor="workspace-name">Workspace name</Label>
|
|
33
|
+
<Input
|
|
34
|
+
id="workspace-name"
|
|
35
|
+
name="workspace"
|
|
36
|
+
placeholder="Northstar Labs"
|
|
37
|
+
required
|
|
38
|
+
/>
|
|
39
|
+
</Field>
|
|
40
|
+
<Field className="lumen-template__field">
|
|
41
|
+
<Label htmlFor="work-email">Work email</Label>
|
|
42
|
+
<Input
|
|
43
|
+
aria-invalid="true"
|
|
44
|
+
id="work-email"
|
|
45
|
+
name="email"
|
|
46
|
+
type="email"
|
|
47
|
+
defaultValue="maya@example"
|
|
48
|
+
required
|
|
49
|
+
/>
|
|
50
|
+
<Alert role="alert" variant="destructive">
|
|
51
|
+
Enter a complete email address.
|
|
52
|
+
</Alert>
|
|
53
|
+
</Field>
|
|
54
|
+
<fieldset className="lumen-template__choices">
|
|
55
|
+
<legend>What are you setting up?</legend>
|
|
56
|
+
<label className="lumen-template__choice">
|
|
57
|
+
<input defaultChecked name="intent" type="radio" value="team" />
|
|
58
|
+
{' '}
|
|
59
|
+
A
|
|
60
|
+
team workspace
|
|
61
|
+
</label>
|
|
62
|
+
<label className="lumen-template__choice">
|
|
63
|
+
<input name="intent" type="radio" value="personal" />
|
|
64
|
+
{' '}
|
|
65
|
+
A personal
|
|
66
|
+
workspace
|
|
67
|
+
</label>
|
|
68
|
+
</fieldset>
|
|
69
|
+
<label>
|
|
70
|
+
<Checkbox defaultChecked name="updates" value="updates" />
|
|
71
|
+
{' '}
|
|
72
|
+
Send
|
|
73
|
+
occasional onboarding tips
|
|
74
|
+
</label>
|
|
75
|
+
<div>
|
|
76
|
+
<div className="lumen-template__section-header">
|
|
77
|
+
<span>Setup progress</span>
|
|
78
|
+
<strong>50%</strong>
|
|
79
|
+
</div>
|
|
80
|
+
<Progress aria-label="Setup is 50% complete" value={50} />
|
|
81
|
+
</div>
|
|
82
|
+
<div className="lumen-template__actions">
|
|
83
|
+
<Button variant="ghost">Back</Button>
|
|
84
|
+
<Button type="submit">Continue</Button>
|
|
85
|
+
</div>
|
|
86
|
+
</form>
|
|
87
|
+
</Card>
|
|
88
|
+
<section className="lumen-login-examples" aria-labelledby="login-examples-title">
|
|
89
|
+
<header>
|
|
90
|
+
<p>Returning members</p>
|
|
91
|
+
<h2 id="login-examples-title">A familiar way back in.</h2>
|
|
92
|
+
<p>Email codes and passkeys, composed with Lumen. These visual examples do not send codes or sign you in.</p>
|
|
93
|
+
</header>
|
|
94
|
+
<Grid className="lumen-login-examples__grid" minItemWidth="18rem">
|
|
95
|
+
<Card className="lumen-login-examples__card">
|
|
96
|
+
<h3>Welcome back</h3>
|
|
97
|
+
<p>Use a saved passkey or receive a code by email.</p>
|
|
98
|
+
<Button disabled type="button">Sign in with a passkey</Button>
|
|
99
|
+
<Field>
|
|
100
|
+
<Label htmlFor="login-email">Email address</Label>
|
|
101
|
+
<Input autoComplete="email" id="login-email" name="login-email" readOnly type="email" value="member@example.com" />
|
|
102
|
+
</Field>
|
|
103
|
+
<Button disabled type="button">Send sign-in code</Button>
|
|
104
|
+
<p>No password to remember.</p>
|
|
105
|
+
</Card>
|
|
106
|
+
<Card className="lumen-login-examples__card">
|
|
107
|
+
<h3>Check your inbox</h3>
|
|
108
|
+
<p>If this address can sign in, a code will arrive shortly.</p>
|
|
109
|
+
<Field>
|
|
110
|
+
<Label htmlFor="login-code">Email code</Label>
|
|
111
|
+
<Input aria-describedby="login-code-hint" autoComplete="one-time-code" id="login-code" inputMode="numeric" name="login-code" placeholder="Enter your code" readOnly />
|
|
112
|
+
<p id="login-code-hint">Paste the complete code from your email.</p>
|
|
113
|
+
</Field>
|
|
114
|
+
<Button disabled type="button">Verify and continue</Button>
|
|
115
|
+
<Button disabled type="button" variant="outline">Resend code</Button>
|
|
116
|
+
<p>Entered the wrong address? Return to email sign-in.</p>
|
|
117
|
+
</Card>
|
|
118
|
+
<Card className="lumen-login-examples__card">
|
|
119
|
+
<h3>Try another way</h3>
|
|
120
|
+
<Alert variant="destructive">Passkey sign-in was canceled. You can try again or request a code by email.</Alert>
|
|
121
|
+
<p>You can still use email when your passkey is unavailable.</p>
|
|
122
|
+
<Button disabled type="button">Try passkey again</Button>
|
|
123
|
+
<Button disabled type="button" variant="outline">Use an email code</Button>
|
|
124
|
+
<p>Your existing account and workspace stay the same.</p>
|
|
125
|
+
</Card>
|
|
126
|
+
</Grid>
|
|
127
|
+
</section>
|
|
128
|
+
</main>
|
|
129
|
+
)
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useRef, useState } from 'react'
|
|
4
|
+
|
|
5
|
+
import { Command, Input, Typography } from '@santi020k/lumen-react'
|
|
6
|
+
|
|
7
|
+
export type WorkspaceCommand = 'search' | 'create' | 'review'
|
|
8
|
+
|
|
9
|
+
const commands: readonly { id: WorkspaceCommand, label: string }[] = [
|
|
10
|
+
{ id: 'search', label: 'Search project documentation' },
|
|
11
|
+
{ id: 'create', label: 'Create a task draft' },
|
|
12
|
+
{ id: 'review', label: 'Review pending proposals' }
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
export const CommandCenterRecipe = ({ onCommand }: { onCommand?: (command: WorkspaceCommand) => void }) => {
|
|
16
|
+
const [selected, setSelected] = useState('')
|
|
17
|
+
const [query, setQuery] = useState('')
|
|
18
|
+
const inputRef = useRef<HTMLInputElement>(null)
|
|
19
|
+
const itemsRef = useRef<(HTMLButtonElement | null)[]>([])
|
|
20
|
+
const matches = commands.filter(command => command.label.toLowerCase().includes(query.trim().toLowerCase()))
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<section aria-label="Workspace commands">
|
|
24
|
+
<Typography>
|
|
25
|
+
<h2>What would you like to do?</h2>
|
|
26
|
+
<p>Search with the keyboard, then choose a command.</p>
|
|
27
|
+
</Typography>
|
|
28
|
+
<Command>
|
|
29
|
+
<Input
|
|
30
|
+
ref={inputRef}
|
|
31
|
+
type="search"
|
|
32
|
+
aria-label="Search workspace commands"
|
|
33
|
+
placeholder="Search commands…"
|
|
34
|
+
value={query}
|
|
35
|
+
onChange={event => {
|
|
36
|
+
setQuery(event.currentTarget.value)
|
|
37
|
+
}}
|
|
38
|
+
onKeyDown={event => {
|
|
39
|
+
if (event.key === 'ArrowDown' && matches.length > 0) {
|
|
40
|
+
event.preventDefault()
|
|
41
|
+
|
|
42
|
+
itemsRef.current[0]?.focus()
|
|
43
|
+
}
|
|
44
|
+
}}
|
|
45
|
+
/>
|
|
46
|
+
{matches.map((command, index) => (
|
|
47
|
+
<button
|
|
48
|
+
key={command.id}
|
|
49
|
+
ref={element => {
|
|
50
|
+
itemsRef.current[index] = element
|
|
51
|
+
}}
|
|
52
|
+
data-ui-command-item
|
|
53
|
+
type="button"
|
|
54
|
+
onKeyDown={event => {
|
|
55
|
+
if (event.key === 'Escape') {
|
|
56
|
+
event.preventDefault()
|
|
57
|
+
|
|
58
|
+
inputRef.current?.focus()
|
|
59
|
+
} else if (['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key)) {
|
|
60
|
+
event.preventDefault()
|
|
61
|
+
|
|
62
|
+
let next = (index + (event.key === 'ArrowDown' ? 1 : -1) + matches.length) % matches.length
|
|
63
|
+
|
|
64
|
+
if (event.key === 'Home') next = 0
|
|
65
|
+
|
|
66
|
+
if (event.key === 'End') next = matches.length - 1
|
|
67
|
+
|
|
68
|
+
itemsRef.current[next]?.focus()
|
|
69
|
+
}
|
|
70
|
+
}}
|
|
71
|
+
onClick={() => {
|
|
72
|
+
setSelected(command.label)
|
|
73
|
+
|
|
74
|
+
onCommand?.(command.id)
|
|
75
|
+
}}
|
|
76
|
+
>
|
|
77
|
+
{command.label}
|
|
78
|
+
</button>
|
|
79
|
+
))}
|
|
80
|
+
{matches.length === 0 && <Typography><p role="status">No matching commands. Try another search.</p></Typography>}
|
|
81
|
+
</Command>
|
|
82
|
+
<p role="status">{selected ? `Selected: ${selected}` : 'Choose a command.'}</p>
|
|
83
|
+
</section>
|
|
84
|
+
)
|
|
85
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import './lumen-template.css'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Badge,
|
|
5
|
+
BarChart,
|
|
6
|
+
Button,
|
|
7
|
+
Card,
|
|
8
|
+
PieChart,
|
|
9
|
+
Progress,
|
|
10
|
+
Sidebar,
|
|
11
|
+
Stat,
|
|
12
|
+
Table
|
|
13
|
+
} from '@santi020k/lumen-react'
|
|
14
|
+
|
|
15
|
+
const sales = [
|
|
16
|
+
{
|
|
17
|
+
data: [
|
|
18
|
+
{ x: 'Mon', y: 11200 },
|
|
19
|
+
{ x: 'Tue', y: 13800 },
|
|
20
|
+
{ x: 'Wed', y: 12600 },
|
|
21
|
+
{ x: 'Thu', y: 15400 },
|
|
22
|
+
{ x: 'Fri', y: 16800 }
|
|
23
|
+
],
|
|
24
|
+
id: 'sales',
|
|
25
|
+
label: 'Sales',
|
|
26
|
+
tone: 'brand' as const
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
const sources = {
|
|
31
|
+
data: [
|
|
32
|
+
{ x: 'Online', y: 812 },
|
|
33
|
+
{ x: 'Marketplace', y: 286 },
|
|
34
|
+
{ x: 'POS', y: 186 }
|
|
35
|
+
],
|
|
36
|
+
id: 'orders',
|
|
37
|
+
label: 'Orders'
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const CommerceDashboardTemplate = () => (
|
|
41
|
+
<div className="lumen-template lumen-template__shell">
|
|
42
|
+
<Sidebar className="lumen-template__sidebar">
|
|
43
|
+
<strong>Mercury Commerce</strong>
|
|
44
|
+
<nav aria-label="Commerce">
|
|
45
|
+
<a aria-current="page" href="#overview">
|
|
46
|
+
Overview
|
|
47
|
+
</a>
|
|
48
|
+
<a href="#orders">Orders</a>
|
|
49
|
+
<a href="#inventory">Inventory</a>
|
|
50
|
+
</nav>
|
|
51
|
+
</Sidebar>
|
|
52
|
+
<main className="lumen-template__main" id="overview">
|
|
53
|
+
<header className="lumen-template__header">
|
|
54
|
+
<div>
|
|
55
|
+
<Badge variant="outline">Store overview</Badge>
|
|
56
|
+
<h1>Commerce command center</h1>
|
|
57
|
+
<p>Sales, fulfillment, and inventory risk.</p>
|
|
58
|
+
</div>
|
|
59
|
+
<Button>Add product</Button>
|
|
60
|
+
</header>
|
|
61
|
+
<section
|
|
62
|
+
className="lumen-template__metrics"
|
|
63
|
+
aria-label="Commerce metrics"
|
|
64
|
+
>
|
|
65
|
+
<Card className="lumen-template__metric">
|
|
66
|
+
<Stat label="Gross sales" value="$92,840" />
|
|
67
|
+
<Badge variant="success">+18.6%</Badge>
|
|
68
|
+
</Card>
|
|
69
|
+
<Card className="lumen-template__metric">
|
|
70
|
+
<Stat label="Orders" value="1,284" />
|
|
71
|
+
<Badge variant="success">+7.4%</Badge>
|
|
72
|
+
</Card>
|
|
73
|
+
<Card className="lumen-template__metric">
|
|
74
|
+
<Stat label="Average order" value="$72.31" />
|
|
75
|
+
<Badge variant="success">+$6.20</Badge>
|
|
76
|
+
</Card>
|
|
77
|
+
<Card className="lumen-template__metric">
|
|
78
|
+
<Stat label="Return rate" value="2.1%" />
|
|
79
|
+
<Badge variant="success">-0.4%</Badge>
|
|
80
|
+
</Card>
|
|
81
|
+
</section>
|
|
82
|
+
<section className="lumen-template__grid">
|
|
83
|
+
<BarChart heading="Sales this week" series={sales} />
|
|
84
|
+
<PieChart
|
|
85
|
+
centerLabel="orders"
|
|
86
|
+
centerValue="1,284"
|
|
87
|
+
heading="Order sources"
|
|
88
|
+
series={sources}
|
|
89
|
+
/>
|
|
90
|
+
</section>
|
|
91
|
+
<section className="lumen-template__grid" id="inventory">
|
|
92
|
+
<Card className="lumen-template__panel">
|
|
93
|
+
<h2>Fulfillment</h2>
|
|
94
|
+
<Stat label="Orders ready" value="42" />
|
|
95
|
+
<Progress
|
|
96
|
+
aria-label="42 of 58 orders fulfilled"
|
|
97
|
+
max={58}
|
|
98
|
+
value={42}
|
|
99
|
+
/>
|
|
100
|
+
</Card>
|
|
101
|
+
<Card className="lumen-template__panel">
|
|
102
|
+
<h2>Inventory signals</h2>
|
|
103
|
+
<ul className="lumen-template__list">
|
|
104
|
+
<li>3 products below safety stock</li>
|
|
105
|
+
<li>8 transfers arriving this week</li>
|
|
106
|
+
<li>94% inventory accuracy</li>
|
|
107
|
+
</ul>
|
|
108
|
+
</Card>
|
|
109
|
+
</section>
|
|
110
|
+
<Card className="lumen-template__panel" id="orders">
|
|
111
|
+
<div className="lumen-template__section-header">
|
|
112
|
+
<h2>Recent orders</h2>
|
|
113
|
+
<Button variant="ghost">View all</Button>
|
|
114
|
+
</div>
|
|
115
|
+
<Table className="lumen-template__table">
|
|
116
|
+
<table>
|
|
117
|
+
<thead>
|
|
118
|
+
<tr>
|
|
119
|
+
<th>Order</th>
|
|
120
|
+
<th>Customer</th>
|
|
121
|
+
<th>Status</th>
|
|
122
|
+
<th>Total</th>
|
|
123
|
+
</tr>
|
|
124
|
+
</thead>
|
|
125
|
+
<tbody>
|
|
126
|
+
<tr>
|
|
127
|
+
<td>#10482</td>
|
|
128
|
+
<td>Nora Singh</td>
|
|
129
|
+
<td>
|
|
130
|
+
<Badge variant="success">Completed</Badge>
|
|
131
|
+
</td>
|
|
132
|
+
<td>$148.00</td>
|
|
133
|
+
</tr>
|
|
134
|
+
<tr>
|
|
135
|
+
<td>#10481</td>
|
|
136
|
+
<td>Theo Martin</td>
|
|
137
|
+
<td>
|
|
138
|
+
<Badge variant="warning">Pending</Badge>
|
|
139
|
+
</td>
|
|
140
|
+
<td>$84.50</td>
|
|
141
|
+
</tr>
|
|
142
|
+
</tbody>
|
|
143
|
+
</table>
|
|
144
|
+
</Table>
|
|
145
|
+
</Card>
|
|
146
|
+
</main>
|
|
147
|
+
</div>
|
|
148
|
+
)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Button, Stack } from '@santi020k/lumen-react'
|
|
2
|
+
|
|
3
|
+
export const ContentFlowActionsRecipe = () => (
|
|
4
|
+
<Stack role="group" aria-label="Changes" gap="related">
|
|
5
|
+
<p role="status">You have unsaved changes.</p>
|
|
6
|
+
<Stack direction="horizontal" gap="related" wrap>
|
|
7
|
+
<Button>Save changes</Button>
|
|
8
|
+
<Button variant="secondary">Discard changes</Button>
|
|
9
|
+
</Stack>
|
|
10
|
+
</Stack>
|
|
11
|
+
)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Button, Stack, Typography } from '@santi020k/lumen-react'
|
|
2
|
+
|
|
3
|
+
export const ContentFlowHeaderRecipe = () => (
|
|
4
|
+
<Stack as="section" gap="group" aria-labelledby="workspace-heading">
|
|
5
|
+
<Typography>
|
|
6
|
+
<h1 id="workspace-heading">Workspace settings</h1>
|
|
7
|
+
<p>Manage your team’s access and notification preferences.</p>
|
|
8
|
+
</Typography>
|
|
9
|
+
<Stack direction="horizontal" gap="related" wrap>
|
|
10
|
+
<Button>Invite a teammate</Button>
|
|
11
|
+
<Button variant="secondary">View activity</Button>
|
|
12
|
+
</Stack>
|
|
13
|
+
</Stack>
|
|
14
|
+
)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Badge, Card, CardContent, CardHeader, CardTitle, Stack } from '@santi020k/lumen-react'
|
|
2
|
+
|
|
3
|
+
export const ContentFlowListRecipe = () => (
|
|
4
|
+
<Card as="section" aria-labelledby="members-heading">
|
|
5
|
+
<CardHeader><CardTitle as="h2" id="members-heading">Team members</CardTitle></CardHeader>
|
|
6
|
+
<CardContent>
|
|
7
|
+
<Stack role="list" gap="group">
|
|
8
|
+
<Stack role="listitem" direction="horizontal" align="center" justify="between" gap="related" wrap>
|
|
9
|
+
<span>Alex Morgan — Workspace owner</span>
|
|
10
|
+
<Badge>Active</Badge>
|
|
11
|
+
</Stack>
|
|
12
|
+
<Stack role="listitem" direction="horizontal" align="center" justify="between" gap="related" wrap>
|
|
13
|
+
<span>Jamie Lee — Design and operations</span>
|
|
14
|
+
<Badge variant="secondary">Invited</Badge>
|
|
15
|
+
</Stack>
|
|
16
|
+
</Stack>
|
|
17
|
+
</CardContent>
|
|
18
|
+
</Card>
|
|
19
|
+
)
|