@santi020k/lumen-astro 0.3.0 → 1.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 +100 -2
- package/components/Accordion.astro +4 -4
- package/components/Affix.astro +2 -2
- package/components/Agenda.astro +3 -2
- package/components/Alert.astro +9 -9
- package/components/AlertDialog.astro +7 -13
- package/components/Anchor.astro +29 -3
- package/components/AnimatedLogo.astro +2 -1
- package/components/AnimatedNumber.astro +5 -2
- package/components/AnimatedPortrait.astro +46 -36
- package/components/AspectRatio.astro +10 -8
- package/components/Attachment.astro +24 -24
- package/components/Autocomplete.astro +3 -2
- package/components/Avatar.astro +4 -3
- package/components/BackToTop.astro +2 -2
- package/components/Badge.astro +9 -9
- package/components/BarChart.astro +211 -0
- package/components/Breadcrumb.astro +3 -3
- package/components/Bubble.astro +7 -7
- package/components/Button.astro +18 -16
- package/components/ButtonGroup.astro +3 -3
- package/components/ButtonLink.astro +9 -3
- package/components/Calendar.astro +43 -31
- package/components/Callout.astro +2 -2
- package/components/Card.astro +12 -10
- package/components/CardContent.astro +26 -0
- package/components/CardDescription.astro +26 -0
- package/components/CardFooter.astro +26 -0
- package/components/CardHeader.astro +26 -0
- package/components/CardTitle.astro +26 -0
- package/components/Carousel.astro +6 -6
- package/components/Cascader.astro +10 -4
- package/components/Chart.astro +32 -6
- package/components/Checkbox.astro +3 -2
- package/components/CheckboxGroup.astro +39 -0
- package/components/Code.astro +55 -52
- package/components/CodeTabs.astro +6 -6
- package/components/Collapsible.astro +3 -3
- package/components/ColorPicker.astro +3 -2
- package/components/Combobox.astro +4 -5
- package/components/Command.astro +6 -6
- package/components/Container.astro +29 -0
- package/components/ContextMenu.astro +7 -13
- package/components/CopyButton.astro +55 -0
- package/components/CoverImage.astro +19 -9
- package/components/DataTable.astro +50 -49
- package/components/DatePicker.astro +20 -17
- package/components/DateRangePicker.astro +3 -2
- package/components/Descriptions.astro +3 -3
- package/components/Dialog.astro +8 -14
- package/components/Direction.astro +3 -3
- package/components/Drawer.astro +7 -13
- package/components/DropdownMenu.astro +7 -13
- package/components/Empty.astro +6 -6
- package/components/ErrorSummary.astro +54 -0
- package/components/Eyebrow.astro +2 -2
- package/components/Field.astro +7 -6
- package/components/FieldError.astro +29 -0
- package/components/FileUpload.astro +2 -2
- package/components/FloatingBadge.astro +2 -2
- package/components/Form.astro +33 -0
- package/components/FormattedDate.astro +2 -2
- package/components/GradientDivider.astro +2 -2
- package/components/Grid.astro +46 -0
- package/components/HoverCard.astro +7 -13
- package/components/Icon.astro +8 -6
- package/components/Image.astro +2 -1
- package/components/Input.astro +6 -5
- package/components/InputGroup.astro +3 -3
- package/components/InputOTP.astro +5 -3
- package/components/Item.astro +11 -8
- package/components/Kbd.astro +3 -3
- package/components/Label.astro +3 -2
- package/components/LanguageToggle.astro +2 -2
- package/components/LineChart.astro +244 -0
- package/components/Link.astro +6 -5
- package/components/ListBox.astro +154 -0
- package/components/Marker.astro +6 -6
- package/components/Mentions.astro +30 -10
- package/components/Menubar.astro +7 -13
- package/components/Message.astro +5 -5
- package/components/MessageScroller.astro +6 -6
- package/components/Meter.astro +1 -0
- package/components/NativeSelect.astro +4 -5
- package/components/NavigationMenu.astro +9 -14
- package/components/Note.astro +1 -1
- package/components/NumberField.astro +3 -2
- package/components/Pagination.astro +3 -3
- package/components/Particles.astro +58 -2
- package/components/PasswordField.astro +73 -0
- package/components/PhoneInput.astro +5 -7
- package/components/PieChart.astro +141 -0
- package/components/Pill.astro +15 -9
- package/components/Popconfirm.astro +8 -3
- package/components/Popover.astro +7 -13
- package/components/Progress.astro +12 -4
- package/components/Prose.astro +2 -2
- package/components/QRCode.astro +13 -5
- package/components/RadioGroup.astro +3 -3
- package/components/Rating.astro +3 -1
- package/components/Resizable.astro +8 -7
- package/components/RevealGroup.astro +4 -2
- package/components/RichTextEditor.astro +3 -2
- package/components/Schedule.astro +3 -2
- package/components/ScrollArea.astro +6 -6
- package/components/ScrollProgress.astro +38 -0
- package/components/ScrollReveal.astro +4 -2
- package/components/SearchField.astro +3 -2
- package/components/Segmented.astro +4 -6
- package/components/Select.astro +23 -14
- package/components/Separator.astro +5 -5
- package/components/Sheet.astro +7 -13
- package/components/Sidebar.astro +9 -14
- package/components/Skeleton.astro +4 -3
- package/components/SkipLink.astro +2 -2
- package/components/Slider.astro +3 -2
- package/components/Sonner.astro +3 -3
- package/components/Sparkline.astro +72 -0
- package/components/SpeedDial.astro +3 -3
- package/components/Spinner.astro +4 -3
- package/components/Stack.astro +46 -0
- package/components/Stat.astro +14 -8
- package/components/StatDescription.astro +16 -0
- package/components/StatIcon.astro +15 -0
- package/components/StatLabel.astro +16 -0
- package/components/StatTrend.astro +28 -0
- package/components/StatValue.astro +16 -0
- package/components/Stepper.astro +11 -8
- package/components/Switch.astro +3 -2
- package/components/Table.astro +7 -6
- package/components/Tabs.astro +6 -6
- package/components/TagGroup.astro +3 -2
- package/components/Textarea.astro +3 -2
- package/components/ThemeBuilder.astro +3 -2
- package/components/ThemeToggle.astro +5 -3
- package/components/TimeField.astro +3 -2
- package/components/Timeline.astro +2 -1
- package/components/TimelineItem.astro +2 -1
- package/components/Toast.astro +10 -16
- package/components/Toggle.astro +3 -2
- package/components/ToggleGroup.astro +3 -3
- package/components/Toolbar.astro +2 -2
- package/components/Tooltip.astro +3 -3
- package/components/Tour.astro +3 -3
- package/components/Transfer.astro +16 -5
- package/components/Tree.astro +3 -2
- package/components/TreeGrid.astro +3 -2
- package/components/TreeSelect.astro +10 -4
- package/components/Typography.astro +3 -3
- package/components/VirtualList.astro +3 -2
- package/components/VisuallyHidden.astro +27 -0
- package/components/Watermark.astro +11 -7
- package/forms.ts +46 -0
- package/index.ts +31 -0
- package/package.json +12 -8
- package/runtime/UIPrimitives.astro +3764 -3142
- package/runtime/controllers/motion.ts +13 -16
- package/index.d.ts +0 -126
|
@@ -1,37 +1,31 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { resolveLumenAstroProps, resolveLumenGlass } from '@santi020k/lumen-core'
|
|
3
|
-
|
|
4
2
|
import type { HTMLAttributes } from 'astro/types'
|
|
5
3
|
|
|
4
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
5
|
+
|
|
6
6
|
interface Props extends HTMLAttributes<'aside'> {
|
|
7
7
|
class?: string | null
|
|
8
8
|
className?: string
|
|
9
9
|
glass?: boolean | 'subtle' | 'strong'
|
|
10
|
-
/**
|
|
11
|
-
* @deprecated Use `glass` instead. `surface="glass"` maps to `glass={true}`.
|
|
12
|
-
*/
|
|
13
|
-
surface?: 'default' | 'glass'
|
|
14
10
|
}
|
|
15
11
|
|
|
16
12
|
const {
|
|
17
13
|
class: classProp = '',
|
|
18
14
|
className = '',
|
|
19
15
|
glass = false,
|
|
20
|
-
surface = 'default',
|
|
21
16
|
...rest
|
|
22
17
|
} = Astro.props
|
|
23
18
|
|
|
24
|
-
const resolvedGlass = resolveLumenGlass(glass, surface)
|
|
25
19
|
const { classList, passthrough } = resolveLumenAstroProps(rest, [
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
20
|
+
'ui-hover-card',
|
|
21
|
+
glass && 'ui-hover-card--glass',
|
|
22
|
+
glass === 'subtle' && 'ui-glass-subtle',
|
|
23
|
+
glass === 'strong' && 'ui-glass-strong'
|
|
30
24
|
], classProp, className)
|
|
31
25
|
---
|
|
32
26
|
|
|
33
27
|
<aside
|
|
34
|
-
data-surface={
|
|
28
|
+
data-surface={glass ? 'glass' : 'default'}
|
|
35
29
|
data-ui-hover-card
|
|
36
30
|
class:list={classList}
|
|
37
31
|
{...passthrough}
|
package/components/Icon.astro
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
3
|
+
|
|
2
4
|
import {
|
|
5
|
+
type LumenIconName,
|
|
3
6
|
renderLumenIconSvg,
|
|
4
|
-
resolveLumenAstroProps
|
|
5
|
-
type LumenIconName
|
|
6
|
-
} from '@santi020k/lumen-core'
|
|
7
|
-
|
|
8
|
-
import type { HTMLAttributes } from 'astro/types'
|
|
7
|
+
resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
9
8
|
|
|
10
9
|
type IconSize = 'default' | 'lg' | 'sm' | 'xl'
|
|
11
10
|
|
|
@@ -32,7 +31,10 @@ const isDecorative = decorative ?? !label
|
|
|
32
31
|
const iconSvg = name ? renderLumenIconSvg(name) : ''
|
|
33
32
|
|
|
34
33
|
if (name && !iconSvg && import.meta.env.DEV) {
|
|
35
|
-
console.warn(
|
|
34
|
+
console.warn(
|
|
35
|
+
`[Lumen Icon] Unknown icon "${name}". ` +
|
|
36
|
+
'Register an icon pack or use the default slot for project-specific SVGs.'
|
|
37
|
+
)
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
const { classList, passthrough } = resolveLumenAstroProps(rest, [
|
package/components/Image.astro
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
3
2
|
import {
|
|
4
3
|
Image as AstroImage,
|
|
5
4
|
type LocalImageProps,
|
|
6
5
|
type RemoteImageProps
|
|
7
6
|
} from 'astro:assets'
|
|
8
7
|
|
|
8
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
9
|
+
|
|
9
10
|
type Props = (LocalImageProps | RemoteImageProps) & {
|
|
10
11
|
class?: string | null
|
|
11
12
|
className?: string
|
package/components/Input.astro
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
3
|
-
|
|
4
2
|
import type { HTMLAttributes } from 'astro/types'
|
|
5
3
|
|
|
4
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
5
|
+
|
|
6
6
|
interface Props extends Omit<HTMLAttributes<'input'>, 'size'> {
|
|
7
7
|
class?: string | null
|
|
8
8
|
className?: string
|
|
@@ -10,10 +10,11 @@ interface Props extends Omit<HTMLAttributes<'input'>, 'size'> {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
const { class: classProp = '', className = '', size = 'default', type = 'text', ...rest } = Astro.props
|
|
13
|
+
|
|
13
14
|
const { classList, passthrough } = resolveLumenAstroProps(rest, [
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
'ui-input',
|
|
16
|
+
size === 'sm' && 'ui-input--sm',
|
|
17
|
+
size === 'lg' && 'ui-input--lg'
|
|
17
18
|
], classProp, className)
|
|
18
19
|
---
|
|
19
20
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
3
|
-
|
|
4
2
|
import type { HTMLAttributes } from 'astro/types'
|
|
5
3
|
|
|
4
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
5
|
+
|
|
6
6
|
interface Props extends HTMLAttributes<'div'> {
|
|
7
7
|
class?: string | null
|
|
8
8
|
className?: string
|
|
@@ -15,7 +15,7 @@ const {
|
|
|
15
15
|
} = Astro.props
|
|
16
16
|
|
|
17
17
|
const { classList, passthrough } = resolveLumenAstroProps(rest, [
|
|
18
|
-
|
|
18
|
+
'ui-input-group'
|
|
19
19
|
], classProp, className)
|
|
20
20
|
---
|
|
21
21
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
3
|
-
|
|
4
2
|
import type { HTMLAttributes } from 'astro/types'
|
|
5
3
|
|
|
4
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
5
|
+
|
|
6
6
|
interface Props extends Omit<HTMLAttributes<'input'>, 'size'> {
|
|
7
7
|
class?: string | null
|
|
8
8
|
className?: string
|
|
@@ -20,9 +20,11 @@ const {
|
|
|
20
20
|
pattern = '[0-9]*',
|
|
21
21
|
...rest
|
|
22
22
|
} = Astro.props
|
|
23
|
+
|
|
23
24
|
const { classList, passthrough } = resolveLumenAstroProps(rest, ['ui-input-otp-field'
|
|
24
25
|
], classProp, className)
|
|
25
|
-
|
|
26
|
+
|
|
27
|
+
const segments = Array.from({ length: Math.max(1, length || 6) }, (_, index) => index)
|
|
26
28
|
---
|
|
27
29
|
|
|
28
30
|
<div
|
package/components/Item.astro
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
3
|
-
|
|
4
2
|
import type { HTMLAttributes } from 'astro/types'
|
|
5
3
|
|
|
4
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
5
|
+
|
|
6
6
|
interface Props extends HTMLAttributes<'div'> {
|
|
7
|
+
as?: 'article' | 'div' | 'li' | 'section'
|
|
7
8
|
class?: string | null
|
|
8
9
|
className?: string
|
|
9
10
|
glass?: boolean | 'subtle' | 'strong'
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
const {
|
|
14
|
+
as: Tag = 'div',
|
|
13
15
|
class: classProp = '',
|
|
14
16
|
className = '',
|
|
15
17
|
glass = false,
|
|
@@ -17,16 +19,17 @@ const {
|
|
|
17
19
|
} = Astro.props
|
|
18
20
|
|
|
19
21
|
const { classList, passthrough } = resolveLumenAstroProps(rest, [
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
'ui-item',
|
|
23
|
+
glass && 'ui-item--glass',
|
|
24
|
+
glass === 'subtle' && 'ui-glass-subtle',
|
|
25
|
+
glass === 'strong' && 'ui-glass-strong'
|
|
24
26
|
], classProp, className)
|
|
25
27
|
---
|
|
26
28
|
|
|
27
|
-
<
|
|
29
|
+
<Tag
|
|
28
30
|
class:list={classList}
|
|
31
|
+
data-slot="item"
|
|
29
32
|
{...passthrough}
|
|
30
33
|
>
|
|
31
34
|
<slot />
|
|
32
|
-
</
|
|
35
|
+
</Tag>
|
package/components/Kbd.astro
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
3
|
-
|
|
4
2
|
import type { HTMLAttributes } from 'astro/types'
|
|
5
3
|
|
|
4
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
5
|
+
|
|
6
6
|
interface Props extends HTMLAttributes<'kbd'> {
|
|
7
7
|
class?: string | null
|
|
8
8
|
className?: string
|
|
@@ -15,7 +15,7 @@ const {
|
|
|
15
15
|
} = Astro.props
|
|
16
16
|
|
|
17
17
|
const { classList, passthrough } = resolveLumenAstroProps(rest, [
|
|
18
|
-
|
|
18
|
+
'ui-kbd'
|
|
19
19
|
], classProp, className)
|
|
20
20
|
---
|
|
21
21
|
|
package/components/Label.astro
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
3
|
-
|
|
4
2
|
import type { HTMLAttributes } from 'astro/types'
|
|
5
3
|
|
|
4
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
5
|
+
|
|
6
6
|
interface Props extends HTMLAttributes<'label'> {
|
|
7
7
|
class?: string | null
|
|
8
8
|
className?: string
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
const { class: classProp = '', className = '', ...rest } = Astro.props
|
|
12
|
+
|
|
12
13
|
const { classList, passthrough } = resolveLumenAstroProps(rest, ['ui-label'
|
|
13
14
|
], classProp, className)
|
|
14
15
|
---
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
3
|
-
|
|
4
2
|
import type { HTMLAttributes } from 'astro/types'
|
|
5
3
|
|
|
4
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
5
|
+
|
|
6
6
|
interface Props extends HTMLAttributes<'button'> {
|
|
7
7
|
class?: string | null
|
|
8
8
|
className?: string
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
alignLumenChartSeries,
|
|
6
|
+
createLumenLineGeometry,
|
|
7
|
+
getLumenChartCategories,
|
|
8
|
+
getLumenChartDomain,
|
|
9
|
+
getLumenChartTicks,
|
|
10
|
+
getLumenChartToneClassName,
|
|
11
|
+
hasLumenChartData,
|
|
12
|
+
type LumenChartSeries,
|
|
13
|
+
resolveLumenChartTone,
|
|
14
|
+
scaleLumenChartValue
|
|
15
|
+
} from '@santi020k/lumen-core'
|
|
16
|
+
|
|
17
|
+
import Chart from './Chart.astro'
|
|
18
|
+
|
|
19
|
+
interface Props extends HTMLAttributes<'figure'> {
|
|
20
|
+
area?: boolean
|
|
21
|
+
caption?: string
|
|
22
|
+
class?: string | null
|
|
23
|
+
className?: string
|
|
24
|
+
description?: string
|
|
25
|
+
emptyLabel?: string
|
|
26
|
+
formatCategory?: (category: number | string) => string
|
|
27
|
+
formatValue?: (value: number) => string
|
|
28
|
+
glass?: boolean | 'subtle' | 'strong'
|
|
29
|
+
heading?: string
|
|
30
|
+
markers?: 'all' | 'auto' | 'none' | boolean | number
|
|
31
|
+
presentation?: 'bare' | 'default'
|
|
32
|
+
referenceValue?: number
|
|
33
|
+
series: readonly LumenChartSeries[]
|
|
34
|
+
showLegend?: boolean
|
|
35
|
+
showTable?: boolean
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const {
|
|
39
|
+
area = false,
|
|
40
|
+
caption,
|
|
41
|
+
class: classProp = '',
|
|
42
|
+
className = '',
|
|
43
|
+
description,
|
|
44
|
+
emptyLabel = 'No chart data available.',
|
|
45
|
+
formatCategory = String,
|
|
46
|
+
formatValue = String,
|
|
47
|
+
glass = false,
|
|
48
|
+
heading,
|
|
49
|
+
markers = 'auto',
|
|
50
|
+
referenceValue,
|
|
51
|
+
series,
|
|
52
|
+
showLegend = series.length > 1,
|
|
53
|
+
showTable = true,
|
|
54
|
+
...rest
|
|
55
|
+
} = Astro.props
|
|
56
|
+
|
|
57
|
+
const width = 640
|
|
58
|
+
const height = 320
|
|
59
|
+
const padding = 44
|
|
60
|
+
const categories = getLumenChartCategories(series)
|
|
61
|
+
const hasData = hasLumenChartData(series)
|
|
62
|
+
const alignedSeries = series.map(item => alignLumenChartSeries(item, categories))
|
|
63
|
+
|
|
64
|
+
const domain = getLumenChartDomain([
|
|
65
|
+
...alignedSeries.flatMap(item => item.data.map(datum => datum.y)),
|
|
66
|
+
referenceValue ?? null
|
|
67
|
+
], false)
|
|
68
|
+
|
|
69
|
+
const geometries = alignedSeries.map(item => createLumenLineGeometry(item.data, {
|
|
70
|
+
domain,
|
|
71
|
+
height,
|
|
72
|
+
includeZero: false,
|
|
73
|
+
padding,
|
|
74
|
+
width
|
|
75
|
+
}))
|
|
76
|
+
|
|
77
|
+
const ticks = getLumenChartTicks(domain)
|
|
78
|
+
const labelStep = Math.max(1, Math.ceil(categories.length / 8))
|
|
79
|
+
let markerStep = 1
|
|
80
|
+
|
|
81
|
+
if (markers === false || markers === 'none') markerStep = Number.POSITIVE_INFINITY
|
|
82
|
+
else if (typeof markers === 'number') markerStep = Math.max(1, Math.round(markers))
|
|
83
|
+
else if (markers === 'auto') markerStep = Math.max(1, Math.ceil(categories.length / 24))
|
|
84
|
+
|
|
85
|
+
const valueFor = (item: LumenChartSeries, category: number | string) => item.data.find(datum => datum.x === category)
|
|
86
|
+
|
|
87
|
+
const categoryLabelFor = (category: number | string) => series.flatMap(item => item.data)
|
|
88
|
+
.find(datum => datum.x === category)?.xLabel ?? formatCategory(category)
|
|
89
|
+
|
|
90
|
+
const referenceY =
|
|
91
|
+
referenceValue === undefined ?
|
|
92
|
+
undefined :
|
|
93
|
+
scaleLumenChartValue(referenceValue, domain, height - padding, padding)
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
<Chart
|
|
97
|
+
class:list={['ui-line-chart', classProp, className]}
|
|
98
|
+
{caption}
|
|
99
|
+
{description}
|
|
100
|
+
{glass}
|
|
101
|
+
{heading}
|
|
102
|
+
{...rest}
|
|
103
|
+
>
|
|
104
|
+
{
|
|
105
|
+
showLegend && hasData && (
|
|
106
|
+
<ul class="ui-chart__legend" aria-label="Chart legend">
|
|
107
|
+
{series.map((item, index) => (
|
|
108
|
+
<li class={getLumenChartToneClassName(item.tone, index)}>
|
|
109
|
+
<span aria-hidden="true" />
|
|
110
|
+
{item.label}
|
|
111
|
+
</li>
|
|
112
|
+
))}
|
|
113
|
+
</ul>
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
{!hasData && <p class="ui-chart__empty" role="status">{emptyLabel}</p>}
|
|
117
|
+
<div class="ui-chart__plot" hidden={!hasData}>
|
|
118
|
+
<svg
|
|
119
|
+
aria-hidden="true"
|
|
120
|
+
preserveAspectRatio="xMidYMid meet"
|
|
121
|
+
viewBox={`0 0 ${width} ${height}`}
|
|
122
|
+
>
|
|
123
|
+
<g class="ui-chart__grid">
|
|
124
|
+
{
|
|
125
|
+
ticks.map(tick => {
|
|
126
|
+
const y = scaleLumenChartValue(
|
|
127
|
+
tick, domain, height - padding, padding
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
<>
|
|
132
|
+
<line x1={padding} x2={width - padding} y1={y} y2={y} />
|
|
133
|
+
<text x={padding - 8} y={y}>
|
|
134
|
+
{formatValue(tick)}
|
|
135
|
+
</text>
|
|
136
|
+
</>
|
|
137
|
+
)
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
</g>
|
|
141
|
+
<g class="ui-chart__axis-labels">
|
|
142
|
+
{
|
|
143
|
+
categories.map((category, index) => {
|
|
144
|
+
if (
|
|
145
|
+
index % labelStep !== 0 &&
|
|
146
|
+
index !== categories.length - 1
|
|
147
|
+
)
|
|
148
|
+
return null
|
|
149
|
+
|
|
150
|
+
const denominator = Math.max(1, categories.length - 1)
|
|
151
|
+
|
|
152
|
+
const x =
|
|
153
|
+
padding + (index / denominator) * (width - padding * 2)
|
|
154
|
+
|
|
155
|
+
return (
|
|
156
|
+
<text text-anchor="middle" x={x} y={height - 14}>
|
|
157
|
+
{categoryLabelFor(category)}
|
|
158
|
+
</text>
|
|
159
|
+
)
|
|
160
|
+
})
|
|
161
|
+
}
|
|
162
|
+
</g>
|
|
163
|
+
{
|
|
164
|
+
referenceY !== undefined && (
|
|
165
|
+
<line
|
|
166
|
+
class="ui-chart__reference"
|
|
167
|
+
x1={padding}
|
|
168
|
+
x2={width - padding}
|
|
169
|
+
y1={referenceY}
|
|
170
|
+
y2={referenceY}
|
|
171
|
+
/>
|
|
172
|
+
)
|
|
173
|
+
}
|
|
174
|
+
{
|
|
175
|
+
geometries.map((geometry, index) => {
|
|
176
|
+
const item = series[index]
|
|
177
|
+
|
|
178
|
+
if (!item) return null
|
|
179
|
+
|
|
180
|
+
const tone = resolveLumenChartTone(item.tone, index)
|
|
181
|
+
|
|
182
|
+
return (
|
|
183
|
+
<g class:list={['ui-line-chart__series', getLumenChartToneClassName(tone)]}>
|
|
184
|
+
{area &&
|
|
185
|
+
geometry.areaPaths.map(path => (
|
|
186
|
+
<path class="ui-line-chart__area" d={path} />
|
|
187
|
+
))}
|
|
188
|
+
<path class="ui-line-chart__line" d={geometry.path} />
|
|
189
|
+
{Number.isFinite(markerStep) &&
|
|
190
|
+
geometry.points.map((point, pointIndex) => pointIndex % markerStep === 0 && (
|
|
191
|
+
<circle
|
|
192
|
+
class="ui-line-chart__point"
|
|
193
|
+
cx={point.xCoordinate}
|
|
194
|
+
cy={point.yCoordinate}
|
|
195
|
+
r="3"
|
|
196
|
+
>
|
|
197
|
+
<title>
|
|
198
|
+
{`${point.xLabel ?? formatCategory(point.x)} · ${item.label}: ${formatValue(point.y ?? 0)}`}
|
|
199
|
+
</title>
|
|
200
|
+
</circle>
|
|
201
|
+
))}
|
|
202
|
+
</g>
|
|
203
|
+
)
|
|
204
|
+
})
|
|
205
|
+
}
|
|
206
|
+
</svg>
|
|
207
|
+
</div>
|
|
208
|
+
{
|
|
209
|
+
showTable && hasData && (
|
|
210
|
+
<details class="ui-chart__data">
|
|
211
|
+
<summary>View chart data</summary>
|
|
212
|
+
<div>
|
|
213
|
+
<table>
|
|
214
|
+
<thead>
|
|
215
|
+
<tr>
|
|
216
|
+
<th scope="col">Category</th>
|
|
217
|
+
{series.map(item => <th scope="col">{item.label}</th>)}
|
|
218
|
+
</tr>
|
|
219
|
+
</thead>
|
|
220
|
+
<tbody>
|
|
221
|
+
{categories.map(category => (
|
|
222
|
+
<tr>
|
|
223
|
+
<th scope="row">{categoryLabelFor(category)}</th>
|
|
224
|
+
{series.map(item => {
|
|
225
|
+
const datum = valueFor(item, category)
|
|
226
|
+
|
|
227
|
+
return (
|
|
228
|
+
<td>
|
|
229
|
+
{datum?.label ??
|
|
230
|
+
(datum?.y === null || datum === undefined ?
|
|
231
|
+
'Not available' :
|
|
232
|
+
formatValue(datum.y))}
|
|
233
|
+
</td>
|
|
234
|
+
)
|
|
235
|
+
})}
|
|
236
|
+
</tr>
|
|
237
|
+
))}
|
|
238
|
+
</tbody>
|
|
239
|
+
</table>
|
|
240
|
+
</div>
|
|
241
|
+
</details>
|
|
242
|
+
)
|
|
243
|
+
}
|
|
244
|
+
</Chart>
|
package/components/Link.astro
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
3
|
-
|
|
4
2
|
import type { HTMLAttributes } from 'astro/types'
|
|
5
3
|
|
|
4
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
5
|
+
|
|
6
6
|
interface Props extends HTMLAttributes<'a'> {
|
|
7
7
|
class?: string | null
|
|
8
8
|
className?: string
|
|
@@ -25,13 +25,14 @@ const { classList, passthrough } = resolveLumenAstroProps(rest, [
|
|
|
25
25
|
variant === 'inherit' && 'ui-link--inherit'
|
|
26
26
|
], classProp, className)
|
|
27
27
|
|
|
28
|
-
const safeRel = newTab
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
const safeRel = newTab ?
|
|
29
|
+
[...new Set(`${rel ?? ''} noopener noreferrer`.trim().split(/\s+/))].join(' ') :
|
|
30
|
+
rel
|
|
31
31
|
---
|
|
32
32
|
|
|
33
33
|
<a
|
|
34
34
|
class:list={classList}
|
|
35
|
+
data-slot="link"
|
|
35
36
|
data-variant={variant}
|
|
36
37
|
rel={safeRel}
|
|
37
38
|
target={newTab ? '_blank' : target}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
3
|
+
|
|
4
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
5
|
+
|
|
6
|
+
interface ListBoxOption {
|
|
7
|
+
disabled?: boolean
|
|
8
|
+
label: string
|
|
9
|
+
section?: string
|
|
10
|
+
value: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface Props extends Omit<HTMLAttributes<'select'>, 'size' | 'value'> {
|
|
14
|
+
class?: string | null
|
|
15
|
+
className?: string
|
|
16
|
+
emptyMessage?: string
|
|
17
|
+
label?: string
|
|
18
|
+
loading?: boolean
|
|
19
|
+
loadingMessage?: string
|
|
20
|
+
multiple?: boolean
|
|
21
|
+
options?: (ListBoxOption | string)[]
|
|
22
|
+
selectionFollowsFocus?: boolean
|
|
23
|
+
value?: string | string[]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const {
|
|
27
|
+
class: classProp = '',
|
|
28
|
+
className = '',
|
|
29
|
+
disabled = false,
|
|
30
|
+
emptyMessage = 'No options available',
|
|
31
|
+
id,
|
|
32
|
+
label,
|
|
33
|
+
loading = false,
|
|
34
|
+
loadingMessage = 'Loading options',
|
|
35
|
+
multiple = false,
|
|
36
|
+
name,
|
|
37
|
+
options = [],
|
|
38
|
+
required = false,
|
|
39
|
+
selectionFollowsFocus = false,
|
|
40
|
+
value,
|
|
41
|
+
...rest
|
|
42
|
+
} = Astro.props
|
|
43
|
+
|
|
44
|
+
const normalizedOptions = options.map(option => typeof option === 'string' ? { label: option, value: option } : option)
|
|
45
|
+
const optionGroups: { label?: string, options: ListBoxOption[] }[] = []
|
|
46
|
+
|
|
47
|
+
for (const option of normalizedOptions) {
|
|
48
|
+
const currentGroup = optionGroups.at(-1)
|
|
49
|
+
|
|
50
|
+
if (!currentGroup || currentGroup.label !== option.section) {
|
|
51
|
+
optionGroups.push({
|
|
52
|
+
...(option.section ? { label: option.section } : {}),
|
|
53
|
+
options: [option]
|
|
54
|
+
})
|
|
55
|
+
} else {
|
|
56
|
+
currentGroup.options.push(option)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let initialValues: string[] = []
|
|
61
|
+
|
|
62
|
+
if (Array.isArray(value)) initialValues = value
|
|
63
|
+
else if (value !== undefined) initialValues = [value]
|
|
64
|
+
|
|
65
|
+
const selectedValues = new Set(initialValues)
|
|
66
|
+
const controlId = id ?? `ui-list-box-${name ?? 'field'}`
|
|
67
|
+
const listId = `${controlId}-list`
|
|
68
|
+
const { classList, passthrough } = resolveLumenAstroProps(rest, ['ui-list-box'], classProp, className)
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
<div
|
|
72
|
+
class:list={classList}
|
|
73
|
+
data-loading={loading ? 'true' : undefined}
|
|
74
|
+
data-multiple={multiple ? 'true' : undefined}
|
|
75
|
+
data-selection-follows-focus={selectionFollowsFocus ? 'true' : undefined}
|
|
76
|
+
data-ui-list-box
|
|
77
|
+
>
|
|
78
|
+
{label && <label class="ui-label" for={controlId}>{label}</label>}
|
|
79
|
+
<select
|
|
80
|
+
class="ui-list-box__native"
|
|
81
|
+
data-ui-list-box-native
|
|
82
|
+
disabled={disabled || loading}
|
|
83
|
+
id={controlId}
|
|
84
|
+
multiple={multiple}
|
|
85
|
+
name={name}
|
|
86
|
+
required={required}
|
|
87
|
+
size={Math.min(Math.max(normalizedOptions.length, 2), 8)}
|
|
88
|
+
{...passthrough}
|
|
89
|
+
>
|
|
90
|
+
{optionGroups.map(group => group.label ?
|
|
91
|
+
(
|
|
92
|
+
<optgroup label={group.label}>
|
|
93
|
+
{group.options.map(option => (
|
|
94
|
+
<option
|
|
95
|
+
disabled={option.disabled}
|
|
96
|
+
selected={selectedValues.has(option.value)}
|
|
97
|
+
value={option.value}
|
|
98
|
+
>
|
|
99
|
+
{option.label}
|
|
100
|
+
</option>
|
|
101
|
+
))}
|
|
102
|
+
</optgroup>
|
|
103
|
+
) :
|
|
104
|
+
group.options.map(option => (
|
|
105
|
+
<option
|
|
106
|
+
disabled={option.disabled}
|
|
107
|
+
selected={selectedValues.has(option.value)}
|
|
108
|
+
value={option.value}
|
|
109
|
+
>
|
|
110
|
+
{option.label}
|
|
111
|
+
</option>
|
|
112
|
+
)))}
|
|
113
|
+
</select>
|
|
114
|
+
<div
|
|
115
|
+
aria-busy={loading ? 'true' : undefined}
|
|
116
|
+
aria-disabled={disabled || loading ? 'true' : undefined}
|
|
117
|
+
aria-multiselectable={multiple ? 'true' : undefined}
|
|
118
|
+
class="ui-list-box__list"
|
|
119
|
+
data-ui-list-box-list
|
|
120
|
+
hidden
|
|
121
|
+
id={listId}
|
|
122
|
+
role="listbox"
|
|
123
|
+
tabindex={disabled || loading ? undefined : '0'}
|
|
124
|
+
>
|
|
125
|
+
{!loading && !normalizedOptions.length && (
|
|
126
|
+
<div aria-disabled="true" class="ui-list-box__empty" role="option">{emptyMessage}</div>
|
|
127
|
+
)}
|
|
128
|
+
{!loading && optionGroups.map((group, groupIndex) => {
|
|
129
|
+
const groupLabelId = group.label ? `${controlId}-group-${groupIndex}` : undefined
|
|
130
|
+
|
|
131
|
+
const renderedOptions = group.options.map(option => (
|
|
132
|
+
<div
|
|
133
|
+
aria-disabled={option.disabled ? 'true' : undefined}
|
|
134
|
+
aria-selected={selectedValues.has(option.value) ? 'true' : 'false'}
|
|
135
|
+
data-ui-list-box-option
|
|
136
|
+
data-value={option.value}
|
|
137
|
+
role="option"
|
|
138
|
+
>
|
|
139
|
+
{option.label}
|
|
140
|
+
</div>
|
|
141
|
+
))
|
|
142
|
+
|
|
143
|
+
return group.label ?
|
|
144
|
+
(
|
|
145
|
+
<div aria-labelledby={groupLabelId} role="group">
|
|
146
|
+
<div class="ui-list-box__section" id={groupLabelId}>{group.label}</div>
|
|
147
|
+
{renderedOptions}
|
|
148
|
+
</div>
|
|
149
|
+
) :
|
|
150
|
+
renderedOptions
|
|
151
|
+
})}
|
|
152
|
+
</div>
|
|
153
|
+
{loading && <p class="ui-list-box__status" role="status">{loadingMessage}</p>}
|
|
154
|
+
</div>
|