@santi020k/lumen 0.4.0 → 1.1.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.
@@ -0,0 +1,311 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { readdir, readFile, stat } from 'node:fs/promises';
3
+ import { extname, join, relative, resolve, sep } from 'node:path';
4
+ import { lumenComponentBehavior, lumenGlobalBehaviors, lumenStylingContracts } from '@santi020k/lumen-core';
5
+ const sourceExtensions = new Set(['.astro', '.css', '.js', '.jsx', '.mjs', '.ts', '.tsx']);
6
+ const ignoredDirectories = new Set([
7
+ '.astro',
8
+ '.git',
9
+ '.next',
10
+ '.open-next',
11
+ '.output',
12
+ '.turbo',
13
+ '.vercel',
14
+ '.vite',
15
+ '.wrangler',
16
+ 'build',
17
+ 'coverage',
18
+ 'dist',
19
+ 'node_modules',
20
+ 'out'
21
+ ]);
22
+ const publicRootSlots = new Set(Object.values(lumenStylingContracts).flatMap(contract => [contract.rootSlot, ...contract.parts]));
23
+ const discoverProject = async (root) => {
24
+ const packageRoots = [];
25
+ const sourceFiles = [];
26
+ const visit = async (directory) => {
27
+ for (const entry of await readdir(directory, { withFileTypes: true })) {
28
+ if (ignoredDirectories.has(entry.name))
29
+ continue;
30
+ const path = join(directory, entry.name);
31
+ if (entry.isDirectory()) {
32
+ await visit(path);
33
+ }
34
+ else if (entry.name === 'package.json') {
35
+ packageRoots.push(directory);
36
+ }
37
+ else if (sourceExtensions.has(extname(entry.name))) {
38
+ sourceFiles.push(path);
39
+ }
40
+ }
41
+ };
42
+ await visit(root);
43
+ if (!packageRoots.includes(root))
44
+ packageRoots.push(root);
45
+ return { packageRoots, sourceFiles };
46
+ };
47
+ const importedNames = (source, packageName) => {
48
+ const names = [];
49
+ const pattern = new RegExp(`import\\s*\\{([\\s\\S]*?)\\}\\s*from\\s*['"]${packageName}['"]`, 'g');
50
+ for (const match of source.matchAll(pattern)) {
51
+ for (const entry of (match[1] ?? '').split(',')) {
52
+ const name = entry.trim().split(/\s+as\s+/u)[0];
53
+ if (name)
54
+ names.push(name);
55
+ }
56
+ }
57
+ return names;
58
+ };
59
+ const finding = (file, rule, message, remediation, severity = 'error') => ({ file, message, remediation, rule, severity });
60
+ const packageNamePattern = String.raw `@santi020k\/lumen-(?:astro|elements|react)(?:\/[^'"]*)?`;
61
+ const packageReferencePattern = new RegExp(String.raw `(?:^|\n)\s*(?:export|import)\s+(?:type\s+)?(?:[^'"\n]*?\s+from\s+)?['"]` +
62
+ String.raw `(${packageNamePattern})['"]`, 'g');
63
+ const dynamicPackageReferencePattern = new RegExp(String.raw `import\(\s*['"](${packageNamePattern})['"]\s*\)`, 'g');
64
+ const cssPackageReferencePattern = new RegExp(String.raw `(?:^|\n)\s*@import\s+(?:url\(\s*)?['"](${packageNamePattern})['"]`, 'g');
65
+ const layoutFilePattern = /(?:^|\/)(?:layouts?\/[^/]+|[^/]*layout[^/]*)\.astro$/iu;
66
+ const getPackageReferences = (source) => [
67
+ ...source.matchAll(packageReferencePattern),
68
+ ...source.matchAll(dynamicPackageReferencePattern),
69
+ ...source.matchAll(cssPackageReferencePattern)
70
+ ].flatMap(match => match[1] ? [match[1]] : []);
71
+ const packageFramework = (packageName) => {
72
+ const framework = /^@santi020k\/lumen-(astro|elements|react)(?:\/|$)/u.exec(packageName)?.[1];
73
+ return framework === 'astro' || framework === 'elements' || framework === 'react' ?
74
+ framework :
75
+ undefined;
76
+ };
77
+ const getFrameworks = (sources) => [
78
+ ...new Set(sources.flatMap(item => getPackageReferences(item.source))
79
+ .filter(packageName => !packageName.endsWith('/styles.css') &&
80
+ !packageName.endsWith('/layers.css'))
81
+ .flatMap(packageName => {
82
+ const framework = packageFramework(packageName);
83
+ return framework ? [framework] : [];
84
+ }))
85
+ ];
86
+ const getBoundaryRoot = (file, packageRoots, fallback) => packageRoots
87
+ .filter(packageRoot => file === packageRoot || file.startsWith(`${packageRoot}${sep}`))
88
+ .sort((left, right) => right.length - left.length)[0] ?? fallback;
89
+ const createBoundaries = (root, packageRoots, sources) => {
90
+ const grouped = new Map();
91
+ for (const source of sources) {
92
+ const boundaryRoot = getBoundaryRoot(source.file, packageRoots, root);
93
+ const entries = grouped.get(boundaryRoot) ?? [];
94
+ entries.push(source);
95
+ grouped.set(boundaryRoot, entries);
96
+ }
97
+ return [...grouped].map(([boundaryRoot, boundarySources]) => ({
98
+ root: boundaryRoot,
99
+ sources: boundarySources
100
+ }));
101
+ };
102
+ const collectCompatibilityFindings = (root, sources) => sources.flatMap(item => {
103
+ const file = relative(root, item.file);
104
+ const findings = [];
105
+ if (/surface\s*=\s*["']glass["']/u.test(item.source)) {
106
+ findings.push(finding(file, 'deprecated-surface-glass', 'The surface="glass" compatibility alias is deprecated.', 'Replace it with the glass prop or attribute.', 'advisory'));
107
+ }
108
+ if (item.source.includes('ui:datatable-selection-change')) {
109
+ findings.push(finding(file, 'deprecated-datatable-event', 'The ui:datatable-selection-change event alias is deprecated.', 'Rename it to ui:data-table-selection-change.', 'advisory'));
110
+ }
111
+ return findings;
112
+ });
113
+ const getCatalogFingerprint = (sources) => {
114
+ const names = [...new Set(sources.flatMap(item => [
115
+ ...importedNames(item.source, '@santi020k/lumen-astro'),
116
+ ...importedNames(item.source, '@santi020k/lumen-react')
117
+ ]))]
118
+ .filter(name => name in lumenComponentBehavior)
119
+ .sort();
120
+ const contracts = names.map(name => [name, lumenComponentBehavior[name]]);
121
+ return createHash('sha256').update(JSON.stringify(contracts)).digest('hex');
122
+ };
123
+ const hasOnlyRuntimeBypassedComponents = (source, componentName, bypassAttribute) => {
124
+ const tagPattern = new RegExp(`<${componentName}(?=\\s|/|>)([^>]*)>`, 'g');
125
+ const tags = [...source.matchAll(tagPattern)];
126
+ const falsePattern = new RegExp(String.raw `\b${bypassAttribute}\s*=\s*(?:\{false\}|["']false["'])`, 'u');
127
+ const truePattern = new RegExp(String.raw `\b${bypassAttribute}(?:\s|/|$)|` +
128
+ String.raw `\b${bypassAttribute}\s*=\s*(?:\{true\}|["']true["'])`, 'u');
129
+ return tags.length > 0 && tags.every(match => {
130
+ const attributes = match[1] ?? '';
131
+ if (falsePattern.test(attributes))
132
+ return false;
133
+ return truePattern.test(attributes);
134
+ });
135
+ };
136
+ const componentNeedsAstroRuntime = (name, importingSources) => {
137
+ if (!(name in lumenComponentBehavior))
138
+ return false;
139
+ const behavior = lumenComponentBehavior[name];
140
+ if (behavior.astro !== 'ui-primitives')
141
+ return false;
142
+ if ('astroRuntimeBypass' in behavior && importingSources.length > 0 &&
143
+ importingSources.every(item => hasOnlyRuntimeBypassedComponents(item.source, name, behavior.astroRuntimeBypass)))
144
+ return false;
145
+ return true;
146
+ };
147
+ const getRuntimeImports = (sources) => {
148
+ const imports = sources.flatMap(item => importedNames(item.source, '@santi020k/lumen-astro')
149
+ .map(name => ({ file: item.file, name })));
150
+ return imports.filter(item => componentNeedsAstroRuntime(item.name, sources.filter(source => importedNames(source.source, '@santi020k/lumen-astro').includes(item.name))));
151
+ };
152
+ const getGlobalRuntimeBehaviors = (sources) => lumenGlobalBehaviors
153
+ .filter(behavior => sources.some(item => {
154
+ if (behavior.name === 'form-validation')
155
+ return item.source.includes('data-ui-form');
156
+ return behavior.authoredBy.split(',').some(eventName => item.source.includes(eventName.trim()));
157
+ }))
158
+ .map(behavior => behavior.name);
159
+ const collectRuntimeFindings = (repositoryRoot, boundary) => {
160
+ const runtimeImports = getRuntimeImports(boundary.sources);
161
+ const runtimeComponents = [
162
+ ...new Set([
163
+ ...runtimeImports.map(item => item.name),
164
+ ...getGlobalRuntimeBehaviors(boundary.sources)
165
+ ])
166
+ ];
167
+ const mountSources = boundary.sources.filter(item => /<UIPrimitives(?:\s|\/|>)/u.test(item.source));
168
+ const findings = [];
169
+ if (runtimeComponents.length > 0 && mountSources.length === 0) {
170
+ const firstRuntimeImport = runtimeImports[0];
171
+ findings.push(finding(firstRuntimeImport ? relative(repositoryRoot, firstRuntimeImport.file) : relative(repositoryRoot, boundary.root), 'astro-runtime-missing', `Interactive Astro usage requires UIPrimitives: ${runtimeComponents.join(', ')}.`, 'Mount <UIPrimitives /> once in the application root, or use a documented controlled prop when application code owns the behavior.'));
172
+ }
173
+ for (const mount of mountSources) {
174
+ const mountCount = [...mount.source.matchAll(/<UIPrimitives(?:\s|\/|>)/g)].length;
175
+ if (mountCount > 1) {
176
+ findings.push(finding(relative(repositoryRoot, mount.file), 'astro-runtime-duplicate', 'UIPrimitives is mounted more than once in this file.', 'Keep one mount in the application root layout.'));
177
+ }
178
+ }
179
+ const layoutMounts = mountSources.filter(item => layoutFilePattern.test(item.file));
180
+ if (layoutMounts.length > 0) {
181
+ for (const mount of mountSources.filter(item => !layoutMounts.includes(item))) {
182
+ findings.push(finding(relative(repositoryRoot, mount.file), 'astro-runtime-duplicate', 'UIPrimitives is mounted in both a layout and a route within this application boundary.', 'Keep the layout mount and remove the route-level mount.'));
183
+ }
184
+ }
185
+ return { findings, runtimeComponents };
186
+ };
187
+ const styleImportByFramework = {
188
+ astro: '@santi020k/lumen-astro/styles.css',
189
+ elements: '@santi020k/lumen-elements/styles.css',
190
+ react: '@santi020k/lumen-react/styles.css'
191
+ };
192
+ const countOccurrences = (source, value) => source.split(value).length - 1;
193
+ const collectCssFindings = (root, sources) => sources
194
+ .filter(item => item.file.endsWith('.css'))
195
+ .flatMap(item => {
196
+ const layerIndex = item.source.search(/^\s*@import\s+(?:url\(\s*)?["'][^"']*\/layers\.css["']/mu);
197
+ const tailwindIndex = item.source.search(/^\s*@import\s+(?:url\(\s*)?["']tailwindcss["']/mu);
198
+ const styleIndex = item.source.search(/^\s*@import\s+(?:url\(\s*)?["'][^"']*\/styles\.css["']/mu);
199
+ const findings = [];
200
+ if (tailwindIndex >= 0 &&
201
+ styleIndex >= 0 &&
202
+ (layerIndex < 0 || !(layerIndex < tailwindIndex && tailwindIndex < styleIndex))) {
203
+ findings.push(finding(relative(root, item.file), 'tailwind-layer-order', 'Tailwind and Lumen imports do not use the verified cascade order.', 'Import Lumen layers.css, then tailwindcss, then the matching Lumen styles.css.'));
204
+ }
205
+ for (const match of item.source.matchAll(/\.ui-([a-z0-9-]+)/g)) {
206
+ const selector = match[1] ?? '';
207
+ if (!publicRootSlots.has(selector)) {
208
+ findings.push(finding(relative(root, item.file), 'internal-selector', `Selector .ui-${selector} is not a documented stable root hook.`, 'Prefer component props, semantic tokens, documented custom properties, or [data-slot].', 'advisory'));
209
+ }
210
+ }
211
+ return findings;
212
+ });
213
+ const collectFrameworkStyleFindings = (repositoryRoot, boundary, frameworks) => frameworks.flatMap(framework => {
214
+ const styleImport = styleImportByFramework[framework];
215
+ const references = boundary.sources.filter(item => item.source.includes(styleImport));
216
+ if (references.length === 0) {
217
+ return [finding(relative(repositoryRoot, boundary.root) || '.', 'framework-style-missing', `No ${styleImport} import was found in this application boundary.`, 'Load the matching adapter stylesheet once in the application root.')];
218
+ }
219
+ return references.flatMap(item => countOccurrences(item.source, styleImport) > 1 ?
220
+ [finding(relative(repositoryRoot, item.file), 'framework-style-duplicate', `The ${framework} stylesheet is loaded more than once in this file.`, 'Keep one stylesheet import in the application root.')] :
221
+ []);
222
+ });
223
+ const collectAdapterMismatchFindings = (repositoryRoot, boundary, frameworks) => {
224
+ const adapters = Object.entries(styleImportByFramework)
225
+ .flatMap(([framework, styleImport]) => boundary.sources.some(item => item.source.includes(styleImport)) ?
226
+ [framework] :
227
+ []);
228
+ return [...new Set(adapters)]
229
+ .filter(adapter => !frameworks.includes(adapter))
230
+ .map(adapter => finding(relative(repositoryRoot, boundary.root) || '.', 'adapter-style-mismatch', `The ${adapter} stylesheet is loaded without matching ${adapter} imports in this application boundary.`, 'Load the stylesheet from the adapter used by this application boundary.'));
231
+ };
232
+ const uniqueFindings = (findings) => [
233
+ ...new Map(findings.map(item => [
234
+ `${item.file}\u0000${item.rule}\u0000${item.message}`,
235
+ item
236
+ ])).values()
237
+ ];
238
+ export const inspectLumenIntegration = async (repository) => {
239
+ const root = resolve(repository);
240
+ if (!(await stat(root)).isDirectory())
241
+ throw new Error(`Not a directory: ${root}`);
242
+ const discovered = await discoverProject(root);
243
+ const sources = await Promise.all(discovered.sourceFiles.map(async (file) => ({
244
+ file,
245
+ source: await readFile(file, 'utf8')
246
+ })));
247
+ const boundaries = createBoundaries(root, discovered.packageRoots, sources);
248
+ const frameworks = [...new Set(boundaries.flatMap(boundary => getFrameworks(boundary.sources)))];
249
+ const runtimeComponents = new Set();
250
+ const findings = [
251
+ ...collectCompatibilityFindings(root, sources),
252
+ ...collectCssFindings(root, sources)
253
+ ];
254
+ for (const boundary of boundaries) {
255
+ const boundaryFrameworks = getFrameworks(boundary.sources);
256
+ const runtime = collectRuntimeFindings(root, boundary);
257
+ runtime.runtimeComponents.forEach(component => runtimeComponents.add(component));
258
+ findings.push(...runtime.findings, ...collectFrameworkStyleFindings(root, boundary, boundaryFrameworks), ...collectAdapterMismatchFindings(root, boundary, boundaryFrameworks));
259
+ }
260
+ const deduplicatedFindings = uniqueFindings(findings);
261
+ return {
262
+ catalogFingerprint: getCatalogFingerprint(sources),
263
+ findings: deduplicatedFindings,
264
+ frameworks,
265
+ generatedAt: new Date().toISOString(),
266
+ healthy: deduplicatedFindings.every(item => item.severity !== 'error'),
267
+ repository: root,
268
+ runtimeComponents: [...runtimeComponents]
269
+ };
270
+ };
271
+ export const formatLumenDiagnostics = (report) => {
272
+ const heading = report.healthy ? 'Lumen integration is healthy.' : 'Lumen integration has blocking findings.';
273
+ if (report.findings.length === 0)
274
+ return heading;
275
+ return [
276
+ heading,
277
+ ...report.findings.map(item => `[${item.severity}] ${item.file} ${item.rule}: ${item.message} ${item.remediation}`)
278
+ ].join('\n');
279
+ };
280
+ export const createLumenSetup = (framework, tailwind = false) => {
281
+ const setupByFramework = {
282
+ astro: {
283
+ styles: '@import "@santi020k/lumen-astro/styles.css";',
284
+ tailwind: '@import "@santi020k/lumen-astro/layers.css";\n' +
285
+ '@import "tailwindcss";\n' +
286
+ '@import "@santi020k/lumen-astro/styles.css";'
287
+ },
288
+ elements: {
289
+ styles: '@import "@santi020k/lumen-elements/styles.css";',
290
+ tailwind: '@import "@santi020k/lumen-elements/layers.css";\n' +
291
+ '@import "tailwindcss";\n' +
292
+ '@import "@santi020k/lumen-elements/styles.css";'
293
+ },
294
+ react: {
295
+ styles: '@import "@santi020k/lumen-react/styles.css";',
296
+ tailwind: '@import "@santi020k/lumen-react/layers.css";\n' +
297
+ '@import "tailwindcss";\n' +
298
+ '@import "@santi020k/lumen-react/styles.css";'
299
+ }
300
+ };
301
+ const styles = tailwind ? setupByFramework[framework].tailwind : setupByFramework[framework].styles;
302
+ if (framework === 'astro') {
303
+ return `${styles}\n\n---\nimport { UIPrimitives } from '@santi020k/lumen-astro'\n---\n\n<UIPrimitives />`;
304
+ }
305
+ if (framework === 'elements') {
306
+ return `${styles}\n\n` +
307
+ 'import { defineLumenElements } from \'@santi020k/lumen-elements/define\'\n\n' +
308
+ 'defineLumenElements()';
309
+ }
310
+ return styles;
311
+ };
@@ -31,6 +31,42 @@ export declare const lumenRegistry: {
31
31
  readonly name: "data-visualization";
32
32
  readonly type: "recipe";
33
33
  readonly components: readonly ["Chart", "Sparkline", "BarChart", "LineChart", "PieChart", "Stat", "Meter"];
34
+ }, {
35
+ readonly name: "analytics-dashboard";
36
+ readonly type: "recipe";
37
+ readonly components: readonly ["Sidebar", "Stat", "Sparkline", "LineChart", "BarChart", "DateRangePicker", "Table", "Badge"];
38
+ }, {
39
+ readonly name: "saas-admin";
40
+ readonly type: "recipe";
41
+ readonly components: readonly ["Sidebar", "Stat", "Sparkline", "Alert", "Progress", "SearchField", "Table", "Badge"];
42
+ }, {
43
+ readonly name: "commerce-dashboard";
44
+ readonly type: "recipe";
45
+ readonly components: readonly ["Sidebar", "Stat", "Sparkline", "BarChart", "PieChart", "Progress", "Table", "Badge"];
46
+ }, {
47
+ readonly name: "project-workspace";
48
+ readonly type: "recipe";
49
+ readonly components: readonly ["Sidebar", "Stat", "Sparkline", "Progress", "Timeline", "Avatar", "Table", "Badge"];
50
+ }, {
51
+ readonly name: "auth-onboarding";
52
+ readonly type: "recipe";
53
+ readonly components: readonly ["Card", "Stepper", "Field", "Label", "Input", "Alert", "Checkbox", "Progress", "Button"];
54
+ }, {
55
+ readonly name: "docs-shell";
56
+ readonly type: "recipe";
57
+ readonly components: readonly ["SkipLink", "NavigationMenu", "ThemeToggle", "Sidebar", "Sheet", "Prose", "Pagination", "Code", "CodeTabs"];
58
+ }, {
59
+ readonly name: "marketing-shell";
60
+ readonly type: "recipe";
61
+ readonly components: readonly ["SkipLink", "NavigationMenu", "ButtonLink", "Card", "ScrollReveal", "BackToTop"];
62
+ }, {
63
+ readonly name: "dashboard-shell";
64
+ readonly type: "recipe";
65
+ readonly components: readonly ["NavigationMenu", "Sidebar", "Card", "Stat", "StatTrend", "Badge", "SearchField", "DateRangePicker", "Empty", "Table", "Chart"];
66
+ }, {
67
+ readonly name: "validated-form";
68
+ readonly type: "recipe";
69
+ readonly components: readonly ["Form", "Field", "FieldError", "Label", "Input", "NativeSelect", "Textarea", "Button"];
34
70
  }, {
35
71
  readonly name: "ai-docs";
36
72
  readonly type: "documentation";
@@ -166,6 +202,41 @@ export declare const lumenRegistry: {
166
202
  readonly category: "Layout";
167
203
  readonly files: readonly ["packages/astro/components/Card.astro", "packages/astro/styles/lumen.css"];
168
204
  readonly dependencies: readonly ["styles"];
205
+ }, {
206
+ readonly name: "CardContent";
207
+ readonly type: "component";
208
+ readonly description: "Provides the main content region inside a card.";
209
+ readonly category: "Layout";
210
+ readonly files: readonly ["packages/astro/components/CardContent.astro", "packages/astro/styles/lumen.css"];
211
+ readonly dependencies: readonly ["Card", "styles"];
212
+ }, {
213
+ readonly name: "CardDescription";
214
+ readonly type: "component";
215
+ readonly description: "Adds supporting copy to a card header.";
216
+ readonly category: "Layout";
217
+ readonly files: readonly ["packages/astro/components/CardDescription.astro", "packages/astro/styles/lumen.css"];
218
+ readonly dependencies: readonly ["Card", "styles"];
219
+ }, {
220
+ readonly name: "CardFooter";
221
+ readonly type: "component";
222
+ readonly description: "Groups actions at the end of a card.";
223
+ readonly category: "Layout";
224
+ readonly files: readonly ["packages/astro/components/CardFooter.astro", "packages/astro/styles/lumen.css"];
225
+ readonly dependencies: readonly ["Card", "styles"];
226
+ }, {
227
+ readonly name: "CardHeader";
228
+ readonly type: "component";
229
+ readonly description: "Groups introductory content at the start of a card.";
230
+ readonly category: "Layout";
231
+ readonly files: readonly ["packages/astro/components/CardHeader.astro", "packages/astro/styles/lumen.css"];
232
+ readonly dependencies: readonly ["Card", "styles"];
233
+ }, {
234
+ readonly name: "CardTitle";
235
+ readonly type: "component";
236
+ readonly description: "Provides a semantic card title with a stable styling hook.";
237
+ readonly category: "Layout";
238
+ readonly files: readonly ["packages/astro/components/CardTitle.astro", "packages/astro/styles/lumen.css"];
239
+ readonly dependencies: readonly ["Card", "styles"];
169
240
  }, {
170
241
  readonly name: "Carousel";
171
242
  readonly type: "component";
@@ -187,6 +258,13 @@ export declare const lumenRegistry: {
187
258
  readonly category: "Forms";
188
259
  readonly files: readonly ["packages/astro/components/Checkbox.astro", "packages/astro/styles/lumen.css"];
189
260
  readonly dependencies: readonly ["styles"];
261
+ }, {
262
+ readonly name: "CheckboxGroup";
263
+ readonly type: "component";
264
+ readonly description: "Groups related checkbox choices under one legend.";
265
+ readonly category: "Forms";
266
+ readonly files: readonly ["packages/astro/components/CheckboxGroup.astro", "packages/astro/styles/lumen.css"];
267
+ readonly dependencies: readonly ["Checkbox", "styles"];
190
268
  }, {
191
269
  readonly name: "Collapsible";
192
270
  readonly type: "component";
@@ -215,6 +293,20 @@ export declare const lumenRegistry: {
215
293
  readonly category: "Forms";
216
294
  readonly files: readonly ["packages/astro/components/Combobox.astro", "packages/astro/styles/lumen.css", "packages/astro/runtime/UIPrimitives.astro"];
217
295
  readonly dependencies: readonly ["styles", "runtime"];
296
+ }, {
297
+ readonly name: "Container";
298
+ readonly type: "component";
299
+ readonly description: "Centers page content within responsive gutters and a maximum width.";
300
+ readonly category: "Layout";
301
+ readonly files: readonly ["packages/astro/components/Container.astro", "packages/astro/styles/lumen.css"];
302
+ readonly dependencies: readonly ["styles"];
303
+ }, {
304
+ readonly name: "CopyButton";
305
+ readonly type: "component";
306
+ readonly description: "Copies arbitrary text or the content of another element with accessible feedback.";
307
+ readonly category: "Actions";
308
+ readonly files: readonly ["packages/astro/components/CopyButton.astro", "packages/astro/styles/lumen.css", "packages/astro/runtime/UIPrimitives.astro"];
309
+ readonly dependencies: readonly ["styles", "runtime"];
218
310
  }, {
219
311
  readonly name: "Command";
220
312
  readonly type: "component";
@@ -292,6 +384,13 @@ export declare const lumenRegistry: {
292
384
  readonly category: "Feedback";
293
385
  readonly files: readonly ["packages/astro/components/Empty.astro", "packages/astro/styles/lumen.css"];
294
386
  readonly dependencies: readonly ["styles"];
387
+ }, {
388
+ readonly name: "ErrorSummary";
389
+ readonly type: "component";
390
+ readonly description: "Summarizes form errors and links people back to invalid controls.";
391
+ readonly category: "Forms";
392
+ readonly files: readonly ["packages/astro/components/ErrorSummary.astro", "packages/astro/styles/lumen.css"];
393
+ readonly dependencies: readonly ["styles"];
295
394
  }, {
296
395
  readonly name: "Eyebrow";
297
396
  readonly type: "component";
@@ -306,6 +405,13 @@ export declare const lumenRegistry: {
306
405
  readonly category: "Forms";
307
406
  readonly files: readonly ["packages/astro/components/Input.astro", "packages/astro/components/Label.astro", "packages/astro/components/Field.astro", "packages/astro/styles/lumen.css"];
308
407
  readonly dependencies: readonly ["Input", "Label", "styles"];
408
+ }, {
409
+ readonly name: "FieldError";
410
+ readonly type: "component";
411
+ readonly description: "Displays an error connected to a form control.";
412
+ readonly category: "Forms";
413
+ readonly files: readonly ["packages/astro/components/FieldError.astro", "packages/astro/styles/lumen.css"];
414
+ readonly dependencies: readonly ["Field", "styles"];
309
415
  }, {
310
416
  readonly name: "FloatingBadge";
311
417
  readonly type: "component";
@@ -313,6 +419,13 @@ export declare const lumenRegistry: {
313
419
  readonly category: "Data display";
314
420
  readonly files: readonly ["packages/astro/components/FloatingBadge.astro", "packages/astro/styles/lumen.css"];
315
421
  readonly dependencies: readonly ["styles"];
422
+ }, {
423
+ readonly name: "Form";
424
+ readonly type: "component";
425
+ readonly description: "Adds consistent validation and submission state to a native form.";
426
+ readonly category: "Forms";
427
+ readonly files: readonly ["packages/astro/components/Form.astro", "packages/astro/styles/lumen.css", "packages/astro/runtime/UIPrimitives.astro"];
428
+ readonly dependencies: readonly ["styles", "runtime"];
316
429
  }, {
317
430
  readonly name: "FormattedDate";
318
431
  readonly type: "component";
@@ -397,6 +510,13 @@ export declare const lumenRegistry: {
397
510
  readonly category: "Data display";
398
511
  readonly files: readonly ["packages/astro/components/LineChart.astro", "packages/astro/components/Chart.astro", "packages/astro/styles/lumen.css"];
399
512
  readonly dependencies: readonly ["Chart", "styles"];
513
+ }, {
514
+ readonly name: "ListBox";
515
+ readonly type: "component";
516
+ readonly description: "Presents a visible single- or multi-select option list.";
517
+ readonly category: "Forms";
518
+ readonly files: readonly ["packages/astro/components/ListBox.astro", "packages/astro/styles/lumen.css", "packages/astro/runtime/UIPrimitives.astro"];
519
+ readonly dependencies: readonly ["styles", "runtime"];
400
520
  }, {
401
521
  readonly name: "Marker";
402
522
  readonly type: "component";
@@ -453,6 +573,13 @@ export declare const lumenRegistry: {
453
573
  readonly category: "Navigation";
454
574
  readonly files: readonly ["packages/astro/components/Pagination.astro", "packages/astro/styles/lumen.css"];
455
575
  readonly dependencies: readonly ["styles"];
576
+ }, {
577
+ readonly name: "PasswordField";
578
+ readonly type: "component";
579
+ readonly description: "Combines a password input with guidance, errors, and a visibility toggle.";
580
+ readonly category: "Forms";
581
+ readonly files: readonly ["packages/astro/components/PasswordField.astro", "packages/astro/styles/lumen.css", "packages/astro/runtime/UIPrimitives.astro"];
582
+ readonly dependencies: readonly ["Button", "Field", "FieldError", "Input", "Label", "styles", "runtime"];
456
583
  }, {
457
584
  readonly name: "PhoneInput";
458
585
  readonly type: "component";
@@ -486,8 +613,8 @@ export declare const lumenRegistry: {
486
613
  readonly type: "component";
487
614
  readonly description: "Shows completion, loading progress, or quota usage.";
488
615
  readonly category: "Feedback";
489
- readonly files: readonly ["packages/astro/components/Progress.astro", "packages/astro/styles/lumen.css"];
490
- readonly dependencies: readonly ["styles"];
616
+ readonly files: readonly ["packages/astro/components/Progress.astro", "packages/astro/styles/lumen.css", "packages/astro/runtime/UIPrimitives.astro"];
617
+ readonly dependencies: readonly ["styles", "runtime"];
491
618
  }, {
492
619
  readonly name: "Prose";
493
620
  readonly type: "component";
@@ -765,6 +892,48 @@ export declare const lumenRegistry: {
765
892
  readonly category: "Data display";
766
893
  readonly description: "A stat component.";
767
894
  readonly files: readonly ["packages/astro/components/Stat.astro", "packages/react/src/components.tsx"];
895
+ }, {
896
+ readonly name: "StatDescription";
897
+ readonly type: "component";
898
+ readonly description: "Adds supporting context to a composed statistic.";
899
+ readonly category: "Data display";
900
+ readonly files: readonly ["packages/astro/components/StatDescription.astro", "packages/astro/styles/lumen.css"];
901
+ readonly dependencies: readonly ["Stat", "styles"];
902
+ }, {
903
+ readonly name: "StatIcon";
904
+ readonly type: "component";
905
+ readonly description: "Provides an icon region for a composed statistic.";
906
+ readonly category: "Data display";
907
+ readonly files: readonly ["packages/astro/components/StatIcon.astro", "packages/astro/styles/lumen.css"];
908
+ readonly dependencies: readonly ["Stat", "styles"];
909
+ }, {
910
+ readonly name: "StatLabel";
911
+ readonly type: "component";
912
+ readonly description: "Labels a composed statistic.";
913
+ readonly category: "Data display";
914
+ readonly files: readonly ["packages/astro/components/StatLabel.astro", "packages/astro/styles/lumen.css"];
915
+ readonly dependencies: readonly ["Stat", "styles"];
916
+ }, {
917
+ readonly name: "StatTrend";
918
+ readonly type: "component";
919
+ readonly description: "Communicates a metric delta with a semantic tone.";
920
+ readonly category: "Data display";
921
+ readonly files: readonly ["packages/astro/components/StatTrend.astro", "packages/astro/styles/lumen.css"];
922
+ readonly dependencies: readonly ["Stat", "styles"];
923
+ }, {
924
+ readonly name: "StatValue";
925
+ readonly type: "component";
926
+ readonly description: "Displays the prominent value in a composed statistic.";
927
+ readonly category: "Data display";
928
+ readonly files: readonly ["packages/astro/components/StatValue.astro", "packages/astro/styles/lumen.css"];
929
+ readonly dependencies: readonly ["Stat", "styles"];
930
+ }, {
931
+ readonly name: "Stack";
932
+ readonly type: "component";
933
+ readonly description: "Arranges children with tokenized direction, spacing, and alignment.";
934
+ readonly category: "Layout";
935
+ readonly files: readonly ["packages/astro/components/Stack.astro", "packages/astro/styles/lumen.css"];
936
+ readonly dependencies: readonly ["styles"];
768
937
  }, {
769
938
  readonly name: "Meter";
770
939
  readonly type: "component";
@@ -915,6 +1084,20 @@ export declare const lumenRegistry: {
915
1084
  readonly category: "Navigation";
916
1085
  readonly description: "A floating action button with expandable sub-actions.";
917
1086
  readonly files: readonly ["packages/astro/components/SpeedDial.astro", "packages/react/src/components.tsx"];
1087
+ }, {
1088
+ readonly name: "Grid";
1089
+ readonly type: "component";
1090
+ readonly category: "Layout";
1091
+ readonly description: "Arranges content in fixed or responsive tokenized columns.";
1092
+ readonly files: readonly ["packages/astro/components/Grid.astro", "packages/astro/styles/lumen.css"];
1093
+ readonly dependencies: readonly ["styles"];
1094
+ }, {
1095
+ readonly name: "VisuallyHidden";
1096
+ readonly type: "component";
1097
+ readonly category: "Layout";
1098
+ readonly description: "Keeps meaningful content available to assistive technology without displaying it.";
1099
+ readonly files: readonly ["packages/astro/components/VisuallyHidden.astro", "packages/astro/styles/lumen.css"];
1100
+ readonly dependencies: readonly ["styles"];
918
1101
  }];
919
1102
  };
920
1103
  //# sourceMappingURL=registry-data.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry-data.d.ts","sourceRoot":"","sources":["../src/registry-data.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkyDQ,CAAA"}
1
+ {"version":3,"file":"registry-data.d.ts","sourceRoot":"","sources":["../src/registry-data.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+sEQ,CAAA"}