@santi020k/lumen-astro 1.7.0-rc.0 → 1.8.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 CHANGED
@@ -9,6 +9,13 @@ configuration is required to render the components.
9
9
  pnpm add @santi020k/lumen-astro
10
10
  ```
11
11
 
12
+ The adapter also exposes Lumen's discovery and diagnostics CLI:
13
+
14
+ ```bash
15
+ pnpm exec lumen show Tabs
16
+ pnpm exec lumen doctor
17
+ ```
18
+
12
19
  Import the CSS once in your root layout and mount `UIPrimitives` once in that same app shell if you
13
20
  use interactive components such as dialogs, menus, popovers, tabs, carousels, toggles, command
14
21
  lists, or toasts. Do not add `UIPrimitives` beside each component instance; one root include
@@ -18,6 +25,11 @@ enhances all matching Lumen markup on the page.
18
25
  @import "@santi020k/lumen-astro/styles.css";
19
26
  ```
20
27
 
28
+ Applications using the essential forms, feedback, tabs, dialogs, calendar, and data-table surface
29
+ can instead load `@santi020k/lumen-astro/styles/critical.css`. The generated entry is about 50 KiB
30
+ raw versus 170 KiB for the complete catalog; switch to `styles.css` when using components outside
31
+ that documented critical set.
32
+
21
33
  The stylesheet defaults `--ui-font` to `"Montserrat", "Avenir Next", "Segoe UI", sans-serif`.
22
34
  It declares the family stack but does not bundle or load font files. Load Montserrat once through
23
35
  your preferred delivery path, or override `--ui-font` in application CSS.
@@ -32,7 +44,7 @@ With Tailwind, keep the Lumen import in the same shared CSS entry:
32
44
 
33
45
  ```astro
34
46
  ---
35
- import { UIPrimitives } from '@santi020k/lumen-astro'
47
+ import UIPrimitives from '@santi020k/lumen-astro/runtime'
36
48
  ---
37
49
 
38
50
  <UIPrimitives />
@@ -52,8 +64,7 @@ import { Button, Card, Input } from '@santi020k/lumen-astro'
52
64
  ```
53
65
 
54
66
  `Input` and `NativeSelect` preserve the native numeric `size` attribute. Use `visualSize="sm"` or
55
- `visualSize="lg"` for presentation. The pre-1.0 `size="sm|lg"` visual alias remains available for
56
- incremental migrations, but new code should keep native behavior and visual styling separate.
67
+ `visualSize="lg"` for presentation so native behavior and visual styling remain separate.
57
68
 
58
69
  ```astro
59
70
  <Input size={32} visualSize="sm" />
@@ -65,6 +76,9 @@ incremental migrations, but new code should keep native behavior and visual styl
65
76
  metadata-backed validation, automatic country detection for pasted international numbers, and the
66
77
  `ui:phone-change` event with a `LumenPhoneNumber` detail.
67
78
 
79
+ The phone metadata and normalization controller are selector-loaded only when a rendered page
80
+ contains `PhoneInput`; pages without the component do not evaluate or download that controller.
81
+
68
82
  ```astro
69
83
  <PhoneInput countryValue="CO" locale="en-US" name="hospitalPhone" />
70
84
  ```
@@ -75,6 +89,10 @@ Popover, dropdown menu, tabs, and tooltip parts expose the DOM and ARIA contract
75
89
  shared progressive-enhancement runtime. Prefer these parts over recreating roles and `data-ui-*`
76
90
  attributes by hand.
77
91
 
92
+ Tabs keep the selected trigger visible when a narrow tab list scrolls horizontally and emit a
93
+ typed `ui:tabs-change` event. Import `LumenTabsChangeDetail` or `LumenTabsChangeEvent` from this
94
+ package when application behavior follows the selected value.
95
+
78
96
  ```astro
79
97
  ---
80
98
  import {
@@ -180,6 +198,22 @@ const errors = result?.error && isInputError(result.error)
180
198
 
181
199
  See the [Astro Actions form guide](https://lumen.santi020k.com/docs/forms/astro-actions).
182
200
 
201
+ ## Error states
202
+
203
+ Use `ErrorState` when a page or region cannot show its primary content. Pass recovery controls
204
+ through the `actions` slot; the application still owns retry and logging behavior. Static states are
205
+ not live regions by default, so set `announce="polite"` only when a newly rendered failure needs an
206
+ announcement.
207
+
208
+ ```astro
209
+ <ErrorState title="Could not load projects" description="Check your connection and try again.">
210
+ <Button slot="actions">Try again</Button>
211
+ </ErrorState>
212
+ ```
213
+
214
+ See the repository [Astro error-handling guide](../../docs/error-handling.md#astro) for the complete
215
+ example, retry ownership, announcement behavior, and verification guidance.
216
+
183
217
  Use `Icon` for Lucide icons by name across framework adapters.
184
218
 
185
219
  ```astro
package/bin/lumen.mjs ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '@santi020k/lumen/cli'
@@ -0,0 +1,118 @@
1
+ ---
2
+ import type { HTMLAttributes } from 'astro/types'
3
+
4
+ import {
5
+ type LumenErrorStateAnnouncement,
6
+ type LumenErrorStateKind,
7
+ type LumenErrorStateLayout,
8
+ resolveLumenAstroProps
9
+ } from '@santi020k/lumen-core'
10
+
11
+ import Illustration from './Illustration.astro'
12
+
13
+ type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6
14
+
15
+ const headingTags = {
16
+ 1: 'h1',
17
+ 2: 'h2',
18
+ 3: 'h3',
19
+ 4: 'h4',
20
+ 5: 'h5',
21
+ 6: 'h6'
22
+ } as const
23
+
24
+ const resolveAnnouncementRole = (
25
+ announce: LumenErrorStateAnnouncement,
26
+ role: Props['role']
27
+ ): Props['role'] => {
28
+ if (role) return role
29
+
30
+ if (announce === 'assertive') return 'alert'
31
+
32
+ if (announce === 'polite') return 'status'
33
+
34
+ return undefined
35
+ }
36
+
37
+ interface Props extends HTMLAttributes<'section'> {
38
+ announce?: LumenErrorStateAnnouncement
39
+ class?: string | null
40
+ className?: string
41
+ description?: string
42
+ headingLevel?: HeadingLevel
43
+ kind?: LumenErrorStateKind
44
+ layout?: LumenErrorStateLayout
45
+ reference?: string
46
+ referenceLabel?: string
47
+ showGraphic?: boolean
48
+ title: string
49
+ }
50
+
51
+ const {
52
+ 'aria-live': ariaLive,
53
+ announce = 'off',
54
+ class: classProp = '',
55
+ className = '',
56
+ description,
57
+ headingLevel = 2,
58
+ id,
59
+ kind = 'error',
60
+ layout = 'default',
61
+ reference,
62
+ referenceLabel = 'Reference',
63
+ role,
64
+ showGraphic = true,
65
+ title,
66
+ ...rest
67
+ } = Astro.props
68
+
69
+ const Heading = headingTags[headingLevel]
70
+ const titleId = id ? `${id}-title` : undefined
71
+ const resolvedLive = ariaLive ?? (announce === 'off' ? undefined : announce)
72
+ const resolvedRole = resolveAnnouncementRole(announce, role)
73
+
74
+ const { classList, passthrough } = resolveLumenAstroProps(rest, [
75
+ 'ui-error-state',
76
+ `ui-error-state--${kind}`,
77
+ `ui-error-state--${layout}`
78
+ ], classProp, className)
79
+ ---
80
+
81
+ <section
82
+ aria-label={titleId ? undefined : title}
83
+ aria-labelledby={titleId}
84
+ aria-live={resolvedLive}
85
+ class:list={classList}
86
+ data-kind={kind}
87
+ data-layout={layout}
88
+ data-ui-error-state
89
+ id={id}
90
+ role={resolvedRole}
91
+ {...passthrough}
92
+ >
93
+ {showGraphic && (
94
+ <div class="ui-error-state__graphic" data-slot="error-state-graphic" aria-hidden="true">
95
+ {Astro.slots.has('graphic') ?
96
+ (<slot name="graphic" />) :
97
+ (
98
+ <Illustration
99
+ size={layout === 'compact' ? 'sm' : 'md'}
100
+ variant={kind}
101
+ />
102
+ )}
103
+ </div>
104
+ )}
105
+ <div class="ui-error-state__content" data-slot="error-state-content">
106
+ <Heading class="ui-error-state__title" data-slot="error-state-title" id={titleId}>{title}</Heading>
107
+ {description && <p class="ui-error-state__description" data-slot="error-state-description">{description}</p>}
108
+ {Astro.slots.has('default') && <div class="ui-error-state__details" data-slot="error-state-details"><slot /></div>}
109
+ {reference && (
110
+ <p class="ui-error-state__reference" data-slot="error-state-reference">
111
+ <span>{referenceLabel}:</span> <code>{reference}</code>
112
+ </p>
113
+ )}
114
+ </div>
115
+ {Astro.slots.has('actions') && (
116
+ <div class="ui-error-state__actions" data-slot="error-state-actions"><slot name="actions" /></div>
117
+ )}
118
+ </section>
@@ -19,9 +19,7 @@ const {
19
19
  ...rest
20
20
  } = Astro.props
21
21
 
22
- const legacyVisualSize = size === 'default' || size === 'lg' || size === 'sm' ? size : undefined
23
- const resolvedVisualSize = visualSize ?? legacyVisualSize ?? 'default'
24
- const nativeSize = legacyVisualSize ? undefined : size
22
+ const resolvedVisualSize = visualSize ?? 'default'
25
23
 
26
24
  const { classList, passthrough } = resolveLumenAstroProps(rest, [
27
25
  'ui-input',
@@ -32,7 +30,7 @@ const { classList, passthrough } = resolveLumenAstroProps(rest, [
32
30
 
33
31
  <input
34
32
  class:list={classList}
35
- size={nativeSize}
33
+ size={size}
36
34
  type={type}
37
35
  {...passthrough}
38
36
  />
@@ -32,15 +32,13 @@ const {
32
32
 
33
33
  const hasValue = Object.hasOwn(rest, 'value')
34
34
  const normalizedOptions = options.map(option => typeof option === 'string' ? { label: option, value: option } : option)
35
- const legacyVisualSize = size === 'default' || size === 'lg' || size === 'sm' ? size : undefined
36
- const resolvedVisualSize = visualSize ?? legacyVisualSize ?? 'default'
37
- const nativeSize = legacyVisualSize ? undefined : size
35
+ const resolvedVisualSize = visualSize ?? 'default'
38
36
 
39
37
  const { classList, passthrough } = resolveLumenAstroProps(rest, ['ui-select', resolvedVisualSize === 'sm' && 'ui-select--sm', resolvedVisualSize === 'lg' && 'ui-select--lg'
40
38
  ], classProp, className)
41
39
  ---
42
40
 
43
- <select class:list={classList} size={nativeSize} {...passthrough}>
41
+ <select class:list={classList} size={size} {...passthrough}>
44
42
  {placeholder && <option disabled selected={!hasValue} value="">{placeholder}</option>}
45
43
  <slot />
46
44
  {normalizedOptions.map(option => (
@@ -21,14 +21,14 @@ const {
21
21
  } = Astro.props
22
22
 
23
23
  const { classList, passthrough } = resolveLumenAstroProps(rest, [
24
- 'ui-sonner'
24
+ 'ui-tvp'
25
25
  ], classProp, className)
26
26
  ---
27
27
 
28
28
  <div
29
29
  aria-atomic={ariaAtomic}
30
30
  aria-live={ariaLive}
31
- data-ui-sonner
31
+ data-ui-toast-viewport
32
32
  data-ui-toast-max={maxCount}
33
33
  data-placement={placement}
34
34
  class:list={classList}
package/index.ts CHANGED
@@ -58,6 +58,7 @@ export { default as DropdownMenuItem } from './components/DropdownMenuItem.astro
58
58
  export { default as DropdownMenuSeparator } from './components/DropdownMenuSeparator.astro'
59
59
  export { default as DropdownMenuTrigger } from './components/DropdownMenuTrigger.astro'
60
60
  export { default as Empty } from './components/Empty.astro'
61
+ export { default as ErrorState } from './components/ErrorState.astro'
61
62
  export { default as ErrorSummary } from './components/ErrorSummary.astro'
62
63
  export { default as Eyebrow } from './components/Eyebrow.astro'
63
64
  export { default as Field } from './components/Field.astro'
@@ -129,7 +130,6 @@ export { default as Sidebar } from './components/Sidebar.astro'
129
130
  export { default as Skeleton } from './components/Skeleton.astro'
130
131
  export { default as SkipLink } from './components/SkipLink.astro'
131
132
  export { default as Slider } from './components/Slider.astro'
132
- export { default as Sonner } from './components/Sonner.astro'
133
133
  export { default as Sparkline } from './components/Sparkline.astro'
134
134
  export { default as SpeedDial } from './components/SpeedDial.astro'
135
135
  export { default as Spinner } from './components/Spinner.astro'
@@ -155,6 +155,7 @@ export { default as TimeField } from './components/TimeField.astro'
155
155
  export { default as Timeline } from './components/Timeline.astro'
156
156
  export { default as TimelineItem } from './components/TimelineItem.astro'
157
157
  export { default as Toast } from './components/Toast.astro'
158
+ export { default as ToastViewport } from './components/ToastViewport.astro'
158
159
  export { default as Toggle } from './components/Toggle.astro'
159
160
  export { default as ToggleGroup } from './components/ToggleGroup.astro'
160
161
  export { default as Toolbar } from './components/Toolbar.astro'
@@ -174,4 +175,7 @@ export {
174
175
  type LumenControlIdMap,
175
176
  normalizeAstroActionErrors
176
177
  } from './forms.ts'
177
- export { default as UIPrimitives } from './runtime/UIPrimitives.astro'
178
+ export type {
179
+ LumenTabsChangeDetail,
180
+ LumenTabsChangeEvent
181
+ } from '@santi020k/lumen-core'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@santi020k/lumen-astro",
3
- "version": "1.7.0-rc.0",
3
+ "version": "1.8.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -8,6 +8,7 @@
8
8
  "type": "module",
9
9
  "sideEffects": [
10
10
  "./styles/lumen.css",
11
+ "./styles/critical.css",
11
12
  "./styles.css"
12
13
  ],
13
14
  "types": "./index.ts",
@@ -24,9 +25,11 @@
24
25
  "./runtime": "./runtime/UIPrimitives.astro",
25
26
  "./layers.css": "./styles/layers.css",
26
27
  "./styles.css": "./styles/lumen.css",
28
+ "./styles/critical.css": "./styles/critical.css",
27
29
  "./package.json": "./package.json"
28
30
  },
29
31
  "files": [
32
+ "bin",
30
33
  "components",
31
34
  "runtime",
32
35
  "styles",
@@ -35,10 +38,13 @@
35
38
  "README.md",
36
39
  "LICENSE"
37
40
  ],
41
+ "bin": {
42
+ "lumen": "./bin/lumen.mjs"
43
+ },
38
44
  "dependencies": {
39
45
  "uqr": "^0.1.3",
40
- "@santi020k/lumen-core": "^1.7.0-rc.0",
41
- "@santi020k/lumen": "^1.7.0-rc.0"
46
+ "@santi020k/lumen": "^1.8.0",
47
+ "@santi020k/lumen-core": "^1.8.0"
42
48
  },
43
49
  "devDependencies": {
44
50
  "@astrojs/ts-plugin": "^1.10.11",