@santi020k/lumen-astro 3.0.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +403 -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/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/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/SourceCitation.astro +18 -0
- package/components/Sparkline.astro +9 -10
- 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 +670 -647
- 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/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/visual-interactions.ts +75 -0
- package/runtime/controllers/world-map.ts +154 -0
- package/styles/critical.css +634 -61
- package/styles/lumen.css +101 -0
|
@@ -2,30 +2,37 @@
|
|
|
2
2
|
import type { HTMLAttributes } from 'astro/types'
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
createLumenChartDatumActivation,
|
|
6
|
+
createLumenLineChartModel,
|
|
7
7
|
formatLumenChartSummary,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
getLumenChartDomain,
|
|
11
|
-
getLumenChartTicks,
|
|
8
|
+
getLumenChartCategoryLabel,
|
|
9
|
+
getLumenChartMotionKey,
|
|
12
10
|
getLumenChartToneClassName,
|
|
13
11
|
hasLumenChartData,
|
|
14
12
|
type LumenChartLabels,
|
|
15
13
|
type LumenChartSeries,
|
|
14
|
+
type LumenLineChartOptions,
|
|
16
15
|
resolveLumenChartLabels,
|
|
17
16
|
resolveLumenChartTone,
|
|
18
17
|
scaleLumenChartValue
|
|
19
18
|
} from '@santi020k/lumen-core'
|
|
20
19
|
|
|
20
|
+
import ChartInspection from '../internal/ChartInspection.astro'
|
|
21
|
+
import { createChartDatumAction } from '../runtime/chart-actions'
|
|
22
|
+
|
|
23
|
+
import Button from './Button.astro'
|
|
21
24
|
import Chart from './Chart.astro'
|
|
25
|
+
import ChartDatumActions from './ChartDatumActions.astro'
|
|
22
26
|
|
|
23
|
-
interface Props extends HTMLAttributes<'figure'
|
|
27
|
+
interface Props extends HTMLAttributes<'figure'>, LumenLineChartOptions {
|
|
28
|
+
interactive?: boolean
|
|
29
|
+
syncGroup?: string
|
|
24
30
|
area?: boolean
|
|
25
31
|
caption?: string
|
|
26
32
|
class?: string | null
|
|
27
33
|
className?: string
|
|
28
34
|
description?: string
|
|
35
|
+
drilldown?: boolean
|
|
29
36
|
emptyLabel?: string
|
|
30
37
|
formatCategory?: (category: number | string) => string
|
|
31
38
|
formatValue?: (value: number) => string
|
|
@@ -43,12 +50,21 @@ interface Props extends HTMLAttributes<'figure'> {
|
|
|
43
50
|
|
|
44
51
|
const {
|
|
45
52
|
area = false,
|
|
53
|
+
annotations = [],
|
|
54
|
+
domain: requestedDomain,
|
|
55
|
+
height: requestedHeight,
|
|
56
|
+
width: requestedWidth,
|
|
57
|
+
xDomain,
|
|
58
|
+
xScale = 'categorical',
|
|
59
|
+
interactive = false,
|
|
60
|
+
syncGroup,
|
|
46
61
|
caption,
|
|
47
62
|
class: classProp = '',
|
|
48
63
|
className = '',
|
|
49
64
|
description,
|
|
65
|
+
drilldown = false,
|
|
50
66
|
emptyLabel,
|
|
51
|
-
formatCategory
|
|
67
|
+
formatCategory,
|
|
52
68
|
formatValue = String,
|
|
53
69
|
glass = false,
|
|
54
70
|
heading,
|
|
@@ -63,32 +79,22 @@ const {
|
|
|
63
79
|
} = Astro.props
|
|
64
80
|
|
|
65
81
|
const resolvedLabels = resolveLumenChartLabels(labels)
|
|
66
|
-
const summary = summaryProp ?? formatLumenChartSummary(series, formatValue, resolvedLabels)
|
|
67
|
-
const width = 640
|
|
68
|
-
const height = 320
|
|
69
|
-
const padding = 44
|
|
70
|
-
const categories = getLumenChartCategories(series)
|
|
71
|
-
const hasData = hasLumenChartData(series)
|
|
72
|
-
const alignedSeries = series.map(item => alignLumenChartSeries(item, categories))
|
|
73
|
-
|
|
74
|
-
const domain = getLumenChartDomain([
|
|
75
|
-
...alignedSeries.flatMap(item => item.data.map(datum => datum.y)),
|
|
76
|
-
referenceValue ?? null
|
|
77
|
-
], false)
|
|
78
|
-
|
|
79
|
-
const ticks = getLumenChartTicks(domain)
|
|
80
|
-
const paddingLeft = getLumenChartAxisPadding(ticks.map(tick => formatValue(tick)))
|
|
81
82
|
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
})
|
|
83
|
+
const model = createLumenLineChartModel(series, {
|
|
84
|
+
annotations,
|
|
85
|
+
xScale,
|
|
86
|
+
...(requestedDomain ? { domain: requestedDomain } : {}),
|
|
87
|
+
...(requestedHeight === undefined ? {} : { height: requestedHeight }),
|
|
88
|
+
...(requestedWidth === undefined ? {} : { width: requestedWidth }),
|
|
89
|
+
...(xDomain ? { xDomain } : {}),
|
|
90
|
+
...(referenceValue === undefined ? {} : { referenceValue }),
|
|
91
|
+
...(formatCategory ? { formatCategory } : {}),
|
|
92
|
+
formatValue
|
|
93
|
+
})
|
|
90
94
|
|
|
91
|
-
const
|
|
95
|
+
const { width, height, padding, paddingLeft, categories, categoryTicks, domain, geometries, ticks, series: alignedSeries } = model
|
|
96
|
+
const hasData = hasLumenChartData(alignedSeries)
|
|
97
|
+
const summary = summaryProp ?? formatLumenChartSummary(alignedSeries, formatValue, resolvedLabels)
|
|
92
98
|
let markerStep = 1
|
|
93
99
|
|
|
94
100
|
if (markers === false || markers === 'none') markerStep = Number.POSITIVE_INFINITY
|
|
@@ -96,14 +102,29 @@ else if (typeof markers === 'number') markerStep = Math.max(1, Math.round(marker
|
|
|
96
102
|
else if (markers === 'auto') markerStep = Math.max(1, Math.ceil(categories.length / 24))
|
|
97
103
|
|
|
98
104
|
const valueFor = (item: LumenChartSeries, category: number | string) => item.data.find(datum => datum.x === category)
|
|
99
|
-
|
|
100
|
-
const categoryLabelFor = (category: number | string) => series.flatMap(item => item.data)
|
|
101
|
-
.find(datum => datum.x === category)?.xLabel ?? formatCategory(category)
|
|
105
|
+
const categoryLabelFor = (category: number | string) => getLumenChartCategoryLabel(alignedSeries, category, formatCategory, 'detail')
|
|
102
106
|
|
|
103
107
|
const referenceY =
|
|
104
108
|
referenceValue === undefined ?
|
|
105
109
|
undefined :
|
|
106
110
|
scaleLumenChartValue(referenceValue, domain, height - padding, padding)
|
|
111
|
+
|
|
112
|
+
const pointActions = drilldown ?
|
|
113
|
+
geometries.map((geometry, index) => {
|
|
114
|
+
const item = alignedSeries[index]
|
|
115
|
+
|
|
116
|
+
return geometry.points.map(point => item ?
|
|
117
|
+
createChartDatumAction(
|
|
118
|
+
createLumenChartDatumActivation(item.id, point),
|
|
119
|
+
`${categoryLabelFor(point.x)} · ${item.label}: ${formatValue(point.y ?? 0)}`,
|
|
120
|
+
resolvedLabels
|
|
121
|
+
) :
|
|
122
|
+
null)
|
|
123
|
+
}) :
|
|
124
|
+
[]
|
|
125
|
+
|
|
126
|
+
const datumActions = pointActions.flat()
|
|
127
|
+
|
|
107
128
|
---
|
|
108
129
|
|
|
109
130
|
<Chart
|
|
@@ -113,22 +134,31 @@ const referenceY =
|
|
|
113
134
|
{glass}
|
|
114
135
|
{heading}
|
|
115
136
|
{summary}
|
|
137
|
+
data-ui-chart-interactive={interactive || undefined}
|
|
138
|
+
data-ui-chart-sync={syncGroup}
|
|
116
139
|
{...rest}
|
|
140
|
+
data-ui-chart-activation={drilldown || undefined}
|
|
117
141
|
>
|
|
118
142
|
{
|
|
119
143
|
showLegend && hasData && (
|
|
120
144
|
<ul class="ui-chart__legend" aria-label={resolvedLabels.chartLegend}>
|
|
121
145
|
{series.map((item, index) => (
|
|
122
146
|
<li class={getLumenChartToneClassName(item.tone, index)}>
|
|
123
|
-
<span aria-hidden="true" />
|
|
124
|
-
{item.label}
|
|
147
|
+
{interactive ? <Button aria-pressed="true" data-ui-chart-toggle={item.id} disabled size="sm" variant="ghost">{item.label}</Button> : <><span aria-hidden="true" />{item.label}</>}
|
|
125
148
|
</li>
|
|
126
149
|
))}
|
|
127
150
|
</ul>
|
|
128
151
|
)
|
|
129
152
|
}
|
|
130
153
|
{!hasData && <p class="ui-chart__empty" role="status">{emptyLabel ?? resolvedLabels.empty}</p>}
|
|
131
|
-
<div
|
|
154
|
+
<div
|
|
155
|
+
aria-label={rest['aria-label'] ?? heading ?? resolvedLabels.chartData}
|
|
156
|
+
class="ui-chart__plot"
|
|
157
|
+
data-ui-chart-interaction-plot={interactive || undefined}
|
|
158
|
+
role="region"
|
|
159
|
+
tabindex="0"
|
|
160
|
+
hidden={!hasData}
|
|
161
|
+
>
|
|
132
162
|
<svg
|
|
133
163
|
aria-hidden="true"
|
|
134
164
|
preserveAspectRatio="xMidYMid meet"
|
|
@@ -154,26 +184,21 @@ const referenceY =
|
|
|
154
184
|
</g>
|
|
155
185
|
<g class="ui-chart__axis-labels">
|
|
156
186
|
{
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
return null
|
|
163
|
-
|
|
164
|
-
const denominator = Math.max(1, categories.length - 1)
|
|
165
|
-
|
|
166
|
-
const x =
|
|
167
|
-
paddingLeft + (index / denominator) * (width - paddingLeft - padding)
|
|
168
|
-
|
|
169
|
-
return (
|
|
170
|
-
<text text-anchor="middle" x={x} y={height - 14}>
|
|
171
|
-
{categoryLabelFor(category)}
|
|
172
|
-
</text>
|
|
173
|
-
)
|
|
174
|
-
})
|
|
187
|
+
categoryTicks.map(tick => (
|
|
188
|
+
<text text-anchor={tick.textAnchor} x={tick.position} y={height - 14}>
|
|
189
|
+
{tick.label}
|
|
190
|
+
</text>
|
|
191
|
+
))
|
|
175
192
|
}
|
|
176
193
|
</g>
|
|
194
|
+
<svg
|
|
195
|
+
x={paddingLeft}
|
|
196
|
+
y={padding}
|
|
197
|
+
width={width - padding - paddingLeft}
|
|
198
|
+
height={height - 2 * padding}
|
|
199
|
+
viewBox={`${paddingLeft} ${padding} ${width - padding - paddingLeft} ${height - 2 * padding}`}
|
|
200
|
+
overflow="hidden"
|
|
201
|
+
>
|
|
177
202
|
{
|
|
178
203
|
referenceY !== undefined && (
|
|
179
204
|
<line
|
|
@@ -187,43 +212,73 @@ const referenceY =
|
|
|
187
212
|
}
|
|
188
213
|
{
|
|
189
214
|
geometries.map((geometry, index) => {
|
|
190
|
-
const item =
|
|
215
|
+
const item = alignedSeries[index]
|
|
191
216
|
|
|
192
217
|
if (!item) return null
|
|
193
218
|
|
|
194
219
|
const tone = resolveLumenChartTone(item.tone, index)
|
|
195
220
|
|
|
196
221
|
return (
|
|
197
|
-
<g
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
222
|
+
<g
|
|
223
|
+
data-ui-chart-series={item.id}
|
|
224
|
+
class:list={['ui-line-chart__series', getLumenChartToneClassName(tone)]}
|
|
225
|
+
>
|
|
226
|
+
{area && geometry.areaPaths.length > 0 && (
|
|
227
|
+
<path
|
|
228
|
+
data-ui-chart-motion-key={JSON.stringify(['area', item.id])}
|
|
229
|
+
class="ui-line-chart__area"
|
|
230
|
+
d={geometry.areaPaths.join(' ')}
|
|
231
|
+
/>
|
|
232
|
+
)}
|
|
233
|
+
<path
|
|
234
|
+
data-ui-chart-motion-key={JSON.stringify(['path', item.id])}
|
|
235
|
+
class="ui-line-chart__line"
|
|
236
|
+
d={geometry.path}
|
|
237
|
+
/>
|
|
203
238
|
{Number.isFinite(markerStep) &&
|
|
204
239
|
geometry.points.map((point, pointIndex) => pointIndex % markerStep === 0 && (
|
|
205
240
|
<circle
|
|
241
|
+
data-ui-chart-datum={pointActions[index]?.[pointIndex]?.serialized}
|
|
242
|
+
data-ui-chart-motion-key={getLumenChartMotionKey(item.id, point)}
|
|
206
243
|
class="ui-line-chart__point"
|
|
207
244
|
cx={point.xCoordinate}
|
|
208
245
|
cy={point.yCoordinate}
|
|
209
246
|
r="3"
|
|
210
247
|
>
|
|
211
248
|
<title>
|
|
212
|
-
{`${
|
|
249
|
+
{`${categoryLabelFor(point.x)} · ${item.label}: ${formatValue(point.y ?? 0)}`}
|
|
213
250
|
</title>
|
|
214
251
|
</circle>
|
|
215
252
|
))}
|
|
253
|
+
{drilldown && geometry.points.map((point, pointIndex) => (
|
|
254
|
+
<circle
|
|
255
|
+
class="ui-chart__datum-hit"
|
|
256
|
+
cx={point.xCoordinate}
|
|
257
|
+
cy={point.yCoordinate}
|
|
258
|
+
r="10"
|
|
259
|
+
data-ui-chart-datum={pointActions[index]?.[pointIndex]?.serialized}
|
|
260
|
+
/>
|
|
261
|
+
))}
|
|
216
262
|
</g>
|
|
217
263
|
)
|
|
218
264
|
})
|
|
219
265
|
}
|
|
266
|
+
</svg>
|
|
267
|
+
{model.annotationMarks.map(mark => (
|
|
268
|
+
<g class:list={['ui-chart__annotation', getLumenChartToneClassName(mark.tone)]}>
|
|
269
|
+
{mark.axis === 'x' ? <><line x1={mark.coordinate} x2={mark.coordinate} y1={padding} y2={height - padding} /><text x={mark.coordinate + 4} y={padding - 8}>{mark.label}</text></> : <><line x1={paddingLeft} x2={width - padding} y1={mark.coordinate} y2={mark.coordinate} /><text text-anchor="end" x={width - padding} y={mark.coordinate - 8}>{mark.label}</text></>}
|
|
270
|
+
</g>
|
|
271
|
+
))}
|
|
272
|
+
{interactive && <line class="ui-chart__crosshair" data-ui-chart-crosshair style="display: none" y1={padding} y2={height - padding} />}
|
|
220
273
|
</svg>
|
|
221
274
|
</div>
|
|
275
|
+
{model.annotationMarks.length > 0 && <ul class="ui-sr-only">{model.annotationMarks.map(mark => <li>{mark.label}: {mark.axis === 'x' ? categoryLabelFor(mark.value) : formatValue(Number(mark.value))}</li>)}</ul>}
|
|
276
|
+
{interactive && hasData && <ChartInspection {model} {formatCategory} {formatValue} labels={resolvedLabels} />}
|
|
222
277
|
{
|
|
223
278
|
showTable && hasData && (
|
|
224
279
|
<details class="ui-chart__data">
|
|
225
280
|
<summary>{resolvedLabels.viewData}</summary>
|
|
226
|
-
<div>
|
|
281
|
+
<div role="group" tabindex="0" aria-label={resolvedLabels.chartData}>
|
|
227
282
|
<table>
|
|
228
283
|
<thead>
|
|
229
284
|
<tr>
|
|
@@ -235,7 +290,7 @@ const referenceY =
|
|
|
235
290
|
{categories.map(category => (
|
|
236
291
|
<tr>
|
|
237
292
|
<th scope="row">{categoryLabelFor(category)}</th>
|
|
238
|
-
{
|
|
293
|
+
{alignedSeries.map(item => {
|
|
239
294
|
const datum = valueFor(item, category)
|
|
240
295
|
|
|
241
296
|
return (
|
|
@@ -255,4 +310,5 @@ const referenceY =
|
|
|
255
310
|
</details>
|
|
256
311
|
)
|
|
257
312
|
}
|
|
313
|
+
{drilldown && <ChartDatumActions actions={datumActions} label={resolvedLabels.exploreData} />}
|
|
258
314
|
</Chart>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { ComponentProps } from 'astro/types'
|
|
3
|
+
|
|
4
|
+
import ComparisonChart from '../internal/ComparisonChart.astro'
|
|
5
|
+
|
|
6
|
+
type Props = Omit<ComponentProps<typeof ComparisonChart>, 'paired'>
|
|
7
|
+
---
|
|
8
|
+
<ComparisonChart {...Astro.props} class:list={['ui-lollipop-chart', Astro.props.class, Astro.props.className]} paired={false} />
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
3
|
+
|
|
4
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
5
|
+
|
|
6
|
+
interface Props extends HTMLAttributes<'section'> {
|
|
7
|
+
className?: string
|
|
8
|
+
label: string
|
|
9
|
+
selectionLabel: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { class: classProp, className, label, selectionLabel, ...rest } = Astro.props
|
|
13
|
+
const { classList, passthrough } = resolveLumenAstroProps(rest, ['ui-media-filmstrip'], classProp, className)
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<section {...passthrough} class:list={classList} aria-label={label}>
|
|
17
|
+
<div class="ui-media-filmstrip__heading"><span>{label}</span><span role="status" data-ui-media-filmstrip-selection>{selectionLabel}</span></div>
|
|
18
|
+
<ol class="ui-media-filmstrip__items"><slot /></ol>
|
|
19
|
+
</section>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
3
|
+
|
|
4
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
5
|
+
|
|
6
|
+
import Button from './Button.astro'
|
|
7
|
+
|
|
8
|
+
interface Props extends HTMLAttributes<'button'> {
|
|
9
|
+
className?: string
|
|
10
|
+
label: string
|
|
11
|
+
mediaId: string
|
|
12
|
+
order?: number
|
|
13
|
+
selected?: boolean
|
|
14
|
+
state?: 'ready' | 'loading' | 'error'
|
|
15
|
+
stateLabel?: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const { class: classProp, className, disabled, label, mediaId, order, selected = false, state = 'ready', stateLabel, ...rest } = Astro.props
|
|
19
|
+
const position = order !== undefined && Number.isSafeInteger(order) && order > 0 ? order : undefined
|
|
20
|
+
const status = stateLabel ?? (state === 'loading' ? 'Loading' : 'Unavailable')
|
|
21
|
+
const { classList, passthrough } = resolveLumenAstroProps(rest, ['ui-media-thumbnail'], classProp, className)
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
<Button {...passthrough} class:list={classList} variant="outline" data-ui-media-thumbnail data-media-id={mediaId} aria-busy={state === 'loading' || undefined} aria-pressed={selected} disabled={Boolean(disabled) || state !== 'ready'} data-state={state}>
|
|
25
|
+
<span class="ui-media-thumbnail__media" aria-hidden="true"><slot /></span>
|
|
26
|
+
<span class="ui-media-thumbnail__label">{label}</span>
|
|
27
|
+
{position !== undefined && <span class="ui-media-thumbnail__order">{position}</span>}
|
|
28
|
+
{state !== 'ready' && <span class="ui-media-thumbnail__state">{status}</span>}
|
|
29
|
+
</Button>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
3
|
+
|
|
4
|
+
import { formatLumenMediaZoom, lumenMediaViewportActions, type LumenMediaViewportLabels, lumenMediaViewportLabels, type LumenMediaViewportValue, normalizeLumenMediaViewport, resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
5
|
+
|
|
6
|
+
import Button from './Button.astro'
|
|
7
|
+
|
|
8
|
+
interface Props extends HTMLAttributes<'figure'> {
|
|
9
|
+
className?: string
|
|
10
|
+
disabled?: boolean
|
|
11
|
+
label: string
|
|
12
|
+
labels?: Partial<LumenMediaViewportLabels>
|
|
13
|
+
locale?: string
|
|
14
|
+
maxZoom?: number
|
|
15
|
+
ratio?: number
|
|
16
|
+
value?: Partial<LumenMediaViewportValue>
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const { class: classProp, className, disabled = false, label, labels, locale, maxZoom = 4, ratio = 16 / 9, value, ...rest } = Astro.props
|
|
20
|
+
const current = normalizeLumenMediaViewport(value, maxZoom)
|
|
21
|
+
const copy = { ...lumenMediaViewportLabels, ...labels }
|
|
22
|
+
const safeRatio = Number.isFinite(ratio) && ratio >= 0.1 && ratio <= 10 ? ratio : 16 / 9
|
|
23
|
+
const statusId = `media-viewport-${crypto.randomUUID()}`
|
|
24
|
+
const { classList, passthrough } = resolveLumenAstroProps(rest, ['ui-media-viewport'], classProp, className)
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
<figure class:list={classList} {...passthrough} data-ui-media-viewport data-disabled={String(disabled)} data-max-zoom={maxZoom} data-zoom={current.zoom} data-pan-x={current.x} data-pan-y={current.y} data-locale={locale}>
|
|
28
|
+
<div class="ui-media-viewport__stage" data-ui-media-viewport-stage role="group" aria-label={label} aria-disabled={disabled} aria-describedby={statusId} tabindex="0" style={`aspect-ratio: ${safeRatio}`}>
|
|
29
|
+
<div class="ui-media-viewport__content" data-ui-media-viewport-content style={`transform: translate(${current.x * (current.zoom - 1) * 50}%, ${current.y * (current.zoom - 1) * 50}%) scale(${current.zoom})`}><slot /></div>
|
|
30
|
+
</div>
|
|
31
|
+
<figcaption>
|
|
32
|
+
<span>{label}</span>
|
|
33
|
+
<span id={statusId} role="status" aria-live="polite" data-ui-media-viewport-status>{formatLumenMediaZoom(current.zoom, locale)}</span>
|
|
34
|
+
<div class="ui-media-viewport__actions" role="group" aria-label={label}>
|
|
35
|
+
{lumenMediaViewportActions.map(action => <Button variant="outline" data-ui-media-viewport-action={action} disabled>{copy[action]}</Button>)}
|
|
36
|
+
</div>
|
|
37
|
+
</figcaption>
|
|
38
|
+
</figure>
|
|
@@ -49,7 +49,7 @@ const { classList, passthrough } = resolveLumenAstroProps(rest, [
|
|
|
49
49
|
/>
|
|
50
50
|
<ul class="ui-mentions__list" data-ui-mentions-list hidden id={listId} role="listbox">
|
|
51
51
|
{normalized.map((option, index) => (
|
|
52
|
-
<li>
|
|
52
|
+
<li role="presentation">
|
|
53
53
|
<button
|
|
54
54
|
aria-selected="false"
|
|
55
55
|
class="ui-mentions__option"
|
|
@@ -57,6 +57,7 @@ const { classList, passthrough } = resolveLumenAstroProps(rest, [
|
|
|
57
57
|
data-value={option.value}
|
|
58
58
|
id={`${listId}-option-${index}`}
|
|
59
59
|
role="option"
|
|
60
|
+
tabindex={-1}
|
|
60
61
|
type="button"
|
|
61
62
|
>
|
|
62
63
|
{option.label}
|
|
@@ -7,12 +7,16 @@ interface Props extends HTMLAttributes<'div'> {
|
|
|
7
7
|
class?: string | null
|
|
8
8
|
className?: string
|
|
9
9
|
glass?: boolean | 'subtle' | 'strong'
|
|
10
|
+
autoScroll?: boolean
|
|
11
|
+
scrollThreshold?: number
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
const {
|
|
13
15
|
class: classProp = '',
|
|
14
16
|
className = '',
|
|
15
17
|
glass = false,
|
|
18
|
+
autoScroll = false,
|
|
19
|
+
scrollThreshold = 32,
|
|
16
20
|
...rest
|
|
17
21
|
} = Astro.props
|
|
18
22
|
|
|
@@ -25,6 +29,8 @@ const { classList, passthrough } = resolveLumenAstroProps(rest, [
|
|
|
25
29
|
---
|
|
26
30
|
|
|
27
31
|
<div
|
|
32
|
+
data-ui-message-scroller={autoScroll ? '' : undefined}
|
|
33
|
+
scroll-threshold={scrollThreshold}
|
|
28
34
|
class:list={classList}
|
|
29
35
|
{...passthrough}
|
|
30
36
|
>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
3
|
+
|
|
4
|
+
import { type LumenWorkflowDuration, resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
5
|
+
|
|
6
|
+
interface Props extends HTMLAttributes<'div'> {
|
|
7
|
+
class?: string | null
|
|
8
|
+
className?: string
|
|
9
|
+
duration?: LumenWorkflowDuration
|
|
10
|
+
enterExit?: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const { class: classProp, className, duration = 'standard', enterExit = true, ...rest } = Astro.props
|
|
14
|
+
const { classList, passthrough } = resolveLumenAstroProps(rest, ['ui-motion-group'], classProp, className)
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
<div class:list={classList} data-ui-motion-group data-ui-motion-duration={duration} data-ui-motion-enter-exit={String(enterExit)} {...passthrough}>
|
|
18
|
+
<slot />
|
|
19
|
+
</div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
import type { HTMLAttributes } from 'astro/types'
|
|
3
3
|
|
|
4
|
-
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
4
|
+
import { type LumenControlVisualSize, resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
5
5
|
|
|
6
6
|
interface Option {
|
|
7
7
|
disabled?: boolean
|
|
@@ -17,7 +17,7 @@ interface Props extends Omit<HTMLAttributes<'select'>, 'size'> {
|
|
|
17
17
|
size?: HTMLAttributes<'select'>['size']
|
|
18
18
|
options?: SelectOption[]
|
|
19
19
|
placeholder?: string
|
|
20
|
-
visualSize?:
|
|
20
|
+
visualSize?: LumenControlVisualSize
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
const {
|
|
@@ -9,6 +9,7 @@ interface Props extends HTMLAttributes<'nav'> {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
const {
|
|
12
|
+
'aria-label': ariaLabel = 'Pagination',
|
|
12
13
|
class: classProp = '',
|
|
13
14
|
className = '',
|
|
14
15
|
...rest
|
|
@@ -20,7 +21,7 @@ const { classList, passthrough } = resolveLumenAstroProps(rest, [
|
|
|
20
21
|
---
|
|
21
22
|
|
|
22
23
|
<nav
|
|
23
|
-
aria-label=
|
|
24
|
+
aria-label={ariaLabel}
|
|
24
25
|
class:list={classList}
|
|
25
26
|
{...passthrough}
|
|
26
27
|
>
|
|
@@ -65,7 +65,7 @@ const { classList } = resolveLumenAstroProps({}, ['ui-password-field'], classPro
|
|
|
65
65
|
type="button"
|
|
66
66
|
variant="ghost"
|
|
67
67
|
>
|
|
68
|
-
<span aria-hidden="true" data-ui-password-toggle-label>
|
|
68
|
+
<span aria-hidden="true" data-ui-password-toggle-label>{showLabel}</span>
|
|
69
69
|
</Button>
|
|
70
70
|
</div>
|
|
71
71
|
{hint && <p class="ui-field__hint" data-ui-field-hint id={hintId}>{hint}</p>}
|