@santi020k/lumen-astro 3.0.1 → 4.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.
- package/README.md +424 -7
- package/components/AmountField.astro +21 -0
- package/components/AnimatedNumber.astro +1 -1
- package/components/ApprovalCard.astro +30 -0
- package/components/AttachmentList.astro +15 -0
- package/components/AttachmentPreview.astro +51 -0
- package/components/Avatar.astro +2 -0
- package/components/BarChart.astro +95 -31
- package/components/BoxPlot.astro +77 -0
- package/components/Breadcrumb.astro +2 -1
- package/components/BulletChart.astro +64 -0
- package/components/Button.astro +1 -1
- package/components/Calendar.astro +54 -65
- package/components/CalendarHeatmap.astro +76 -0
- package/components/Card.astro +4 -0
- package/components/ChangeSummary.astro +36 -0
- package/components/ChartDatumActions.astro +24 -0
- package/components/ChartMotion.astro +11 -0
- package/components/Code.astro +18 -3
- package/components/CodeTabs.astro +12 -0
- package/components/ComboChart.astro +93 -11
- package/components/CountryFlag.astro +23 -0
- package/components/DataTable.astro +15 -7
- package/components/DatePicker.astro +24 -17
- package/components/DescriptionDetail.astro +18 -0
- package/components/DescriptionItem.astro +18 -0
- package/components/DescriptionTerm.astro +18 -0
- package/components/DeviceFrame.astro +79 -0
- package/components/DialogBody.astro +20 -0
- package/components/DialogClose.astro +21 -0
- package/components/DialogFooter.astro +20 -0
- package/components/DialogHeader.astro +20 -0
- package/components/DialogTitle.astro +21 -0
- package/components/DumbbellChart.astro +8 -0
- package/components/FileUpload.astro +3 -1
- package/components/FilterBar.astro +25 -0
- package/components/FunnelChart.astro +50 -0
- package/components/Grid.astro +2 -2
- package/components/Heatmap.astro +61 -12
- package/components/Histogram.astro +30 -0
- package/components/Icon.astro +7 -3
- package/components/ImageComparison.astro +74 -0
- package/components/Input.astro +2 -2
- package/components/LineChart.astro +122 -66
- package/components/ListBox.astro +2 -1
- package/components/LollipopChart.astro +8 -0
- package/components/MediaFilmstrip.astro +19 -0
- package/components/MediaThumbnail.astro +29 -0
- package/components/MediaViewport.astro +38 -0
- package/components/Mentions.astro +2 -1
- package/components/MessageScroller.astro +6 -0
- package/components/MotionGroup.astro +19 -0
- package/components/NativeSelect.astro +2 -2
- package/components/Pagination.astro +2 -1
- package/components/PasswordField.astro +1 -1
- package/components/PhoneInput.astro +60 -9
- package/components/PhoneNumber.astro +19 -0
- package/components/PieChart.astro +26 -3
- package/components/Progress.astro +2 -4
- package/components/PromptComposer.astro +36 -0
- package/components/RangeChart.astro +38 -8
- package/components/ScatterChart.astro +62 -14
- package/components/Segmented.astro +5 -5
- package/components/Select.astro +8 -8
- package/components/Skeleton.astro +46 -5
- package/components/SourceCitation.astro +18 -0
- package/components/Sparkline.astro +9 -10
- package/components/Spinner.astro +4 -4
- package/components/Stack.astro +2 -2
- package/components/StreamMessage.astro +26 -0
- package/components/Tabs.astro +3 -0
- package/components/ToolActivity.astro +17 -0
- package/components/TreeSelect.astro +1 -0
- package/components/VirtualList.astro +5 -2
- package/components/VisualEffect.astro +21 -0
- package/components/WaterfallChart.astro +27 -0
- package/components/WorldMap.astro +213 -0
- package/forms.ts +17 -4
- package/index.ts +37 -0
- package/internal/ChartInspection.astro +27 -0
- package/internal/ComparisonChart.astro +69 -0
- package/internal/IntervalChart.astro +66 -0
- package/package.json +6 -4
- package/runtime/UIPrimitives.astro +739 -711
- package/runtime/chart-actions.ts +19 -0
- package/runtime/controllers/amount-field.ts +12 -0
- package/runtime/controllers/attachments.ts +13 -0
- package/runtime/controllers/chart-activation.ts +33 -0
- package/runtime/controllers/charts.ts +33 -0
- package/runtime/controllers/combobox.ts +39 -0
- package/runtime/controllers/comparison-reset.ts +20 -0
- package/runtime/controllers/data-table.ts +142 -0
- package/runtime/controllers/dialogs.ts +32 -32
- package/runtime/controllers/document-navigation.ts +54 -22
- package/runtime/controllers/file-upload.ts +89 -0
- package/runtime/controllers/image-comparison.ts +53 -0
- package/runtime/controllers/list-box-proxy.ts +209 -0
- package/runtime/controllers/media-selection.ts +20 -0
- package/runtime/controllers/media-viewport.ts +54 -0
- package/runtime/controllers/media-workspace.ts +8 -0
- package/runtime/controllers/message-scroller.ts +13 -0
- package/runtime/controllers/motion.ts +15 -16
- package/runtime/controllers/optional-media.ts +29 -0
- package/runtime/controllers/phone-input.ts +128 -39
- package/runtime/controllers/progress.ts +52 -0
- package/runtime/controllers/visual-interactions.ts +75 -0
- package/runtime/controllers/world-map.ts +154 -0
- package/styles/critical.css +696 -66
- package/styles/lumen.css +101 -0
package/README.md
CHANGED
|
@@ -1,10 +1,79 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://lumen.santi020k.com">
|
|
3
|
+
<picture>
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/santi020k/lumen/main/docs/assets/readme/package-dark.svg">
|
|
5
|
+
<img src="https://raw.githubusercontent.com/santi020k/lumen/main/docs/assets/readme/package-light.svg" alt="Lumen UI — Web. Native. Thoughtfully connected." width="1200" height="184">
|
|
6
|
+
</picture>
|
|
7
|
+
</a>
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
<h1 align="center">Lumen UI · Astro</h1>
|
|
11
|
+
|
|
12
|
+
<p align="center">Reference components · Progressive enhancement · Standalone CSS</p>
|
|
13
|
+
|
|
14
|
+
<p align="center">
|
|
15
|
+
<a href="https://www.npmjs.com/package/@santi020k/lumen-astro"><img src="https://img.shields.io/npm/v/@santi020k/lumen-astro?style=flat-square&color=0369a0" alt="npm version"></a>
|
|
16
|
+
<a href="https://github.com/santi020k/lumen/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-13967e?style=flat-square" alt="MIT license"></a>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
<a href="https://lumen.santi020k.com/docs/frameworks/astro">Documentation</a>
|
|
21
|
+
·
|
|
22
|
+
<a href="https://www.npmjs.com/package/@santi020k/lumen-astro">npm</a>
|
|
23
|
+
·
|
|
24
|
+
<a href="https://github.com/santi020k/lumen/tree/main/packages/astro">Source</a>
|
|
25
|
+
·
|
|
26
|
+
<a href="https://github.com/santi020k/lumen/issues">Issues</a>
|
|
27
|
+
</p>
|
|
28
|
+
|
|
29
|
+
**Package:** `@santi020k/lumen-astro`
|
|
30
|
+
|
|
31
|
+
**On this page:** [Install](#install) · [Appearance presets](#appearance-presets) · [Resources](#resources)
|
|
32
|
+
|
|
33
|
+
<details>
|
|
34
|
+
<summary>Browse all sections</summary>
|
|
35
|
+
|
|
36
|
+
- [Install](#install)
|
|
37
|
+
- [Appearance presets](#appearance-presets)
|
|
38
|
+
- [Compound interactive components](#compound-interactive-components)
|
|
39
|
+
- [Context navigation](#context-navigation)
|
|
40
|
+
- [Forms and Astro Actions](#forms-and-astro-actions)
|
|
41
|
+
- [Error states](#error-states)
|
|
42
|
+
- [Long-form navigation](#long-form-navigation)
|
|
43
|
+
- [Data visualization](#data-visualization)
|
|
44
|
+
- [Code tabs](#code-tabs)
|
|
45
|
+
- [Optimized images](#optimized-images)
|
|
46
|
+
- [Kanban boards](#kanban-boards)
|
|
47
|
+
- [Motion](#motion)
|
|
48
|
+
- [Glass surfaces](#glass-surfaces)
|
|
49
|
+
- [Semantic stat roots](#semantic-stat-roots)
|
|
50
|
+
- [Consumer composition recipes](#consumer-composition-recipes)
|
|
51
|
+
- [Exact amount fields](#exact-amount-fields)
|
|
52
|
+
- [Phone presentation in v4](#phone-presentation-in-v4)
|
|
53
|
+
- [Combobox keyboard behavior](#combobox-keyboard-behavior)
|
|
54
|
+
- [Content flow](#content-flow)
|
|
55
|
+
- [Attachment composition](#attachment-composition)
|
|
56
|
+
- [Chart datum actions](#chart-datum-actions)
|
|
57
|
+
- [Dashboard composition](#dashboard-composition)
|
|
58
|
+
- [Visual interactions and product blocks](#visual-interactions-and-product-blocks)
|
|
59
|
+
- [Device demonstrations](#device-demonstrations)
|
|
60
|
+
- [World map](#world-map)
|
|
61
|
+
- [Studio media workspace](#studio-media-workspace)
|
|
62
|
+
- [Resources](#resources)
|
|
63
|
+
|
|
64
|
+
</details>
|
|
2
65
|
|
|
3
66
|
Production-ready Astro primitives for Lumen UI. The stylesheet is standalone CSS, so no Tailwind
|
|
4
67
|
configuration is required to render the components.
|
|
5
68
|
|
|
69
|
+
Form controls use `visualSize` (`visual-size` in Elements) with `default`, `sm` and `lg`.
|
|
70
|
+
Select, PhoneInput and Segmented follow Input and NativeSelect; numeric input/select `size` keeps
|
|
71
|
+
its native meaning. See the [v4 migration guide](https://github.com/santi020k/lumen/blob/main/docs/migrating-v3-to-v4.md#form-control-visual-sizing).
|
|
72
|
+
|
|
6
73
|
## Install
|
|
7
74
|
|
|
75
|
+
Requires Astro 5 or newer in the consuming application.
|
|
76
|
+
|
|
8
77
|
```bash
|
|
9
78
|
pnpm add @santi020k/lumen-astro
|
|
10
79
|
```
|
|
@@ -53,11 +122,11 @@ import UIPrimitives from '@santi020k/lumen-astro/runtime'
|
|
|
53
122
|
|
|
54
123
|
```astro
|
|
55
124
|
---
|
|
56
|
-
import { Button, Card, Input } from '@santi020k/lumen-astro'
|
|
125
|
+
import { Button, Card, Input, Label } from '@santi020k/lumen-astro'
|
|
57
126
|
---
|
|
58
127
|
|
|
59
128
|
<Card>
|
|
60
|
-
<
|
|
129
|
+
<Label for="email">Email</Label>
|
|
61
130
|
<Input id="email" type="email" placeholder="you@example.com" />
|
|
62
131
|
<Button>Subscribe</Button>
|
|
63
132
|
</Card>
|
|
@@ -74,7 +143,10 @@ import { Button, Card, Input } from '@santi020k/lumen-astro'
|
|
|
74
143
|
`PhoneInput` generates localized country names, supplementary flags, and calling codes when custom
|
|
75
144
|
`countries` are not provided. Mount `UIPrimitives` once to enable as-you-type formatting,
|
|
76
145
|
metadata-backed validation, automatic country detection for pasted international numbers, and the
|
|
77
|
-
`ui:phone-change` event with a `LumenPhoneNumber` detail.
|
|
146
|
+
`ui:phone-change` event with a `LumenPhoneNumber` detail. Validation messages and inherited locale
|
|
147
|
+
resolve in the phone control's owning document, including after iframe adoption. Repeated runtime
|
|
148
|
+
initialization binds adopted phone controls to their current reset root; reset synchronization follows
|
|
149
|
+
the current form owner and honors cancellation without duplicating edit listeners.
|
|
78
150
|
|
|
79
151
|
The phone metadata and normalization controller are selector-loaded only when a rendered page
|
|
80
152
|
contains `PhoneInput`; pages without the component do not evaluate or download that controller.
|
|
@@ -83,16 +155,36 @@ contains `PhoneInput`; pages without the component do not evaluate or download t
|
|
|
83
155
|
<PhoneInput countryValue="CO" locale="en-US" name="hospitalPhone" />
|
|
84
156
|
```
|
|
85
157
|
|
|
158
|
+
## Appearance presets
|
|
159
|
+
|
|
160
|
+
Set `data-lumen-preset="studio"` and an optional `data-lumen-scheme="light|dark"` on the application root. See [appearance presets](https://github.com/santi020k/lumen/blob/main/docs/appearance-presets.md) for Default, Studio, Glass and scoped customization.
|
|
161
|
+
|
|
86
162
|
## Compound interactive components
|
|
87
163
|
|
|
164
|
+
DatePicker, Calendar, and InputOTP enhancement skips markup marked `data-ui-owner`, such as the
|
|
165
|
+
matching React controls, so those islands keep their ids, labels, and state before and after hydration.
|
|
166
|
+
|
|
88
167
|
Popover, dropdown menu, tabs, and tooltip parts expose the DOM and ARIA contracts consumed by the
|
|
89
168
|
shared progressive-enhancement runtime. Prefer these parts over recreating roles and `data-ui-*`
|
|
90
169
|
attributes by hand.
|
|
91
170
|
|
|
171
|
+
Disclosure keyboard navigation skips hidden or inert regions, invisible controls, and native
|
|
172
|
+
disabled controls, including a disabled fieldset. Available controls in a fieldset's first legend
|
|
173
|
+
retain their native keyboard behavior; removing `inert` makes a region available again.
|
|
174
|
+
|
|
175
|
+
Mentions keeps suggestion navigation on the textarea through `aria-activedescendant`; suggestion
|
|
176
|
+
buttons are excluded from the Tab sequence. Returning focus before the delayed blur dismissal
|
|
177
|
+
preserves reopened suggestions. Static Toast markup is enhanced again after client
|
|
178
|
+
navigation, retaining Escape dismissal without duplicate listeners.
|
|
179
|
+
|
|
92
180
|
Tabs keep the selected trigger visible when a narrow tab list scrolls horizontally and emit a
|
|
93
181
|
typed `ui:tabs-change` event. Import `LumenTabsChangeDetail` or `LumenTabsChangeEvent` from this
|
|
94
182
|
package when application behavior follows the selected value.
|
|
95
183
|
|
|
184
|
+
Keyboard tab navigation skips disabled triggers and stays within the current group when tabs are nested.
|
|
185
|
+
Dialogs preserve native `autofocus`, restore their connected opener on close, and dismiss only a
|
|
186
|
+
backdrop press that starts and ends outside the dialog. Alert dialogs retain explicit dismissal.
|
|
187
|
+
|
|
96
188
|
```astro
|
|
97
189
|
---
|
|
98
190
|
import {
|
|
@@ -211,7 +303,7 @@ announcement.
|
|
|
211
303
|
</ErrorState>
|
|
212
304
|
```
|
|
213
305
|
|
|
214
|
-
See the repository [Astro error-handling guide](
|
|
306
|
+
See the repository [Astro error-handling guide](https://github.com/santi020k/lumen/blob/main/docs/error-handling.md#astro) for the complete
|
|
215
307
|
example, retry ownership, announcement behavior, and verification guidance.
|
|
216
308
|
|
|
217
309
|
Use `Icon` for Lucide icons by name across framework adapters.
|
|
@@ -247,6 +339,24 @@ import { Anchor, CopyButton, ScrollProgress } from '@santi020k/lumen-astro'
|
|
|
247
339
|
]} />
|
|
248
340
|
```
|
|
249
341
|
|
|
342
|
+
Enhanced `DatePicker` controls mirror native input `aria-invalid`, `aria-describedby`, and
|
|
343
|
+
`aria-errormessage` attributes onto the visible trigger, including later attribute changes.
|
|
344
|
+
Valid updates and uncanceled resets clear generated validation feedback while preserving explicit
|
|
345
|
+
application errors.
|
|
346
|
+
|
|
347
|
+
`Skeleton` accepts `shape` (`rectangle`, `text`, `circle`), `width`, `height`, and `animation`
|
|
348
|
+
(`shimmer`, `pulse`, `none`). Numeric sizes are pixels; CSS lengths, percentages, and math or
|
|
349
|
+
custom-property expressions also work. Explicit styles take precedence. Empty placeholders default
|
|
350
|
+
to 1rem high, while text and element content can grow naturally. Reduced motion stops animations.
|
|
351
|
+
Unnamed Skeletons and Spinners are decorative. Give a standalone indicator an accessible name, or
|
|
352
|
+
wrap a group in one named status region with `VisuallyHidden` text.
|
|
353
|
+
|
|
354
|
+
```astro
|
|
355
|
+
<Skeleton shape="circle" width={40} />
|
|
356
|
+
<Skeleton shape="text" width="80%" />
|
|
357
|
+
<Skeleton animation="pulse" height={8} width="60%" />
|
|
358
|
+
```
|
|
359
|
+
|
|
250
360
|
`Progress` can be updated after hydration by dispatching `ui:progress-change` from its root with
|
|
251
361
|
`{ value, max? }`. Use `CopyButton` to copy arbitrary text or a referenced element without giving
|
|
252
362
|
non-code content `Code` semantics.
|
|
@@ -266,6 +376,17 @@ sync with the accessible label; free-form default children remain the idle prese
|
|
|
266
376
|
|
|
267
377
|
## Data visualization
|
|
268
378
|
|
|
379
|
+
The web visualization milestone adds `WaterfallChart` for signed changes and explicit totals, and
|
|
380
|
+
`Histogram` for precomputed numeric bins (`frequency="density"` for unequal widths). Line charts
|
|
381
|
+
support explicit continuous axes, annotations, optional keyboard/pointer/touch inspection, and
|
|
382
|
+
synchronized cursors. Heatmaps show labeled axes, a color legend, and explicit missing cells.
|
|
383
|
+
See the [visualization contracts](https://github.com/santi020k/lumen/blob/main/docs/data-visualization.md) and
|
|
384
|
+
[interactive web example](https://lumen.santi020k.com/docs/web/data-visualization).
|
|
385
|
+
|
|
386
|
+
Set `interactive` on `LineChart` and mount `UIPrimitives` to enable inspection and legend buttons.
|
|
387
|
+
Static charts continue to render without client JavaScript. After moving an enhanced chart into another
|
|
388
|
+
document, rerun `UIPrimitives` initialization so cursor synchronization follows that document's peers.
|
|
389
|
+
|
|
269
390
|
Use `Sparkline` beside a metric, `BarChart` for categorical comparison, `LineChart` for ordered
|
|
270
391
|
trends, `PieChart` for a small part-to-whole breakdown, `ScatterChart` for numeric relationships,
|
|
271
392
|
`Heatmap` for a matrix, `RangeChart` for intervals, and `ComboChart` for a shared-domain mix of bars,
|
|
@@ -291,7 +412,7 @@ const series = [{
|
|
|
291
412
|
`variant="donut"` and also supports `variant="pie"`.
|
|
292
413
|
|
|
293
414
|
Every chart includes a factual screen-reader summary by default and accepts `summary` for more
|
|
294
|
-
useful domain context. See [data visualization](
|
|
415
|
+
useful domain context. See [data visualization](https://github.com/santi020k/lumen/blob/main/docs/data-visualization.md) for selection,
|
|
295
416
|
missing-data, live-data, and accessibility guidance.
|
|
296
417
|
|
|
297
418
|
Lucide intentionally excludes brand marks. For GitHub and other project-specific icons, put the
|
|
@@ -395,6 +516,17 @@ content readable without JavaScript and honor reduced-motion preferences.
|
|
|
395
516
|
<AnimatedNumber decimals={1} suffix="%" value={99.8} />
|
|
396
517
|
```
|
|
397
518
|
|
|
519
|
+
With the optional motion stylesheet, native `Collapsible` and `Accordion` content smoothly expands and collapses in browsers supporting
|
|
520
|
+
`::details-content` and `interpolate-size`. Other browsers retain the immediate native toggle.
|
|
521
|
+
Dialogs, drawers, sheets, menus, and toasts retain their existing shared-token transitions.
|
|
522
|
+
|
|
523
|
+
For optional insertion, removal, or state feedback, use
|
|
524
|
+
[`animateLumenPresence`](https://github.com/santi020k/lumen/blob/main/packages/core/README.md#presence-motion) on a DOM reference. Applications keep
|
|
525
|
+
ownership of state, focus, and DOM removal. Set `data-ui-motion="reduce"` on a container for a local
|
|
526
|
+
reduced-motion preference; the system preference is always respected.
|
|
527
|
+
Try dialogs, bottom drawers, and side sheets in the [motion playground](https://lumen.santi020k.com/docs/motion-playground).
|
|
528
|
+
System reduced motion shortens both panel and backdrop transitions.
|
|
529
|
+
|
|
398
530
|
## Glass surfaces
|
|
399
531
|
|
|
400
532
|
Lumen includes glassmorphism tokens and reusable classes in the shared stylesheet. Cards use a
|
|
@@ -425,7 +557,292 @@ or `variant="glass"` for selective translucency.
|
|
|
425
557
|
|
|
426
558
|
## Consumer composition recipes
|
|
427
559
|
|
|
428
|
-
See [consumer UI recipes](
|
|
560
|
+
See [consumer UI recipes](https://github.com/santi020k/lumen/blob/main/docs/consumer-ui-recipes.md) for static React icons, responsive
|
|
429
561
|
record tables, keyboard-aware native sheets, whole-unit amount fields, adaptive editors, and
|
|
430
562
|
asynchronous action states. Each recipe identifies the public primitives and the behavior that
|
|
431
563
|
remains owned by the application.
|
|
564
|
+
|
|
565
|
+
## Exact amount fields
|
|
566
|
+
|
|
567
|
+
`AmountField` formats an ASCII decimal-string `value` in the requested locale and submits a
|
|
568
|
+
complete ungrouped value through its named hidden input. Include `UIPrimitives` for editing,
|
|
569
|
+
validity and reset behavior. Domain validation and monetary units remain application-owned.
|
|
570
|
+
|
|
571
|
+
```astro
|
|
572
|
+
<AmountField name="amount" locale="es-CO" value="1234.50" aria-label="Amount COP" />
|
|
573
|
+
<UIPrimitives />
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
See [consumer workflows](https://github.com/santi020k/lumen/blob/main/docs/consumer-ui-recipes.md#executable-consumer-workflows).
|
|
577
|
+
|
|
578
|
+
### Accessible documentation controls
|
|
579
|
+
|
|
580
|
+
`Code` and `CodeTabs` accept `copyLabel`, `copiedLabel`, `errorLabel`, and
|
|
581
|
+
`codeLabel` strings. The first three customize clipboard controls and their live
|
|
582
|
+
success/error feedback; `codeLabel` names the keyboard-focusable region for an
|
|
583
|
+
unwrapped code block. A denied or unavailable clipboard reports the error label
|
|
584
|
+
and keeps the source available for manual selection. `CodeTabs` forwards these
|
|
585
|
+
labels to each code example.
|
|
586
|
+
|
|
587
|
+
`Code` with `highlighted` enhances the supplied `pre` when the Astro runtime loads.
|
|
588
|
+
For keyboard scrolling before JavaScript loads, give that `pre` `tabindex="0"`,
|
|
589
|
+
`role="region"`, and an accessible name; existing attributes are preserved.
|
|
590
|
+
Wrapped blocks do not add an extra tab stop.
|
|
591
|
+
|
|
592
|
+
`NavigationMenu` contains ordinary site links, so every enabled link remains in
|
|
593
|
+
native Tab order. Use `Menubar` or `Toolbar` for their documented composite-widget
|
|
594
|
+
keyboard behavior. A `ThemeToggle` with `controlled` respects the host theme at
|
|
595
|
+
initialization and leaves persistence and theme changes to its owner.
|
|
596
|
+
|
|
597
|
+
### Virtual list and editor ownership
|
|
598
|
+
|
|
599
|
+
`VirtualList` displays fixed-height rows with inert spacers that retain the full scroll extent.
|
|
600
|
+
Rows stay mounted; use pagination when the initial DOM cost matters. Scrolling, resizing, sizing
|
|
601
|
+
changes and direct row changes refresh the window. Focused rows remain available. After document
|
|
602
|
+
adoption, rerun the standard initializer to rebind the controller to the destination document. See the
|
|
603
|
+
[fixed-height list contract](https://github.com/santi020k/lumen/blob/main/docs/ai-usage.md#fixed-height-virtual-lists).
|
|
604
|
+
|
|
605
|
+
External rich-text engines should handle the cancelable `ui:editor-command-request` event before
|
|
606
|
+
execution and use `ui:editor-command` only for completion notifications. React also supports
|
|
607
|
+
`useRichTextEditor({ commandHandler })`. Disable native toolbar state syncing when the external
|
|
608
|
+
engine owns it. See the [editor guidance](https://github.com/santi020k/lumen/blob/main/docs/ai-usage.md).
|
|
609
|
+
|
|
610
|
+
## Phone presentation in v4
|
|
611
|
+
|
|
612
|
+
Phone inputs bundle the same offline flag artwork on every platform. The selected country shows
|
|
613
|
+
its flag and calling code inside one continuous input border. Country names remain in the native
|
|
614
|
+
picker and its accessible name; flags are supplementary. Unknown flag codes fall back to text.
|
|
615
|
+
|
|
616
|
+
Astro and React `PhoneInput` accept `disabled`, `readOnly`, `required`, `errorMessage`,
|
|
617
|
+
`showValidationError`, and `inputProps`. Their `id` targets the number input in v4; React also
|
|
618
|
+
accepts `inputRef`. Web Components use `disabled`, `readonly`, `required`, `error-message`,
|
|
619
|
+
`show-validation-error="false"`, and `input-id`, with native input attributes on the host.
|
|
620
|
+
Both controls lock together and validation remains associated with the input. Astro forwards
|
|
621
|
+
`inputProps.form` to the number input, country picker and read-only country fallback so external
|
|
622
|
+
form submission and reset include every part.
|
|
623
|
+
|
|
624
|
+
The `phone-input`, `phone-country`, and `country-flag` styling parts plus `--ui-phone-height`,
|
|
625
|
+
`--ui-phone-padding`, and `--ui-phone-country-gap` replace consumer CSS overlays.
|
|
626
|
+
|
|
627
|
+
Astro and React also export `CountryFlag` (`regionCode`, optional `decorative`) and `PhoneNumber`
|
|
628
|
+
(`value: LumenPhoneNumber`, optional `link`). A telephone link is rendered only for a complete
|
|
629
|
+
E.164 value. Use the model returned by the phone normalizer; keep domain persistence in your app.
|
|
630
|
+
Artwork attribution is shipped with the core package in `PHONE_FLAG_LICENSE.txt`.
|
|
631
|
+
|
|
632
|
+
## Combobox keyboard behavior
|
|
633
|
+
|
|
634
|
+
In v4, Combobox retains input focus and exposes its active option through `aria-activedescendant`.
|
|
635
|
+
Enter commits an active option; text editing and composition remain native. Escape dismisses one
|
|
636
|
+
nested control at a time. See the [shared keyboard contract](https://github.com/santi020k/lumen/blob/main/docs/ai-usage.md#combobox-keyboard-behavior-in-v4)
|
|
637
|
+
for dynamic options, controlled inputs and migration guidance.
|
|
638
|
+
|
|
639
|
+
## Content flow
|
|
640
|
+
|
|
641
|
+
Stack and Grid own sibling spacing. Their gap accepts `related`, `group` (default) and `section`,
|
|
642
|
+
or canonical `none`, `xs`, `sm`, `md`, `lg`, `xl`, `2xl`, `3xl` sizes. Card owns the inset and gap
|
|
643
|
+
between its visible parts; use `density="compact"`, `"comfortable"` (default) or `"spacious"`.
|
|
644
|
+
Elements uses the same names as attributes. Use a nested Stack for CardContent groups and Field
|
|
645
|
+
for label/control/feedback. See [content flow](https://github.com/santi020k/lumen/blob/main/docs/content-flow.md) and the
|
|
646
|
+
[v4 migration guide](https://github.com/santi020k/lumen/blob/main/docs/migrating-to-lumen.md) for ownership and changed explicit gaps.
|
|
647
|
+
|
|
648
|
+
### Reading and complete compositions
|
|
649
|
+
|
|
650
|
+
Prose and Typography trim outer child margins and separate headings from preceding text.
|
|
651
|
+
Container gutters grow from 16px to 32px with viewport width; override `--ui-container-gutter`
|
|
652
|
+
when a product needs fixed gutters. Card allows interactive overflow; use AspectRatio to clip media.
|
|
653
|
+
Install `content-flow-header`, `content-flow-settings`, `content-flow-list` or `content-flow-actions`
|
|
654
|
+
with `lumen add <recipe> --target astro|react|elements`. MCP returns the same complete examples.
|
|
655
|
+
Connect application actions and replace sample IDs before reuse. See
|
|
656
|
+
[content flow](https://github.com/santi020k/lumen/blob/main/docs/content-flow.md) for composition and migration guidance.
|
|
657
|
+
|
|
658
|
+
### Large fixed-height collections
|
|
659
|
+
|
|
660
|
+
`VirtualList` supports an empty `mode="data"` root with the public Core data controller.
|
|
661
|
+
Only the visible window, overscan and focused neighbors mount. Stable keys retain row identity;
|
|
662
|
+
applications own offscreen editing state. See [data rendering](https://github.com/santi020k/lumen/blob/main/docs/virtual-list-data.md) for
|
|
663
|
+
setup, lifecycle, accessibility and the mounted-mode tradeoff.
|
|
664
|
+
|
|
665
|
+
Action-error normalization ignores malformed fields and non-string messages. Enhanced forms include
|
|
666
|
+
externally associated native controls. Reinitialize with `LumenInitUiPrimitives(destination)` after
|
|
667
|
+
adopting an enhanced form into another document so blur validation follows its owner, including
|
|
668
|
+
controls created in another document. Timed toasts stay paused while hovered or focused.
|
|
669
|
+
|
|
670
|
+
### Compound dialog tasks
|
|
671
|
+
|
|
672
|
+
Use `DialogHeader`, `DialogTitle`, `DialogBody`, `DialogFooter`, and `DialogClose`
|
|
673
|
+
for long forms. Associate the title explicitly so labeling works before enhancement.
|
|
674
|
+
`DialogBody` must be a direct child of `Dialog` for independent scrolling. Footer
|
|
675
|
+
submit actions target a form inside the body with the native `form` attribute.
|
|
676
|
+
|
|
677
|
+
```astro
|
|
678
|
+
<Dialog id="record-dialog" aria-labelledby="record-title">
|
|
679
|
+
<DialogHeader><DialogTitle id="record-title">Edit record</DialogTitle></DialogHeader>
|
|
680
|
+
<DialogBody><Form id="record-form"><Input name="name" aria-label="Name" /></Form></DialogBody>
|
|
681
|
+
<DialogFooter>
|
|
682
|
+
<DialogClose variant="outline">Cancel</DialogClose>
|
|
683
|
+
<Button type="submit" form="record-form">Save</Button>
|
|
684
|
+
</DialogFooter>
|
|
685
|
+
</Dialog>
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
Mount `UIPrimitives` once and open the dialog with a button carrying
|
|
689
|
+
`data-ui-dialog-trigger="record-dialog"`. Set `selectedFilesLabel="{count} files selected"`
|
|
690
|
+
on `FileUpload` to supply localized multiple-file feedback; the single-file label is its filename.
|
|
691
|
+
A trigger ignores its own click when that click arrives canceled (`event.preventDefault()`) or
|
|
692
|
+
when the trigger matches `:disabled` or `[aria-disabled="true"]`, matching close control behavior.
|
|
693
|
+
Register cancellation listeners before the runtime binds the trigger. Activating a trigger for an
|
|
694
|
+
already open dialog preserves its mode and original focus-return target.
|
|
695
|
+
|
|
696
|
+
### Rich description rows
|
|
697
|
+
|
|
698
|
+
Use `Descriptions` with `DescriptionItem`, `DescriptionTerm`, and `DescriptionDetail`
|
|
699
|
+
when a value contains links, badges, formatted dates, or actions. Astro renders a
|
|
700
|
+
native `dl` containing `div`, `dt`, and `dd` elements. The existing `items` array
|
|
701
|
+
remains available and can be combined with child rows.
|
|
702
|
+
|
|
703
|
+
```astro
|
|
704
|
+
<Descriptions>
|
|
705
|
+
<DescriptionItem>
|
|
706
|
+
<DescriptionTerm>Status</DescriptionTerm>
|
|
707
|
+
<DescriptionDetail><Badge variant="success">Active</Badge></DescriptionDetail>
|
|
708
|
+
</DescriptionItem>
|
|
709
|
+
</Descriptions>
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
## Attachment composition
|
|
713
|
+
|
|
714
|
+
Use `AttachmentList` to group native `li` children and `AttachmentPreview` for browser-owned images
|
|
715
|
+
with localized loading, error, and unsupported-file states. Compose independent actions rather
|
|
716
|
+
than nesting controls inside a linked Attachment. The application retains file validation,
|
|
717
|
+
authorization, persistence, and object URL cleanup. See the
|
|
718
|
+
[attachment composition recipe](https://github.com/santi020k/lumen/blob/main/docs/consumer-ui-recipes.md#attachment-previews-and-file-lists)
|
|
719
|
+
for adapter props, slots, child contracts, retry identity, and safe state events.
|
|
720
|
+
|
|
721
|
+
## Chart datum actions
|
|
722
|
+
|
|
723
|
+
Set `drilldown` on BarChart, LineChart, PieChart, ScatterChart, ComboChart, Heatmap, or RangeChart
|
|
724
|
+
and mount `UIPrimitives` once. Each available plotted datum has a corresponding native button in
|
|
725
|
+
the actions disclosure, including when `showTable={false}`. Marks remain decorative to assistive
|
|
726
|
+
technology. The figure emits `ui:chart-datum-activate` with a validated
|
|
727
|
+
`LumenChartDatumActivationDetail`; apps decide whether to navigate, filter, or open a detail view.
|
|
728
|
+
|
|
729
|
+
Translate `labels.exploreData` and `labels.formatDatumAction(context)`, and format visible values
|
|
730
|
+
with the chart's existing formatters. Missing observations have no action; pie actions cover only
|
|
731
|
+
positive slices. A line's `markers="none"` hides visible markers while retaining pointer targets
|
|
732
|
+
and native keyboard actions. See [data visualization](https://github.com/santi020k/lumen/blob/main/docs/data-visualization.md#astro-chart-actions).
|
|
733
|
+
|
|
734
|
+
## Dashboard composition
|
|
735
|
+
|
|
736
|
+
`FilterBar` groups host-owned filtering controls, active criteria, reset actions, and a polite
|
|
737
|
+
result announcement. `ChangeSummary` presents explicit before/after values and application-owned
|
|
738
|
+
changed state. Neither component owns requests, persistence, parsing, or financial policy.
|
|
739
|
+
|
|
740
|
+
ScatterChart supports independent X/Y formatting, explicit domains, logarithmic positive X values,
|
|
741
|
+
and labeled reference lines/regions. Automatic domains leave room for complete bubbles; explicit
|
|
742
|
+
domain limits stay exact and can intentionally crop marks. ComboChart and RangeChart include
|
|
743
|
+
category labels and value scales. See [consumer UI recipes](https://github.com/santi020k/lumen/blob/main/docs/consumer-ui-recipes.md)
|
|
744
|
+
for dashboard tables, freshness, import review, activity inbox, and persistent Kanban patterns.
|
|
745
|
+
|
|
746
|
+
### Actual-versus-target charts
|
|
747
|
+
|
|
748
|
+
`BulletChart` compares a nullable actual `value` with a finite `target` and optional
|
|
749
|
+
labeled `ranges`. A strong actual bar, target marker, readable value labels, and expandable exact
|
|
750
|
+
data work together. Domains include zero and all measurements; invalid inputs fail closed, including malformed range containers.
|
|
751
|
+
Null values stay distinct from zero. See the [chart guide](https://github.com/santi020k/lumen/blob/main/docs/data-visualization.md#actual-values-and-targets)
|
|
752
|
+
for the input, localization, and domain contracts.
|
|
753
|
+
|
|
754
|
+
### Rankings and paired comparisons
|
|
755
|
+
|
|
756
|
+
Use `LollipopChart` for zero-based rankings and `DumbbellChart` for paired measurements (native
|
|
757
|
+
`LumenLollipopChart` and `LumenDumbbellChart`). Supply ordered comparison data with `id`, `label`,
|
|
758
|
+
nullable `value`, optional nullable `reference`, and optional `tone`. Both charts preserve missing
|
|
759
|
+
values and expose exact data. See the [shared visualization contract](https://github.com/santi020k/lumen/blob/main/docs/data-visualization.md#rankings-and-paired-comparisons).
|
|
760
|
+
|
|
761
|
+
### Calendars, funnels, and distributions
|
|
762
|
+
|
|
763
|
+
Use `CalendarHeatmap` for daily date-only observations with an explicit start/end range,
|
|
764
|
+
`FunnelChart` for ordered nonnegative stages, and `BoxPlot` for precomputed quartiles, whiskers,
|
|
765
|
+
and outliers. All retain missing values and expose exact data. See the
|
|
766
|
+
[data visualization guide](https://github.com/santi020k/lumen/blob/main/docs/data-visualization.md#calendars-funnels-and-box-plots).
|
|
767
|
+
|
|
768
|
+
Media controllers for ImageComparison and FileUpload load only when matching components are present.
|
|
769
|
+
Keep mounting `UIPrimitives` once; no additional consumer setup is required. Image comparisons
|
|
770
|
+
follow their current native form owner for reset and honor canceled resets. Reinitialize after
|
|
771
|
+
document adoption to register destination reset delegation without duplicate input listeners.
|
|
772
|
+
|
|
773
|
+
## Visual interactions and product blocks
|
|
774
|
+
|
|
775
|
+
See [visual interactions](https://github.com/santi020k/lumen/blob/main/docs/visual-interactions.md) for keyed motion, semantic effects,
|
|
776
|
+
chart continuity, AI surfaces, optional SDK integrations, and the four installable product recipes.
|
|
777
|
+
Import `@santi020k/lumen/styles/motion.css` alongside the base stylesheet to opt into native
|
|
778
|
+
disclosure height transitions and the CSS reduction scope. This small optional stylesheet works
|
|
779
|
+
with Astro, React, and Elements and keeps those effects out of the default stylesheet. The presence
|
|
780
|
+
helper's system and local reduced-motion checks work without this CSS import.
|
|
781
|
+
|
|
782
|
+
## Device demonstrations
|
|
783
|
+
|
|
784
|
+
`DeviceFrame` presents slotted HTML, an image, or a titled iframe inside `macbook-pro`, `macbook-air`, `imac`,
|
|
785
|
+
`iphone`, `pixel`, and `ipad-pro` frames, with generic `laptop`, `desktop`, `android`, and `tablet` options.
|
|
786
|
+
Device-specific enclosures include a MacBook Pro display notch and full front edge, a tapered MacBook Air deck, curved iMac
|
|
787
|
+
stand and chin, rounded phone glass with separate rails and buttons, and an iPad Pro with even
|
|
788
|
+
bezels and no Home button. The generic `tablet` retains its classic enclosure.
|
|
789
|
+
Shells are decorative and do not emulate device hardware. `orientation` selects portrait or landscape; `tone` selects
|
|
790
|
+
light or dark chrome independently of the screen content. Use `color="white"`,
|
|
791
|
+
`color="black"`, or a 3-, 4-, 6-, or 8-digit hex color such as `color="#a9b8ac"` for
|
|
792
|
+
a custom hardware finish. `color` takes precedence over `tone`; invalid values fall back to the
|
|
793
|
+
tone. The finish stays independent of the content theme. For CSS-driven updates, set
|
|
794
|
+
`--ui-device-color` to a CSS color on the frame.
|
|
795
|
+
|
|
796
|
+
Iframe layouts use the preset screen viewport and scale to the available width. Override
|
|
797
|
+
`screenWidth` and `screenHeight` for a custom viewport (1–16384 CSS pixels). Slotted HTML shares
|
|
798
|
+
the host viewport; container queries can adapt it to the screen. Images preserve their proportions.
|
|
799
|
+
`scroll={false}` clips HTML overflow; an iframe manages its own scrolling.
|
|
800
|
+
|
|
801
|
+
Supply image alternative text and iframe titles. Consumers own iframe `sandbox`, `allow`,
|
|
802
|
+
loading, and referrer policies. Remote sites can refuse embedding through their response headers.
|
|
803
|
+
The decorative shell does not alter focus or intercept interactions. Camera and home-indicator
|
|
804
|
+
details occupy separate chrome outside live HTML and iframe viewports. Direct phone images extend
|
|
805
|
+
under the decorative camera and home indicator for a full-bleed presentation.
|
|
806
|
+
Screen presets are 1280 × 800 for MacBook Pro and MacBook Air, 1440 × 810 for iMac, 390 × 844 for iPhone,
|
|
807
|
+
412 × 915 for Pixel, and 834 × 1194 for iPad Pro (1194 × 834 in landscape). These are demonstration
|
|
808
|
+
viewports, not physical display specifications.
|
|
809
|
+
|
|
810
|
+
```astro
|
|
811
|
+
---
|
|
812
|
+
import { DeviceFrame } from '@santi020k/lumen-astro'
|
|
813
|
+
---
|
|
814
|
+
<DeviceFrame device="iphone">
|
|
815
|
+
<iframe src="/demo" title="Mobile application demo" loading="lazy"></iframe>
|
|
816
|
+
</DeviceFrame>
|
|
817
|
+
```
|
|
818
|
+
|
|
819
|
+
The component bundles its resize behavior; `UIPrimitives` is not required for this frame.
|
|
820
|
+
|
|
821
|
+
## World map
|
|
822
|
+
|
|
823
|
+
WorldMap supports highlighted countries, location markers, dotted or solid styles, country selection,
|
|
824
|
+
and theme customization. Use `initialView="highlighted"` (Elements: `initial-view`) to start with a
|
|
825
|
+
regional view. Zoom toward the cursor with Ctrl/Cmd-scroll, or fit highlighted countries using the
|
|
826
|
+
map controls. Adopted maps emit selection events in their current document; reinitialization follows
|
|
827
|
+
interaction mode changes without duplicating listeners or resetting zoom. Import geography explicitly from
|
|
828
|
+
`@santi020k/lumen-core/world-map-data`; it is excluded from root exports. See the
|
|
829
|
+
[WorldMap usage guide](https://github.com/santi020k/lumen/blob/main/docs/world-map.md) for adapter examples, events, localization,
|
|
830
|
+
accessibility, and customization.
|
|
831
|
+
|
|
832
|
+
## Studio media workspace
|
|
833
|
+
|
|
834
|
+
Compose MediaViewport, MediaThumbnail, MediaFilmstrip and ImageComparison modes with the
|
|
835
|
+
[Studio media workspace recipes](https://github.com/santi020k/lumen/blob/main/docs/studio-media-workspaces.md). Applications retain
|
|
836
|
+
media loading, selection, adjustment algorithms, processing, export and persistence.
|
|
837
|
+
|
|
838
|
+
## Resources
|
|
839
|
+
|
|
840
|
+
| Guide | What you will find |
|
|
841
|
+
| --- | --- |
|
|
842
|
+
| [Styling contract](https://github.com/santi020k/lumen/blob/main/docs/styling-contract.md) | Stable styling parts, component variables, and overrides. |
|
|
843
|
+
| [Error handling](https://github.com/santi020k/lumen/blob/main/docs/error-handling.md) | Field feedback, summaries, alerts, and recovery surfaces. |
|
|
844
|
+
| [Contributing](https://github.com/santi020k/lumen/blob/main/CONTRIBUTING.md) | Setup, checks, and contribution workflow. |
|
|
845
|
+
| [Release history](https://github.com/santi020k/lumen/releases) | Published releases and version notes. |
|
|
846
|
+
|
|
847
|
+
Part of [Lumen UI](https://lumen.santi020k.com), created by [Santiago Molina](https://santi020k.com).
|
|
848
|
+
Licensed under [MIT](https://github.com/santi020k/lumen/blob/main/LICENSE); third-party artwork retains its own notices.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
3
|
+
|
|
4
|
+
import { formatLumenAmountDraft, getLumenAmountValue, type LumenAmountOptions, resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
5
|
+
|
|
6
|
+
interface Props extends Omit<HTMLAttributes<'input'>, 'value' | 'type' | 'min' | 'max' | 'step'>, LumenAmountOptions {
|
|
7
|
+
value?: string
|
|
8
|
+
defaultValue?: string
|
|
9
|
+
invalidMessage?: string
|
|
10
|
+
className?: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const { value, defaultValue, locale = 'en-US', fractionDigits = 2, allowNegative = false, invalidMessage, name, form, disabled, class: classProp = '', className = '', ...rest } = Astro.props
|
|
14
|
+
const initial = value ?? defaultValue ?? ''
|
|
15
|
+
const { classList, passthrough } = resolveLumenAstroProps(rest, ['ui-input', 'ui-amount-field'], classProp, className)
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
<span data-ui-amount-field locale={locale} fraction-digits={fractionDigits} allow-negative={allowNegative ? '' : undefined} value={value} default-value={defaultValue ?? initial} invalid-message={invalidMessage}>
|
|
19
|
+
<input {...passthrough} class:list={classList} data-ui-amount-input type="text" inputmode="decimal" value={formatLumenAmountDraft(initial, { locale, fractionDigits, allowNegative })} form={form} disabled={disabled} />
|
|
20
|
+
<input data-ui-amount-value type="hidden" name={name} form={form} disabled={disabled} value={getLumenAmountValue(initial) ?? ''} />
|
|
21
|
+
</span>
|
|
@@ -28,7 +28,7 @@ const {
|
|
|
28
28
|
...rest
|
|
29
29
|
} = Astro.props
|
|
30
30
|
|
|
31
|
-
const safeDecimals = Math.max(0, Math.min(20, Math.floor(decimals)))
|
|
31
|
+
const safeDecimals = Math.max(0, Math.min(20, (Math.floor(decimals) || 0)))
|
|
32
32
|
|
|
33
33
|
const formatter = new Intl.NumberFormat(locale, {
|
|
34
34
|
maximumFractionDigits: safeDecimals,
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
3
|
+
|
|
4
|
+
import type { LumenApprovalStatus } from '@santi020k/lumen-core'
|
|
5
|
+
|
|
6
|
+
import Button from './Button.astro'
|
|
7
|
+
import Card from './Card.astro'
|
|
8
|
+
import Stack from './Stack.astro'
|
|
9
|
+
|
|
10
|
+
interface Props extends HTMLAttributes<'div'> {
|
|
11
|
+
approveLabel?: string
|
|
12
|
+
disabled?: boolean
|
|
13
|
+
label: string
|
|
14
|
+
rejectLabel?: string
|
|
15
|
+
requestId: string
|
|
16
|
+
status?: LumenApprovalStatus
|
|
17
|
+
statusLabel: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const { approveLabel = 'Approve', class: className, disabled = false, label, rejectLabel = 'Reject', requestId, status = 'pending', statusLabel, ...rest } = Astro.props
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
<Card {...rest} aria-label={label} class:list={['ui-approval-card', className]} data-disabled={String(disabled)} data-ui-approval-card data-request-id={requestId} data-status={status}>
|
|
24
|
+
<Stack gap="group"><strong>{label}</strong><slot /><span role="status">{statusLabel}</span>
|
|
25
|
+
<Stack direction="horizontal" gap="related" wrap>
|
|
26
|
+
<Button data-ui-approval-response="approve" disabled={disabled || status !== 'pending'} type="button">{approveLabel}</Button>
|
|
27
|
+
<Button data-ui-approval-response="reject" disabled={disabled || status !== 'pending'} type="button" variant="secondary">{rejectLabel}</Button>
|
|
28
|
+
</Stack>
|
|
29
|
+
</Stack>
|
|
30
|
+
</Card>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
3
|
+
|
|
4
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
5
|
+
|
|
6
|
+
interface Props extends HTMLAttributes<'ul'> {
|
|
7
|
+
class?: string | null
|
|
8
|
+
className?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const { class: classProp = '', className = '', ...rest } = Astro.props
|
|
12
|
+
const { classList, passthrough } = resolveLumenAstroProps(rest, ['ui-attachment-list'], classProp, className)
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
<ul class:list={classList} data-slot="attachment-list" {...passthrough}><slot /></ul>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
type LumenAttachmentPreviewLabels,
|
|
6
|
+
lumenAttachmentPreviewLabels,
|
|
7
|
+
type LumenAttachmentPreviewState,
|
|
8
|
+
resolveLumenAstroProps,
|
|
9
|
+
resolveLumenAttachmentPreviewState
|
|
10
|
+
} from '@santi020k/lumen-core'
|
|
11
|
+
|
|
12
|
+
interface Props extends HTMLAttributes<'figure'> {
|
|
13
|
+
alt: string
|
|
14
|
+
class?: string | null
|
|
15
|
+
className?: string
|
|
16
|
+
contentType?: string
|
|
17
|
+
labels?: Partial<LumenAttachmentPreviewLabels>
|
|
18
|
+
retryKey?: number | string
|
|
19
|
+
src?: string
|
|
20
|
+
state?: LumenAttachmentPreviewState
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const { alt, class: classProp = '', className = '', contentType, labels, retryKey, src, state: requested, ...rest } = Astro.props
|
|
24
|
+
const state = resolveLumenAttachmentPreviewState(src, contentType, requested)
|
|
25
|
+
const canPreview = resolveLumenAttachmentPreviewState(src, contentType) === 'ready'
|
|
26
|
+
const copy = { ...lumenAttachmentPreviewLabels, ...labels }
|
|
27
|
+
const { classList, passthrough } = resolveLumenAstroProps(rest, ['ui-attachment-preview'], classProp, className)
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
<figure
|
|
31
|
+
class:list={classList}
|
|
32
|
+
{...passthrough}
|
|
33
|
+
aria-busy={state === 'loading'}
|
|
34
|
+
data-state={state}
|
|
35
|
+
data-ui-attachment-preview
|
|
36
|
+
data-ui-attachment-preview-state={requested}
|
|
37
|
+
data-ui-attachment-preview-content-type={contentType}
|
|
38
|
+
data-ui-attachment-preview-retry-key={retryKey}
|
|
39
|
+
data-ui-attachment-preview-error-label={copy.error}
|
|
40
|
+
data-ui-attachment-preview-loading-label={copy.loading}
|
|
41
|
+
data-ui-attachment-preview-unavailable-label={copy.unavailable}
|
|
42
|
+
>
|
|
43
|
+
<div data-slot="attachment-preview-media" hidden={state !== 'ready'}>
|
|
44
|
+
{/* Browser-owned private URLs and object URLs must not enter Astro's server image optimizer. */}
|
|
45
|
+
{canPreview && <img src={src} alt={alt} data-ui-attachment-preview-image loading="eager" />}
|
|
46
|
+
</div>
|
|
47
|
+
<p role="status" data-slot="attachment-preview-fallback" data-ui-attachment-preview-message hidden={state === 'ready'}>{state === 'ready' ? '' : copy[state]}</p>
|
|
48
|
+
{Astro.slots.has('caption') && <figcaption><slot name="caption" /></figcaption>}
|
|
49
|
+
<slot />
|
|
50
|
+
{Astro.slots.has('actions') && <div data-slot="attachment-preview-actions"><slot name="actions" /></div>}
|
|
51
|
+
</figure>
|
package/components/Avatar.astro
CHANGED
|
@@ -30,6 +30,8 @@ const { classList, passthrough } = resolveLumenAstroProps(rest, [
|
|
|
30
30
|
|
|
31
31
|
<span
|
|
32
32
|
class:list={classList}
|
|
33
|
+
role={!src && alt ? 'img' : undefined}
|
|
34
|
+
aria-label={!src && alt ? alt : undefined}
|
|
33
35
|
{...passthrough}
|
|
34
36
|
>
|
|
35
37
|
{src ? <img alt={alt} src={src} /> : fallbackText && <span aria-hidden={fallback ? undefined : 'true'}>{fallbackText}</span>}
|