@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.
- 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 +127 -67
- 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,29 +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
|
-
getLumenChartTicks,
|
|
8
|
+
getLumenChartCategoryLabel,
|
|
9
|
+
getLumenChartMotionKey,
|
|
11
10
|
getLumenChartToneClassName,
|
|
12
11
|
hasLumenChartData,
|
|
13
12
|
type LumenChartLabels,
|
|
14
13
|
type LumenChartSeries,
|
|
14
|
+
type LumenLineChartOptions,
|
|
15
15
|
resolveLumenChartLabels,
|
|
16
16
|
resolveLumenChartTone,
|
|
17
17
|
scaleLumenChartValue
|
|
18
18
|
} from '@santi020k/lumen-core'
|
|
19
19
|
|
|
20
|
+
import ChartInspection from '../internal/ChartInspection.astro'
|
|
21
|
+
import { createChartDatumAction } from '../runtime/chart-actions'
|
|
22
|
+
|
|
23
|
+
import Button from './Button.astro'
|
|
20
24
|
import Chart from './Chart.astro'
|
|
25
|
+
import ChartDatumActions from './ChartDatumActions.astro'
|
|
21
26
|
|
|
22
|
-
interface Props extends HTMLAttributes<'figure'
|
|
27
|
+
interface Props extends HTMLAttributes<'figure'>, LumenLineChartOptions {
|
|
28
|
+
interactive?: boolean
|
|
29
|
+
syncGroup?: string
|
|
23
30
|
area?: boolean
|
|
24
31
|
caption?: string
|
|
25
32
|
class?: string | null
|
|
26
33
|
className?: string
|
|
27
34
|
description?: string
|
|
35
|
+
drilldown?: boolean
|
|
28
36
|
emptyLabel?: string
|
|
29
37
|
formatCategory?: (category: number | string) => string
|
|
30
38
|
formatValue?: (value: number) => string
|
|
@@ -42,12 +50,21 @@ interface Props extends HTMLAttributes<'figure'> {
|
|
|
42
50
|
|
|
43
51
|
const {
|
|
44
52
|
area = false,
|
|
53
|
+
annotations = [],
|
|
54
|
+
domain: requestedDomain,
|
|
55
|
+
height: requestedHeight,
|
|
56
|
+
width: requestedWidth,
|
|
57
|
+
xDomain,
|
|
58
|
+
xScale = 'categorical',
|
|
59
|
+
interactive = false,
|
|
60
|
+
syncGroup,
|
|
45
61
|
caption,
|
|
46
62
|
class: classProp = '',
|
|
47
63
|
className = '',
|
|
48
64
|
description,
|
|
65
|
+
drilldown = false,
|
|
49
66
|
emptyLabel,
|
|
50
|
-
formatCategory
|
|
67
|
+
formatCategory,
|
|
51
68
|
formatValue = String,
|
|
52
69
|
glass = false,
|
|
53
70
|
heading,
|
|
@@ -62,29 +79,22 @@ const {
|
|
|
62
79
|
} = Astro.props
|
|
63
80
|
|
|
64
81
|
const resolvedLabels = resolveLumenChartLabels(labels)
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
...
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const geometries
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
includeZero: false,
|
|
82
|
-
padding,
|
|
83
|
-
width
|
|
84
|
-
}))
|
|
85
|
-
|
|
86
|
-
const ticks = getLumenChartTicks(domain)
|
|
87
|
-
const labelStep = Math.max(1, Math.ceil(categories.length / 8))
|
|
82
|
+
|
|
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
|
+
})
|
|
94
|
+
|
|
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)
|
|
88
98
|
let markerStep = 1
|
|
89
99
|
|
|
90
100
|
if (markers === false || markers === 'none') markerStep = Number.POSITIVE_INFINITY
|
|
@@ -92,14 +102,29 @@ else if (typeof markers === 'number') markerStep = Math.max(1, Math.round(marker
|
|
|
92
102
|
else if (markers === 'auto') markerStep = Math.max(1, Math.ceil(categories.length / 24))
|
|
93
103
|
|
|
94
104
|
const valueFor = (item: LumenChartSeries, category: number | string) => item.data.find(datum => datum.x === category)
|
|
95
|
-
|
|
96
|
-
const categoryLabelFor = (category: number | string) => series.flatMap(item => item.data)
|
|
97
|
-
.find(datum => datum.x === category)?.xLabel ?? formatCategory(category)
|
|
105
|
+
const categoryLabelFor = (category: number | string) => getLumenChartCategoryLabel(alignedSeries, category, formatCategory, 'detail')
|
|
98
106
|
|
|
99
107
|
const referenceY =
|
|
100
108
|
referenceValue === undefined ?
|
|
101
109
|
undefined :
|
|
102
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
|
+
|
|
103
128
|
---
|
|
104
129
|
|
|
105
130
|
<Chart
|
|
@@ -109,22 +134,31 @@ const referenceY =
|
|
|
109
134
|
{glass}
|
|
110
135
|
{heading}
|
|
111
136
|
{summary}
|
|
137
|
+
data-ui-chart-interactive={interactive || undefined}
|
|
138
|
+
data-ui-chart-sync={syncGroup}
|
|
112
139
|
{...rest}
|
|
140
|
+
data-ui-chart-activation={drilldown || undefined}
|
|
113
141
|
>
|
|
114
142
|
{
|
|
115
143
|
showLegend && hasData && (
|
|
116
144
|
<ul class="ui-chart__legend" aria-label={resolvedLabels.chartLegend}>
|
|
117
145
|
{series.map((item, index) => (
|
|
118
146
|
<li class={getLumenChartToneClassName(item.tone, index)}>
|
|
119
|
-
<span aria-hidden="true" />
|
|
120
|
-
{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}</>}
|
|
121
148
|
</li>
|
|
122
149
|
))}
|
|
123
150
|
</ul>
|
|
124
151
|
)
|
|
125
152
|
}
|
|
126
153
|
{!hasData && <p class="ui-chart__empty" role="status">{emptyLabel ?? resolvedLabels.empty}</p>}
|
|
127
|
-
<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
|
+
>
|
|
128
162
|
<svg
|
|
129
163
|
aria-hidden="true"
|
|
130
164
|
preserveAspectRatio="xMidYMid meet"
|
|
@@ -139,8 +173,8 @@ const referenceY =
|
|
|
139
173
|
|
|
140
174
|
return (
|
|
141
175
|
<>
|
|
142
|
-
<line x1={
|
|
143
|
-
<text x={
|
|
176
|
+
<line x1={paddingLeft} x2={width - padding} y1={y} y2={y} />
|
|
177
|
+
<text x={paddingLeft - 8} y={y}>
|
|
144
178
|
{formatValue(tick)}
|
|
145
179
|
</text>
|
|
146
180
|
</>
|
|
@@ -150,31 +184,26 @@ const referenceY =
|
|
|
150
184
|
</g>
|
|
151
185
|
<g class="ui-chart__axis-labels">
|
|
152
186
|
{
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
return null
|
|
159
|
-
|
|
160
|
-
const denominator = Math.max(1, categories.length - 1)
|
|
161
|
-
|
|
162
|
-
const x =
|
|
163
|
-
padding + (index / denominator) * (width - padding * 2)
|
|
164
|
-
|
|
165
|
-
return (
|
|
166
|
-
<text text-anchor="middle" x={x} y={height - 14}>
|
|
167
|
-
{categoryLabelFor(category)}
|
|
168
|
-
</text>
|
|
169
|
-
)
|
|
170
|
-
})
|
|
187
|
+
categoryTicks.map(tick => (
|
|
188
|
+
<text text-anchor={tick.textAnchor} x={tick.position} y={height - 14}>
|
|
189
|
+
{tick.label}
|
|
190
|
+
</text>
|
|
191
|
+
))
|
|
171
192
|
}
|
|
172
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
|
+
>
|
|
173
202
|
{
|
|
174
203
|
referenceY !== undefined && (
|
|
175
204
|
<line
|
|
176
205
|
class="ui-chart__reference"
|
|
177
|
-
x1={
|
|
206
|
+
x1={paddingLeft}
|
|
178
207
|
x2={width - padding}
|
|
179
208
|
y1={referenceY}
|
|
180
209
|
y2={referenceY}
|
|
@@ -183,43 +212,73 @@ const referenceY =
|
|
|
183
212
|
}
|
|
184
213
|
{
|
|
185
214
|
geometries.map((geometry, index) => {
|
|
186
|
-
const item =
|
|
215
|
+
const item = alignedSeries[index]
|
|
187
216
|
|
|
188
217
|
if (!item) return null
|
|
189
218
|
|
|
190
219
|
const tone = resolveLumenChartTone(item.tone, index)
|
|
191
220
|
|
|
192
221
|
return (
|
|
193
|
-
<g
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
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
|
+
/>
|
|
199
238
|
{Number.isFinite(markerStep) &&
|
|
200
239
|
geometry.points.map((point, pointIndex) => pointIndex % markerStep === 0 && (
|
|
201
240
|
<circle
|
|
241
|
+
data-ui-chart-datum={pointActions[index]?.[pointIndex]?.serialized}
|
|
242
|
+
data-ui-chart-motion-key={getLumenChartMotionKey(item.id, point)}
|
|
202
243
|
class="ui-line-chart__point"
|
|
203
244
|
cx={point.xCoordinate}
|
|
204
245
|
cy={point.yCoordinate}
|
|
205
246
|
r="3"
|
|
206
247
|
>
|
|
207
248
|
<title>
|
|
208
|
-
{`${
|
|
249
|
+
{`${categoryLabelFor(point.x)} · ${item.label}: ${formatValue(point.y ?? 0)}`}
|
|
209
250
|
</title>
|
|
210
251
|
</circle>
|
|
211
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
|
+
))}
|
|
212
262
|
</g>
|
|
213
263
|
)
|
|
214
264
|
})
|
|
215
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} />}
|
|
216
273
|
</svg>
|
|
217
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} />}
|
|
218
277
|
{
|
|
219
278
|
showTable && hasData && (
|
|
220
279
|
<details class="ui-chart__data">
|
|
221
280
|
<summary>{resolvedLabels.viewData}</summary>
|
|
222
|
-
<div>
|
|
281
|
+
<div role="group" tabindex="0" aria-label={resolvedLabels.chartData}>
|
|
223
282
|
<table>
|
|
224
283
|
<thead>
|
|
225
284
|
<tr>
|
|
@@ -231,7 +290,7 @@ const referenceY =
|
|
|
231
290
|
{categories.map(category => (
|
|
232
291
|
<tr>
|
|
233
292
|
<th scope="row">{categoryLabelFor(category)}</th>
|
|
234
|
-
{
|
|
293
|
+
{alignedSeries.map(item => {
|
|
235
294
|
const datum = valueFor(item, category)
|
|
236
295
|
|
|
237
296
|
return (
|
|
@@ -251,4 +310,5 @@ const referenceY =
|
|
|
251
310
|
</details>
|
|
252
311
|
)
|
|
253
312
|
}
|
|
313
|
+
{drilldown && <ChartDatumActions actions={datumActions} label={resolvedLabels.exploreData} />}
|
|
254
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>}
|