@santi020k/lumen-astro 3.0.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +403 -7
  2. package/components/AmountField.astro +21 -0
  3. package/components/AnimatedNumber.astro +1 -1
  4. package/components/ApprovalCard.astro +30 -0
  5. package/components/AttachmentList.astro +15 -0
  6. package/components/AttachmentPreview.astro +51 -0
  7. package/components/Avatar.astro +2 -0
  8. package/components/BarChart.astro +95 -31
  9. package/components/BoxPlot.astro +77 -0
  10. package/components/Breadcrumb.astro +2 -1
  11. package/components/BulletChart.astro +64 -0
  12. package/components/Button.astro +1 -1
  13. package/components/Calendar.astro +54 -65
  14. package/components/CalendarHeatmap.astro +76 -0
  15. package/components/Card.astro +4 -0
  16. package/components/ChangeSummary.astro +36 -0
  17. package/components/ChartDatumActions.astro +24 -0
  18. package/components/ChartMotion.astro +11 -0
  19. package/components/Code.astro +18 -3
  20. package/components/CodeTabs.astro +12 -0
  21. package/components/ComboChart.astro +93 -11
  22. package/components/CountryFlag.astro +23 -0
  23. package/components/DataTable.astro +15 -7
  24. package/components/DatePicker.astro +24 -17
  25. package/components/DescriptionDetail.astro +18 -0
  26. package/components/DescriptionItem.astro +18 -0
  27. package/components/DescriptionTerm.astro +18 -0
  28. package/components/DeviceFrame.astro +79 -0
  29. package/components/DialogBody.astro +20 -0
  30. package/components/DialogClose.astro +21 -0
  31. package/components/DialogFooter.astro +20 -0
  32. package/components/DialogHeader.astro +20 -0
  33. package/components/DialogTitle.astro +21 -0
  34. package/components/DumbbellChart.astro +8 -0
  35. package/components/FileUpload.astro +3 -1
  36. package/components/FilterBar.astro +25 -0
  37. package/components/FunnelChart.astro +50 -0
  38. package/components/Grid.astro +2 -2
  39. package/components/Heatmap.astro +61 -12
  40. package/components/Histogram.astro +30 -0
  41. package/components/Icon.astro +7 -3
  42. package/components/ImageComparison.astro +74 -0
  43. package/components/Input.astro +2 -2
  44. package/components/LineChart.astro +127 -67
  45. package/components/LollipopChart.astro +8 -0
  46. package/components/MediaFilmstrip.astro +19 -0
  47. package/components/MediaThumbnail.astro +29 -0
  48. package/components/MediaViewport.astro +38 -0
  49. package/components/Mentions.astro +2 -1
  50. package/components/MessageScroller.astro +6 -0
  51. package/components/MotionGroup.astro +19 -0
  52. package/components/NativeSelect.astro +2 -2
  53. package/components/Pagination.astro +2 -1
  54. package/components/PasswordField.astro +1 -1
  55. package/components/PhoneInput.astro +60 -9
  56. package/components/PhoneNumber.astro +19 -0
  57. package/components/PieChart.astro +26 -3
  58. package/components/PromptComposer.astro +36 -0
  59. package/components/RangeChart.astro +38 -8
  60. package/components/ScatterChart.astro +62 -14
  61. package/components/Segmented.astro +5 -5
  62. package/components/Select.astro +8 -8
  63. package/components/SourceCitation.astro +18 -0
  64. package/components/Sparkline.astro +9 -10
  65. package/components/Stack.astro +2 -2
  66. package/components/StreamMessage.astro +26 -0
  67. package/components/Tabs.astro +3 -0
  68. package/components/ToolActivity.astro +17 -0
  69. package/components/TreeSelect.astro +1 -0
  70. package/components/VirtualList.astro +5 -2
  71. package/components/VisualEffect.astro +21 -0
  72. package/components/WaterfallChart.astro +27 -0
  73. package/components/WorldMap.astro +213 -0
  74. package/forms.ts +17 -4
  75. package/index.ts +37 -0
  76. package/internal/ChartInspection.astro +27 -0
  77. package/internal/ComparisonChart.astro +69 -0
  78. package/internal/IntervalChart.astro +66 -0
  79. package/package.json +6 -4
  80. package/runtime/UIPrimitives.astro +670 -647
  81. package/runtime/chart-actions.ts +19 -0
  82. package/runtime/controllers/amount-field.ts +12 -0
  83. package/runtime/controllers/attachments.ts +13 -0
  84. package/runtime/controllers/chart-activation.ts +33 -0
  85. package/runtime/controllers/charts.ts +33 -0
  86. package/runtime/controllers/combobox.ts +39 -0
  87. package/runtime/controllers/comparison-reset.ts +20 -0
  88. package/runtime/controllers/data-table.ts +142 -0
  89. package/runtime/controllers/dialogs.ts +32 -32
  90. package/runtime/controllers/document-navigation.ts +54 -22
  91. package/runtime/controllers/file-upload.ts +89 -0
  92. package/runtime/controllers/image-comparison.ts +53 -0
  93. package/runtime/controllers/media-selection.ts +20 -0
  94. package/runtime/controllers/media-viewport.ts +54 -0
  95. package/runtime/controllers/media-workspace.ts +8 -0
  96. package/runtime/controllers/message-scroller.ts +13 -0
  97. package/runtime/controllers/motion.ts +15 -16
  98. package/runtime/controllers/optional-media.ts +29 -0
  99. package/runtime/controllers/phone-input.ts +128 -39
  100. package/runtime/controllers/visual-interactions.ts +75 -0
  101. package/runtime/controllers/world-map.ts +154 -0
  102. package/styles/critical.css +634 -61
  103. package/styles/lumen.css +101 -0
@@ -57,16 +57,15 @@ const endpoint = geometry.points[geometry.points.length - 1]
57
57
  ))
58
58
  }
59
59
  <path class="ui-sparkline__line" d={geometry.path} />
60
- {
61
- showEndpoint && endpoint && (
62
- <circle
63
- class="ui-sparkline__endpoint"
64
- cx={endpoint.xCoordinate}
65
- cy={endpoint.yCoordinate}
66
- r="2.5"
67
- />
68
- )
69
- }
70
60
  </svg>
61
+ {
62
+ showEndpoint && endpoint && (
63
+ <span
64
+ aria-hidden="true"
65
+ class="ui-sparkline__endpoint"
66
+ style={{ left: `${endpoint.xCoordinate / 120 * 100}%`, top: `${endpoint.yCoordinate / 40 * 100}%` }}
67
+ />
68
+ )
69
+ }
71
70
  <span class="ui-sr-only">{label}</span>
72
71
  </span>
@@ -9,7 +9,7 @@ interface Props extends HTMLAttributes<'div'> {
9
9
  class?: string | null
10
10
  className?: string
11
11
  direction?: 'horizontal' | 'vertical'
12
- gap?: 'lg' | 'md' | 'none' | 'sm' | 'xl'
12
+ gap?: '2xl' | '3xl' | 'group' | 'lg' | 'md' | 'none' | 'related' | 'section' | 'sm' | 'xl' | 'xs'
13
13
  justify?: 'between' | 'center' | 'end' | 'start'
14
14
  wrap?: boolean
15
15
  }
@@ -20,7 +20,7 @@ const {
20
20
  class: classProp = '',
21
21
  className = '',
22
22
  direction = 'vertical',
23
- gap = 'md',
23
+ gap = 'group',
24
24
  justify = 'start',
25
25
  wrap = false,
26
26
  ...rest
@@ -0,0 +1,26 @@
1
+ ---
2
+ import type { HTMLAttributes } from 'astro/types'
3
+
4
+ import type { LumenStreamStatus } from '@santi020k/lumen-core'
5
+
6
+ import Message from './Message.astro'
7
+ import Prose from './Prose.astro'
8
+ import Stack from './Stack.astro'
9
+
10
+ interface Props extends HTMLAttributes<'article'> {
11
+ label?: string
12
+ status?: LumenStreamStatus
13
+ statusLabel: string
14
+ }
15
+
16
+ const { class: className, label = 'Assistant', status = 'idle', statusLabel, ...rest } = Astro.props
17
+ ---
18
+
19
+ <Message {...rest} aria-label={label} class:list={['ui-stream-message', className]} data-status={status} from="assistant">
20
+ <Prose aria-busy={status === 'streaming'} aria-live="off" data-ui-stream-content><slot /></Prose>
21
+ <Stack direction="horizontal" gap="related" wrap>
22
+ <span aria-live="polite" role="status">{statusLabel}</span>
23
+ <slot name="actions" />
24
+ </Stack>
25
+ <slot name="sources" />
26
+ </Message>
@@ -7,6 +7,7 @@ interface Props extends HTMLAttributes<'div'> {
7
7
  class?: string | null
8
8
  className?: string
9
9
  glass?: boolean | 'subtle' | 'strong'
10
+ indicator?: boolean
10
11
  initialValue?: string
11
12
  storageKey?: string
12
13
  }
@@ -15,6 +16,7 @@ const {
15
16
  class: classProp = '',
16
17
  className = '',
17
18
  glass = false,
19
+ indicator = false,
18
20
  initialValue,
19
21
  storageKey,
20
22
  ...rest
@@ -29,6 +31,7 @@ const { classList, passthrough } = resolveLumenAstroProps(rest, [
29
31
  ---
30
32
 
31
33
  <div
34
+ data-ui-tab-indicator={indicator || undefined}
32
35
  data-initial-value={initialValue}
33
36
  data-storage-key={storageKey}
34
37
  data-ui-tabs
@@ -0,0 +1,17 @@
1
+ ---
2
+ import type { HTMLAttributes } from 'astro/types'
3
+
4
+ import type { LumenToolStatus } from '@santi020k/lumen-core'
5
+
6
+ import Collapsible from './Collapsible.astro'
7
+ import Stack from './Stack.astro'
8
+
9
+ interface Props extends HTMLAttributes<'details'> { label: string, status?: LumenToolStatus, statusLabel: string }
10
+
11
+ const { class: className, label, status = 'queued', statusLabel, ...rest } = Astro.props
12
+ ---
13
+
14
+ <Collapsible {...rest} class:list={['ui-tool-activity', className]} data-status={status}>
15
+ <summary>{label}</summary>
16
+ <Stack gap="related"><span role="status">{statusLabel}</span><slot /></Stack>
17
+ </Collapsible>
@@ -59,6 +59,7 @@ const { classList, passthrough } = resolveLumenAstroProps(rest, [
59
59
  <div class="ui-tree-select__tree" role="tree">
60
60
  {rows.map(row => (
61
61
  <button
62
+ aria-level={row.depth + 1}
62
63
  class="ui-tree-select__option"
63
64
  data-value={row.value}
64
65
  role="treeitem"
@@ -7,14 +7,17 @@ interface Props extends HTMLAttributes<'div'> {
7
7
  class?: string | null
8
8
  className?: string
9
9
  glass?: boolean | 'subtle' | 'strong'
10
+ itemSize?: number | string
11
+ overscan?: number | string
12
+ mode?: 'data' | 'mounted'
10
13
  }
11
14
 
12
- const { class: classProp = '', className = '', glass = false, ...rest } = Astro.props
15
+ const { class: classProp = '', className = '', glass = false, itemSize = 44, overscan = 4, mode = 'mounted', tabindex = 0, ...rest } = Astro.props
13
16
 
14
17
  const { classList, passthrough } = resolveLumenAstroProps(rest, ['ui-virtual-list', glass && 'ui-virtual-list--glass', glass === 'subtle' && 'ui-glass-subtle', glass === 'strong' && 'ui-glass-strong'
15
18
  ], classProp, className)
16
19
  ---
17
20
 
18
- <div class:list={classList} data-ui-virtual-list {...passthrough}>
21
+ <div class:list={classList} data-ui-virtual-list data-ui-virtual-list-mode={mode} data-ui-item-size={itemSize} data-ui-overscan={overscan} tabindex={tabindex} {...passthrough}>
19
22
  <slot />
20
23
  </div>
@@ -0,0 +1,21 @@
1
+ ---
2
+ import type { HTMLAttributes } from 'astro/types'
3
+
4
+ import { type LumenVisualEffectVariant, normalizeLumenEffectIntensity, resolveLumenAstroProps } from '@santi020k/lumen-core'
5
+
6
+ interface Props extends HTMLAttributes<'div'> {
7
+ animated?: boolean
8
+ class?: string | null
9
+ className?: string
10
+ intensity?: number
11
+ variant?: LumenVisualEffectVariant
12
+ }
13
+
14
+ const { animated = false, class: classProp, className, intensity = 0.5, style, variant = 'mesh', ...rest } = Astro.props
15
+ const { classList, passthrough } = resolveLumenAstroProps(rest, ['ui-visual-effect'], classProp, className)
16
+ const effectStyle = `${typeof style === 'string' ? style : ''};--ui-effect-intensity:${normalizeLumenEffectIntensity(intensity)}`
17
+ ---
18
+
19
+ <div class:list={classList} data-ui-visual-effect={variant} data-ui-effect-animated={String(animated)} style={effectStyle} {...passthrough}>
20
+ <slot />
21
+ </div>
@@ -0,0 +1,27 @@
1
+ ---
2
+ import type { HTMLAttributes } from 'astro/types'
3
+
4
+ import { createLumenWaterfallGeometry, type LumenChartLabels, type LumenWaterfallDatum, resolveLumenChartLabels } from '@santi020k/lumen-core'
5
+
6
+ import IntervalChart from '../internal/IntervalChart.astro'
7
+
8
+ interface Props extends HTMLAttributes<'figure'> {
9
+ caption?: string
10
+ class?: string | null
11
+ className?: string
12
+ data: readonly LumenWaterfallDatum[]
13
+ description?: string
14
+ formatValue?: (value: number) => string
15
+ heading?: string
16
+ labels?: Partial<LumenChartLabels>
17
+ presentation?: 'bare' | 'default'
18
+ showTable?: boolean
19
+ summary?: string
20
+ valueLabel?: string
21
+ }
22
+
23
+ const { data, class: classProp, className, formatValue = String, labels, valueLabel = resolveLumenChartLabels(labels).value, ...rest } = Astro.props
24
+ const model = createLumenWaterfallGeometry(data, { formatValue })
25
+ ---
26
+
27
+ <IntervalChart {...rest} class:list={['ui-waterfall-chart', classProp, className]} {model} {labels} {formatValue} formatBoundary={formatValue} {valueLabel} />
@@ -0,0 +1,213 @@
1
+ ---
2
+ import type { HTMLAttributes } from 'astro/types'
3
+
4
+ import {
5
+ findLumenWorldMapCountry,
6
+ LUMEN_WORLD_MAP_VIEW_BOX,
7
+ type LumenWorldMapCountryGeometry,
8
+ type LumenWorldMapMarker,
9
+ type LumenWorldMapVariant,
10
+ normalizeLumenWorldMapCountries,
11
+ normalizeLumenWorldMapHighlightedCountries,
12
+ normalizeLumenWorldMapMarkers,
13
+ projectLumenWorldMapCoordinate,
14
+ resolveLumenAstroProps,
15
+ resolveLumenWorldMapCountryLabel
16
+ } from '@santi020k/lumen-core'
17
+ import { type LumenWorldMapZoomLabels, lumenWorldMapZoomLabels } from '@santi020k/lumen-core/world-map-zoom'
18
+
19
+ import Button from './Button.astro'
20
+
21
+ interface Props extends HTMLAttributes<'figure'> {
22
+ initialView?: 'world' | 'highlighted'
23
+ zoomable?: boolean
24
+ zoomLabels?: Partial<LumenWorldMapZoomLabels>
25
+ animated?: boolean
26
+ caption?: string
27
+ class?: string | null
28
+ className?: string
29
+ countries: readonly LumenWorldMapCountryGeometry[]
30
+ description?: string
31
+ heading?: string
32
+ highlightedCountries?: readonly string[]
33
+ interactive?: boolean
34
+ label: string
35
+ labels?: Readonly<Record<string, string>>
36
+ listLabel?: string
37
+ markers?: readonly LumenWorldMapMarker[]
38
+ selectedCountry?: string
39
+ variant?: LumenWorldMapVariant
40
+ }
41
+
42
+ const {
43
+ animated = true,
44
+ caption,
45
+ class: classProp = '',
46
+ className = '',
47
+ countries: inputCountries,
48
+ description,
49
+ heading,
50
+ highlightedCountries,
51
+ interactive = true,
52
+ label,
53
+ labels,
54
+ listLabel = 'Choose a country',
55
+ markers,
56
+ selectedCountry,
57
+ variant = 'dotted',
58
+ initialView = 'world',
59
+ zoomable = true,
60
+ zoomLabels,
61
+ ...rest
62
+ } = Astro.props
63
+
64
+ const countries = normalizeLumenWorldMapCountries(inputCountries)
65
+ const highlightedIds = normalizeLumenWorldMapHighlightedCountries(highlightedCountries, countries)
66
+ const highlightedSet = new Set(highlightedIds)
67
+ const normalizedMarkers = normalizeLumenWorldMapMarkers(markers)
68
+ const selected = findLumenWorldMapCountry(countries, selectedCountry)
69
+ const zoomText = { ...lumenWorldMapZoomLabels, ...zoomLabels }
70
+ const instanceId = `ui-world-map-${crypto.randomUUID()}`
71
+ const neutralPatternId = `${instanceId}-dot-neutral`
72
+ const highlightPatternId = `${instanceId}-dot-highlight`
73
+ const { height: viewBoxHeight, width: viewBoxWidth } = LUMEN_WORLD_MAP_VIEW_BOX
74
+ const { classList, passthrough } = resolveLumenAstroProps(rest, ['ui-world-map'], classProp, className)
75
+ ---
76
+
77
+ <figure
78
+ class:list={classList}
79
+ data-animated={String(animated)}
80
+ data-interactive={String(interactive)}
81
+ data-ui-world-map
82
+ data-initial-view={initialView}
83
+ data-variant={variant}
84
+ id={instanceId}
85
+ {...passthrough}
86
+ >
87
+ {
88
+ (heading || description) && (
89
+ <header class="ui-world-map__heading">
90
+ {heading && <h3>{heading}</h3>}
91
+ {description && <p>{description}</p>}
92
+ </header>
93
+ )
94
+ }
95
+ {zoomable && (
96
+ <div class="ui-world-map__zoom-controls">
97
+ <Button aria-label={zoomText.zoomOut} data-ui-world-map-zoom="out" disabled size="icon" variant="outline">−</Button>
98
+ <output aria-label={zoomText.level} aria-live="polite" data-ui-world-map-zoom-status>100%</output>
99
+ <Button aria-label={zoomText.zoomIn} data-ui-world-map-zoom="in" disabled size="icon" variant="outline">+</Button>
100
+ <Button data-ui-world-map-zoom="fit" disabled size="sm" variant="outline">{zoomText.fit}</Button>
101
+ <Button data-ui-world-map-zoom="reset" disabled size="sm" variant="outline">{zoomText.reset}</Button>
102
+ </div>
103
+ )}
104
+ <div class="ui-world-map__frame">
105
+ <div
106
+ aria-label={`${zoomText.viewport}: ${label}`}
107
+ class="ui-world-map__viewport"
108
+ data-ui-world-map-viewport
109
+ role="region"
110
+ tabindex={zoomable ? 0 : undefined}
111
+ >
112
+ <svg
113
+ aria-label={label}
114
+ class="ui-world-map__plot"
115
+ role="img"
116
+ viewBox={`0 0 ${viewBoxWidth} ${viewBoxHeight}`}
117
+ xmlns="http://www.w3.org/2000/svg"
118
+ >
119
+ {
120
+ variant === 'dotted' && (
121
+ <defs>
122
+ <pattern height="4" id={neutralPatternId} patternUnits="userSpaceOnUse" width="4">
123
+ <circle class="ui-world-map__dot ui-world-map__dot--neutral" cx="2" cy="2" r="1.1" />
124
+ </pattern>
125
+ <pattern height="4" id={highlightPatternId} patternUnits="userSpaceOnUse" width="4">
126
+ <circle class="ui-world-map__dot ui-world-map__dot--highlight" cx="2" cy="2" r="1.1" />
127
+ </pattern>
128
+ </defs>
129
+ )
130
+ }
131
+ <g aria-hidden="true" class="ui-world-map__countries">
132
+ {countries.map(country => {
133
+ const isHighlighted = highlightedSet.has(country.id)
134
+ const isSelected = selected?.id === country.id
135
+ const countryLabel = resolveLumenWorldMapCountryLabel(country, labels)
136
+
137
+ return (
138
+ <path
139
+ class:list={[
140
+ 'ui-world-map__country',
141
+ isHighlighted && 'ui-world-map__country--highlighted',
142
+ isSelected && 'ui-world-map__country--selected'
143
+ ]}
144
+ d={country.path}
145
+ data-label={countryLabel}
146
+ data-label-x={country.labelX}
147
+ data-label-y={country.labelY}
148
+ data-ui-world-map-country={country.id}
149
+ fill={
150
+ variant === 'dotted' ?
151
+ `url(#${isHighlighted ? highlightPatternId : neutralPatternId})` :
152
+ undefined
153
+ }
154
+ fill-rule="evenodd"
155
+ >
156
+ <title>{countryLabel}</title>
157
+ </path>
158
+ )
159
+ })}
160
+ </g>
161
+ {
162
+ normalizedMarkers.length > 0 && (
163
+ <g aria-hidden="true" class="ui-world-map__markers">
164
+ {normalizedMarkers.map(marker => {
165
+ const { x, y } = projectLumenWorldMapCoordinate(marker.longitude, marker.latitude)
166
+
167
+ return (
168
+ <circle class="ui-world-map__marker" cx={x} cy={y} r="4">
169
+ <title>{marker.label}</title>
170
+ </circle>
171
+ )
172
+ })}
173
+ </g>
174
+ )
175
+ }
176
+ <path aria-hidden="true" class="ui-world-map__selection" d={selected?.path ?? ''} />
177
+ </svg>
178
+ </div>
179
+ <span class="ui-world-map__inspection" data-ui-world-map-inspection hidden />
180
+ </div>
181
+ {
182
+ interactive && (
183
+ <label class="ui-world-map__select-label">
184
+ <span>{listLabel}</span>
185
+ <select class="ui-select ui-world-map__select" data-ui-world-map-select disabled>
186
+ <option value="">{listLabel}</option>
187
+ {countries.map(country => (
188
+ <option selected={selected?.id === country.id} value={country.id}>
189
+ {resolveLumenWorldMapCountryLabel(country, labels)}
190
+ </option>
191
+ ))}
192
+ </select>
193
+ </label>
194
+ )
195
+ }
196
+ {
197
+ highlightedIds.length > 0 && (
198
+ <ul aria-label="Highlighted countries" class="ui-world-map__highlights" data-ui-world-map-highlights>
199
+ {highlightedIds.map(id => {
200
+ const country = findLumenWorldMapCountry(countries, id)
201
+
202
+ return country && <li>{resolveLumenWorldMapCountryLabel(country, labels)}</li>
203
+ })}
204
+ </ul>
205
+ )
206
+ }
207
+ {normalizedMarkers.length > 0 && (
208
+ <ul aria-label="Map markers" class="ui-sr-only">
209
+ {normalizedMarkers.map(marker => <li>{marker.label}</li>)}
210
+ </ul>
211
+ )}
212
+ {caption && <figcaption>{caption}</figcaption>}
213
+ </figure>
package/forms.ts CHANGED
@@ -10,11 +10,24 @@ export interface AstroActionErrorLike {
10
10
 
11
11
  export type LumenControlIdMap = Readonly<Record<string, string>>
12
12
 
13
- const isActionErrorLike = (error: unknown): error is AstroActionErrorLike => (
14
- typeof error === 'object' &&
15
- error !== null
13
+ const isFieldMessages = (value: unknown): boolean => (
14
+ value === null || value === undefined || typeof value === 'string' ||
15
+ (Array.isArray(value) && value.every((message: unknown) => typeof message === 'string'))
16
16
  )
17
17
 
18
+ const isActionFields = (value: unknown): value is NonNullable<AstroActionErrorLike['fields']> => (
19
+ typeof value === 'object' && value !== null && !Array.isArray(value) &&
20
+ Object.values(value).every(isFieldMessages)
21
+ )
22
+
23
+ const isActionErrorLike = (error: unknown): error is AstroActionErrorLike => {
24
+ if (typeof error !== 'object' || error === null) return false
25
+
26
+ if ('message' in error && error.message !== undefined && typeof error.message !== 'string') return false
27
+
28
+ return !('fields' in error) || error.fields === undefined || isActionFields(error.fields)
29
+ }
30
+
18
31
  export const normalizeAstroActionErrors = (
19
32
  error: unknown,
20
33
  controlIds: LumenControlIdMap = {}
@@ -35,7 +48,7 @@ export const normalizeAstroActionErrors = (
35
48
  return {
36
49
  fields: normalized.fields.map(fieldError => ({
37
50
  ...fieldError,
38
- ...(controlIds[fieldError.name] ?
51
+ ...(Object.hasOwn(controlIds, fieldError.name) && controlIds[fieldError.name] ?
39
52
  {
40
53
  controlId: controlIds[fieldError.name]
41
54
  } :
package/index.ts CHANGED
@@ -3,24 +3,31 @@ export { default as Affix } from './components/Affix.astro'
3
3
  export { default as Agenda } from './components/Agenda.astro'
4
4
  export { default as Alert } from './components/Alert.astro'
5
5
  export { default as AlertDialog } from './components/AlertDialog.astro'
6
+ export { default as AmountField } from './components/AmountField.astro'
6
7
  export { default as Anchor } from './components/Anchor.astro'
7
8
  export { default as AnimatedLogo } from './components/AnimatedLogo.astro'
8
9
  export { default as AnimatedNumber } from './components/AnimatedNumber.astro'
9
10
  export { default as AnimatedPortrait } from './components/AnimatedPortrait.astro'
11
+ export { default as ApprovalCard } from './components/ApprovalCard.astro'
10
12
  export { default as AspectRatio } from './components/AspectRatio.astro'
11
13
  export { default as Attachment } from './components/Attachment.astro'
14
+ export { default as AttachmentList } from './components/AttachmentList.astro'
15
+ export { default as AttachmentPreview } from './components/AttachmentPreview.astro'
12
16
  export { default as Autocomplete } from './components/Autocomplete.astro'
13
17
  export { default as Avatar } from './components/Avatar.astro'
14
18
  export { default as Backdrop } from './components/Backdrop.astro'
15
19
  export { default as BackToTop } from './components/BackToTop.astro'
16
20
  export { default as Badge } from './components/Badge.astro'
17
21
  export { default as BarChart } from './components/BarChart.astro'
22
+ export { default as BoxPlot } from './components/BoxPlot.astro'
18
23
  export { default as Breadcrumb } from './components/Breadcrumb.astro'
19
24
  export { default as Bubble } from './components/Bubble.astro'
25
+ export { default as BulletChart } from './components/BulletChart.astro'
20
26
  export { default as Button } from './components/Button.astro'
21
27
  export { default as ButtonGroup } from './components/ButtonGroup.astro'
22
28
  export { default as ButtonLink } from './components/ButtonLink.astro'
23
29
  export { default as Calendar } from './components/Calendar.astro'
30
+ export { default as CalendarHeatmap } from './components/CalendarHeatmap.astro'
24
31
  export { default as Callout } from './components/Callout.astro'
25
32
  export { default as Card } from './components/Card.astro'
26
33
  export { default as CardContent } from './components/CardContent.astro'
@@ -30,7 +37,9 @@ export { default as CardHeader } from './components/CardHeader.astro'
30
37
  export { default as CardTitle } from './components/CardTitle.astro'
31
38
  export { default as Carousel } from './components/Carousel.astro'
32
39
  export { default as Cascader } from './components/Cascader.astro'
40
+ export { default as ChangeSummary } from './components/ChangeSummary.astro'
33
41
  export { default as Chart } from './components/Chart.astro'
42
+ export { default as ChartMotion } from './components/ChartMotion.astro'
34
43
  export { default as Checkbox } from './components/Checkbox.astro'
35
44
  export { default as CheckboxGroup } from './components/CheckboxGroup.astro'
36
45
  export { default as Code } from './components/Code.astro'
@@ -44,12 +53,22 @@ export { default as Container } from './components/Container.astro'
44
53
  export { default as ContextMenu } from './components/ContextMenu.astro'
45
54
  export { default as ContextNavigation } from './components/ContextNavigation.astro'
46
55
  export { default as CopyButton } from './components/CopyButton.astro'
56
+ export { default as CountryFlag } from './components/CountryFlag.astro'
47
57
  export { default as CoverImage } from './components/CoverImage.astro'
48
58
  export { default as DataTable } from './components/DataTable.astro'
49
59
  export { default as DatePicker } from './components/DatePicker.astro'
50
60
  export { default as DateRangePicker } from './components/DateRangePicker.astro'
61
+ export { default as DescriptionDetail } from './components/DescriptionDetail.astro'
62
+ export { default as DescriptionItem } from './components/DescriptionItem.astro'
51
63
  export { default as Descriptions } from './components/Descriptions.astro'
64
+ export { default as DescriptionTerm } from './components/DescriptionTerm.astro'
65
+ export { default as DeviceFrame } from './components/DeviceFrame.astro'
52
66
  export { default as Dialog } from './components/Dialog.astro'
67
+ export { default as DialogBody } from './components/DialogBody.astro'
68
+ export { default as DialogClose } from './components/DialogClose.astro'
69
+ export { default as DialogFooter } from './components/DialogFooter.astro'
70
+ export { default as DialogHeader } from './components/DialogHeader.astro'
71
+ export { default as DialogTitle } from './components/DialogTitle.astro'
53
72
  export { default as Direction } from './components/Direction.astro'
54
73
  export { default as Drawer } from './components/Drawer.astro'
55
74
  export { default as DropdownMenu } from './components/DropdownMenu.astro'
@@ -57,6 +76,7 @@ export { default as DropdownMenuContent } from './components/DropdownMenuContent
57
76
  export { default as DropdownMenuItem } from './components/DropdownMenuItem.astro'
58
77
  export { default as DropdownMenuSeparator } from './components/DropdownMenuSeparator.astro'
59
78
  export { default as DropdownMenuTrigger } from './components/DropdownMenuTrigger.astro'
79
+ export { default as DumbbellChart } from './components/DumbbellChart.astro'
60
80
  export { default as Empty } from './components/Empty.astro'
61
81
  export { default as ErrorState } from './components/ErrorState.astro'
62
82
  export { default as ErrorSummary } from './components/ErrorSummary.astro'
@@ -64,17 +84,21 @@ export { default as Eyebrow } from './components/Eyebrow.astro'
64
84
  export { default as Field } from './components/Field.astro'
65
85
  export { default as FieldError } from './components/FieldError.astro'
66
86
  export { default as FileUpload } from './components/FileUpload.astro'
87
+ export { default as FilterBar } from './components/FilterBar.astro'
67
88
  export { default as FloatingBadge } from './components/FloatingBadge.astro'
68
89
  export { default as Form } from './components/Form.astro'
69
90
  export { default as FormattedDate } from './components/FormattedDate.astro'
91
+ export { default as FunnelChart } from './components/FunnelChart.astro'
70
92
  export { default as GradientDivider } from './components/GradientDivider.astro'
71
93
  export { default as Graphic } from './components/Graphic.astro'
72
94
  export { default as Grid } from './components/Grid.astro'
73
95
  export { default as Heatmap } from './components/Heatmap.astro'
96
+ export { default as Histogram } from './components/Histogram.astro'
74
97
  export { default as HoverCard } from './components/HoverCard.astro'
75
98
  export { default as Icon } from './components/Icon.astro'
76
99
  export { default as Illustration } from './components/Illustration.astro'
77
100
  export { default as Image } from './components/Image.astro'
101
+ export { default as ImageComparison } from './components/ImageComparison.astro'
78
102
  export { default as Input } from './components/Input.astro'
79
103
  export { default as InputGroup } from './components/InputGroup.astro'
80
104
  export { default as InputOTP } from './components/InputOTP.astro'
@@ -87,12 +111,17 @@ export { default as LanguageToggle } from './components/LanguageToggle.astro'
87
111
  export { default as LineChart } from './components/LineChart.astro'
88
112
  export { default as Link } from './components/Link.astro'
89
113
  export { default as ListBox } from './components/ListBox.astro'
114
+ export { default as LollipopChart } from './components/LollipopChart.astro'
90
115
  export { default as Marker } from './components/Marker.astro'
116
+ export { default as MediaFilmstrip } from './components/MediaFilmstrip.astro'
117
+ export { default as MediaThumbnail } from './components/MediaThumbnail.astro'
118
+ export { default as MediaViewport } from './components/MediaViewport.astro'
91
119
  export { default as Mentions } from './components/Mentions.astro'
92
120
  export { default as Menubar } from './components/Menubar.astro'
93
121
  export { default as Message } from './components/Message.astro'
94
122
  export { default as MessageScroller } from './components/MessageScroller.astro'
95
123
  export { default as Meter } from './components/Meter.astro'
124
+ export { default as MotionGroup } from './components/MotionGroup.astro'
96
125
  export { default as NativeSelect } from './components/NativeSelect.astro'
97
126
  export { default as NavigationMenu } from './components/NavigationMenu.astro'
98
127
  export { default as Note } from './components/Note.astro'
@@ -101,6 +130,7 @@ export { default as Pagination } from './components/Pagination.astro'
101
130
  export { default as Particles } from './components/Particles.astro'
102
131
  export { default as PasswordField } from './components/PasswordField.astro'
103
132
  export { default as PhoneInput } from './components/PhoneInput.astro'
133
+ export { default as PhoneNumber } from './components/PhoneNumber.astro'
104
134
  export { default as PieChart } from './components/PieChart.astro'
105
135
  export { default as Pill } from './components/Pill.astro'
106
136
  export { default as Popconfirm } from './components/Popconfirm.astro'
@@ -108,6 +138,7 @@ export { default as Popover } from './components/Popover.astro'
108
138
  export { default as PopoverPanel } from './components/PopoverPanel.astro'
109
139
  export { default as PopoverTrigger } from './components/PopoverTrigger.astro'
110
140
  export { default as Progress } from './components/Progress.astro'
141
+ export { default as PromptComposer } from './components/PromptComposer.astro'
111
142
  export { default as Prose } from './components/Prose.astro'
112
143
  export { default as QRCode } from './components/QRCode.astro'
113
144
  export { default as RadioGroup } from './components/RadioGroup.astro'
@@ -130,6 +161,7 @@ export { default as Sidebar } from './components/Sidebar.astro'
130
161
  export { default as Skeleton } from './components/Skeleton.astro'
131
162
  export { default as SkipLink } from './components/SkipLink.astro'
132
163
  export { default as Slider } from './components/Slider.astro'
164
+ export { default as SourceCitation } from './components/SourceCitation.astro'
133
165
  export { default as Sparkline } from './components/Sparkline.astro'
134
166
  export { default as SpeedDial } from './components/SpeedDial.astro'
135
167
  export { default as Spinner } from './components/Spinner.astro'
@@ -141,6 +173,7 @@ export { default as StatLabel } from './components/StatLabel.astro'
141
173
  export { default as StatTrend } from './components/StatTrend.astro'
142
174
  export { default as StatValue } from './components/StatValue.astro'
143
175
  export { default as Stepper } from './components/Stepper.astro'
176
+ export { default as StreamMessage } from './components/StreamMessage.astro'
144
177
  export { default as Switch } from './components/Switch.astro'
145
178
  export { default as Table } from './components/Table.astro'
146
179
  export { default as Tabs } from './components/Tabs.astro'
@@ -158,6 +191,7 @@ export { default as Toast } from './components/Toast.astro'
158
191
  export { default as ToastViewport } from './components/ToastViewport.astro'
159
192
  export { default as Toggle } from './components/Toggle.astro'
160
193
  export { default as ToggleGroup } from './components/ToggleGroup.astro'
194
+ export { default as ToolActivity } from './components/ToolActivity.astro'
161
195
  export { default as Toolbar } from './components/Toolbar.astro'
162
196
  export { default as Tooltip } from './components/Tooltip.astro'
163
197
  export { default as TooltipContent } from './components/TooltipContent.astro'
@@ -168,8 +202,11 @@ export { default as TreeGrid } from './components/TreeGrid.astro'
168
202
  export { default as TreeSelect } from './components/TreeSelect.astro'
169
203
  export { default as Typography } from './components/Typography.astro'
170
204
  export { default as VirtualList } from './components/VirtualList.astro'
205
+ export { default as VisualEffect } from './components/VisualEffect.astro'
171
206
  export { default as VisuallyHidden } from './components/VisuallyHidden.astro'
207
+ export { default as WaterfallChart } from './components/WaterfallChart.astro'
172
208
  export { default as Watermark } from './components/Watermark.astro'
209
+ export { default as WorldMap } from './components/WorldMap.astro'
173
210
  export {
174
211
  type AstroActionErrorLike,
175
212
  type LumenControlIdMap,
@@ -0,0 +1,27 @@
1
+ ---
2
+ import { type createLumenLineChartModel, getLumenChartCategoryLabel, getLumenChartToneClassName, type LumenChartLabels } from '@santi020k/lumen-core'
3
+
4
+ interface Props {
5
+ formatCategory?: ((value: number | string) => string) | undefined
6
+ formatValue: (value: number) => string
7
+ labels: Readonly<LumenChartLabels>
8
+ model: ReturnType<typeof createLumenLineChartModel>
9
+ }
10
+
11
+ const { formatCategory, formatValue, labels, model } = Astro.props
12
+ const lookup = model.series.map(series => new Map(series.data.map(datum => [datum.x, datum])))
13
+ ---
14
+
15
+ <div class="ui-chart__inspection" data-ui-chart-inspection hidden>
16
+ {model.categories.map((category, index) => (
17
+ <div data-ui-chart-point={JSON.stringify(category)} data-ui-chart-position={model.positions[index]} hidden>
18
+ <strong>{getLumenChartCategoryLabel(model.series, category, formatCategory, 'detail')}</strong>
19
+ {model.series.map((series, seriesIndex) => {
20
+ const value = lookup[seriesIndex]?.get(category)?.y
21
+
22
+ return <span class={getLumenChartToneClassName(series.tone, seriesIndex)} data-ui-chart-series-value={series.id}><i aria-hidden="true" />{series.label}{' '}<b>{value === null || value === undefined || !Number.isFinite(value) ? labels.notAvailable : formatValue(value)}</b></span>
23
+ })}
24
+ </div>
25
+ ))}
26
+ </div>
27
+ <p aria-live="polite" aria-atomic="true" class="ui-sr-only" data-ui-chart-announcement />