@santi020k/lumen-astro 0.1.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/LICENSE +21 -0
- package/README.md +142 -0
- package/components/Accordion.astro +27 -0
- package/components/Affix.astro +41 -0
- package/components/Agenda.astro +19 -0
- package/components/Alert.astro +38 -0
- package/components/AlertDialog.astro +41 -0
- package/components/Anchor.astro +43 -0
- package/components/AnimatedLogo.astro +30 -0
- package/components/AnimatedNumber.astro +56 -0
- package/components/AnimatedPortrait.astro +124 -0
- package/components/AspectRatio.astro +39 -0
- package/components/Attachment.astro +46 -0
- package/components/Autocomplete.astro +24 -0
- package/components/Avatar.astro +36 -0
- package/components/BackToTop.astro +30 -0
- package/components/Badge.astro +36 -0
- package/components/Breadcrumb.astro +28 -0
- package/components/Bubble.astro +36 -0
- package/components/Button.astro +52 -0
- package/components/ButtonGroup.astro +27 -0
- package/components/ButtonLink.astro +58 -0
- package/components/Calendar.astro +197 -0
- package/components/Callout.astro +27 -0
- package/components/Card.astro +40 -0
- package/components/Carousel.astro +33 -0
- package/components/Cascader.astro +109 -0
- package/components/Chart.astro +32 -0
- package/components/Checkbox.astro +22 -0
- package/components/Code.astro +96 -0
- package/components/Collapsible.astro +28 -0
- package/components/ColorPicker.astro +16 -0
- package/components/Combobox.astro +67 -0
- package/components/Command.astro +33 -0
- package/components/ContextMenu.astro +44 -0
- package/components/CoverImage.astro +180 -0
- package/components/DataTable.astro +122 -0
- package/components/DatePicker.astro +108 -0
- package/components/DateRangePicker.astro +18 -0
- package/components/Descriptions.astro +41 -0
- package/components/Dialog.astro +40 -0
- package/components/Direction.astro +30 -0
- package/components/Drawer.astro +40 -0
- package/components/DropdownMenu.astro +40 -0
- package/components/Empty.astro +32 -0
- package/components/Eyebrow.astro +27 -0
- package/components/Field.astro +42 -0
- package/components/FileUpload.astro +44 -0
- package/components/FloatingBadge.astro +27 -0
- package/components/FormattedDate.astro +27 -0
- package/components/GradientDivider.astro +24 -0
- package/components/HoverCard.astro +40 -0
- package/components/Icon.astro +50 -0
- package/components/Image.astro +33 -0
- package/components/Input.astro +24 -0
- package/components/InputGroup.astro +27 -0
- package/components/InputOTP.astro +60 -0
- package/components/Item.astro +32 -0
- package/components/Kbd.astro +27 -0
- package/components/Label.astro +18 -0
- package/components/LanguageToggle.astro +30 -0
- package/components/Link.astro +27 -0
- package/components/Marker.astro +33 -0
- package/components/Mentions.astro +47 -0
- package/components/Menubar.astro +40 -0
- package/components/Message.astro +32 -0
- package/components/MessageScroller.astro +32 -0
- package/components/Meter.astro +31 -0
- package/components/NativeSelect.astro +37 -0
- package/components/NavigationMenu.astro +40 -0
- package/components/Note.astro +23 -0
- package/components/NumberField.astro +16 -0
- package/components/Pagination.astro +28 -0
- package/components/Particles.astro +31 -0
- package/components/PhoneInput.astro +86 -0
- package/components/Pill.astro +30 -0
- package/components/Popconfirm.astro +40 -0
- package/components/Popover.astro +40 -0
- package/components/Progress.astro +30 -0
- package/components/Prose.astro +27 -0
- package/components/QRCode.astro +44 -0
- package/components/RadioGroup.astro +28 -0
- package/components/Rating.astro +42 -0
- package/components/Resizable.astro +55 -0
- package/components/RevealGroup.astro +54 -0
- package/components/RichTextEditor.astro +19 -0
- package/components/Schedule.astro +19 -0
- package/components/ScrollArea.astro +32 -0
- package/components/ScrollReveal.astro +50 -0
- package/components/SearchField.astro +16 -0
- package/components/Segmented.astro +56 -0
- package/components/Select.astro +120 -0
- package/components/Separator.astro +31 -0
- package/components/Sheet.astro +40 -0
- package/components/Sidebar.astro +39 -0
- package/components/Skeleton.astro +36 -0
- package/components/SkipLink.astro +27 -0
- package/components/Slider.astro +20 -0
- package/components/Sonner.astro +38 -0
- package/components/SpeedDial.astro +77 -0
- package/components/Spinner.astro +36 -0
- package/components/Stat.astro +34 -0
- package/components/Stepper.astro +57 -0
- package/components/Switch.astro +23 -0
- package/components/Table.astro +32 -0
- package/components/Tabs.astro +33 -0
- package/components/TagGroup.astro +18 -0
- package/components/Textarea.astro +17 -0
- package/components/ThemeBuilder.astro +19 -0
- package/components/ThemeToggle.astro +41 -0
- package/components/TimeField.astro +16 -0
- package/components/Timeline.astro +12 -0
- package/components/TimelineItem.astro +19 -0
- package/components/Toast.astro +50 -0
- package/components/Toggle.astro +25 -0
- package/components/ToggleGroup.astro +28 -0
- package/components/Toolbar.astro +36 -0
- package/components/Tooltip.astro +27 -0
- package/components/Tour.astro +52 -0
- package/components/Transfer.astro +70 -0
- package/components/Tree.astro +19 -0
- package/components/TreeGrid.astro +19 -0
- package/components/TreeSelect.astro +69 -0
- package/components/Typography.astro +27 -0
- package/components/VirtualList.astro +19 -0
- package/components/Watermark.astro +60 -0
- package/index.d.ts +125 -0
- package/index.ts +125 -0
- package/package.json +74 -0
- package/runtime/UIPrimitives.astro +4649 -0
- package/styles/lumen.css +5 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
3
|
+
|
|
4
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
5
|
+
|
|
6
|
+
interface CascaderOption {
|
|
7
|
+
children?: CascaderOption[]
|
|
8
|
+
label: string
|
|
9
|
+
value: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface Props extends HTMLAttributes<'div'> {
|
|
13
|
+
class?: string
|
|
14
|
+
className?: string
|
|
15
|
+
name?: string
|
|
16
|
+
options?: CascaderOption[]
|
|
17
|
+
placeholder?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const {
|
|
21
|
+
class: classProp = '',
|
|
22
|
+
className = '',
|
|
23
|
+
name,
|
|
24
|
+
options = [],
|
|
25
|
+
placeholder = 'Select…',
|
|
26
|
+
...rest
|
|
27
|
+
} = Astro.props
|
|
28
|
+
|
|
29
|
+
interface RenderedColumn {
|
|
30
|
+
id: string
|
|
31
|
+
options: { label: string; nextId?: string | undefined; value: string }[]
|
|
32
|
+
root: boolean
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const cascaderId = `ui-cascader-${Math.random().toString(36).slice(2)}`
|
|
36
|
+
const panelId = `${cascaderId}-panel`
|
|
37
|
+
let columnCount = 0
|
|
38
|
+
const columns: RenderedColumn[] = []
|
|
39
|
+
|
|
40
|
+
const buildColumn = (items: CascaderOption[], root: boolean): string => {
|
|
41
|
+
columnCount += 1
|
|
42
|
+
|
|
43
|
+
const id = `${cascaderId}-column-${columnCount}`
|
|
44
|
+
|
|
45
|
+
const rendered: RenderedColumn['options'] = items.map(item => ({
|
|
46
|
+
label: item.label,
|
|
47
|
+
value: item.value
|
|
48
|
+
}))
|
|
49
|
+
|
|
50
|
+
columns.push({ id, options: rendered, root })
|
|
51
|
+
|
|
52
|
+
for (const [index, item] of items.entries()) {
|
|
53
|
+
const renderedOption = rendered[index]
|
|
54
|
+
|
|
55
|
+
if (item.children && item.children.length > 0 && renderedOption) {
|
|
56
|
+
renderedOption.nextId = buildColumn(item.children, false)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return id
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (options.length > 0) {
|
|
64
|
+
buildColumn(options, true)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const { classList, passthrough } = resolveLumenAstroProps(rest, [
|
|
68
|
+
'ui-cascader'
|
|
69
|
+
], classProp, className)
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
<div class:list={classList} data-surface="default" data-ui-cascader data-ui-popover {...passthrough}>
|
|
73
|
+
<button
|
|
74
|
+
aria-controls={panelId}
|
|
75
|
+
aria-expanded="false"
|
|
76
|
+
aria-haspopup="listbox"
|
|
77
|
+
class="ui-select ui-select__trigger ui-cascader__trigger"
|
|
78
|
+
data-ui-trigger
|
|
79
|
+
role="combobox"
|
|
80
|
+
type="button"
|
|
81
|
+
>
|
|
82
|
+
<span data-ui-cascader-placeholder={placeholder} data-ui-cascader-value>{placeholder}</span>
|
|
83
|
+
</button>
|
|
84
|
+
<div class="ui-cascader__panel" data-ui-panel hidden id={panelId}>
|
|
85
|
+
{columns.map(column => (
|
|
86
|
+
<ol aria-label={column.root ? 'Options' : 'Sub-options'} class="ui-cascader__column" hidden={!column.root} id={column.id} role="listbox">
|
|
87
|
+
{column.options.map(option => (
|
|
88
|
+
<li role="presentation">
|
|
89
|
+
<button
|
|
90
|
+
aria-selected="false"
|
|
91
|
+
class="ui-cascader__option"
|
|
92
|
+
data-label={option.label}
|
|
93
|
+
data-ui-cascader-next={option.nextId ? `#${option.nextId}` : undefined}
|
|
94
|
+
data-ui-cascader-option
|
|
95
|
+
data-value={option.value}
|
|
96
|
+
role="option"
|
|
97
|
+
type="button"
|
|
98
|
+
>
|
|
99
|
+
<span>{option.label}</span>
|
|
100
|
+
{option.nextId && <span aria-hidden="true">›</span>}
|
|
101
|
+
</button>
|
|
102
|
+
</li>
|
|
103
|
+
))}
|
|
104
|
+
</ol>
|
|
105
|
+
))}
|
|
106
|
+
<slot />
|
|
107
|
+
</div>
|
|
108
|
+
{name && <input data-ui-cascader-input name={name} type="hidden" />}
|
|
109
|
+
</div>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
3
|
+
|
|
4
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
5
|
+
|
|
6
|
+
interface Props extends HTMLAttributes<'figure'> {
|
|
7
|
+
class?: string
|
|
8
|
+
className?: string
|
|
9
|
+
glass?: boolean | 'subtle' | 'strong'
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const {
|
|
13
|
+
class: classProp = '',
|
|
14
|
+
className = '',
|
|
15
|
+
glass = false,
|
|
16
|
+
...rest
|
|
17
|
+
} = Astro.props
|
|
18
|
+
|
|
19
|
+
const { classList, passthrough } = resolveLumenAstroProps(rest, [
|
|
20
|
+
'ui-chart',
|
|
21
|
+
glass && 'ui-chart--glass',
|
|
22
|
+
glass === 'subtle' && 'ui-glass-subtle',
|
|
23
|
+
glass === 'strong' && 'ui-glass-strong'
|
|
24
|
+
], classProp, className)
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
<figure
|
|
28
|
+
class:list={classList}
|
|
29
|
+
{...passthrough}
|
|
30
|
+
>
|
|
31
|
+
<slot />
|
|
32
|
+
</figure>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
3
|
+
|
|
4
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
5
|
+
|
|
6
|
+
type HTMLInputAttributes = HTMLAttributes<'input'>
|
|
7
|
+
|
|
8
|
+
interface Props extends Omit<HTMLInputAttributes, 'type'> {
|
|
9
|
+
class?: string
|
|
10
|
+
className?: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const { class: classProp = '', className = '', ...rest } = Astro.props
|
|
14
|
+
const { classList, passthrough } = resolveLumenAstroProps(rest, ['ui-checkbox'
|
|
15
|
+
], classProp, className)
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
<input
|
|
19
|
+
class:list={classList}
|
|
20
|
+
type="checkbox"
|
|
21
|
+
{...passthrough}
|
|
22
|
+
/>
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { renderLumenCodeHtml, renderLumenIconSvg, resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
3
|
+
|
|
4
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
5
|
+
|
|
6
|
+
type CodeTheme = 'auto' | 'lumen' | 'santi020k'
|
|
7
|
+
type CodeVariant = 'block' | 'inline'
|
|
8
|
+
|
|
9
|
+
interface Props extends HTMLAttributes<'code'> {
|
|
10
|
+
class?: string
|
|
11
|
+
className?: string
|
|
12
|
+
code?: string
|
|
13
|
+
copy?: boolean
|
|
14
|
+
highlighted?: boolean
|
|
15
|
+
label?: string
|
|
16
|
+
language?: string
|
|
17
|
+
theme?: CodeTheme
|
|
18
|
+
variant?: CodeVariant
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const {
|
|
22
|
+
class: classProp = '',
|
|
23
|
+
className = '',
|
|
24
|
+
code,
|
|
25
|
+
copy = false,
|
|
26
|
+
highlighted = false,
|
|
27
|
+
label,
|
|
28
|
+
language,
|
|
29
|
+
theme = 'auto',
|
|
30
|
+
variant = 'inline',
|
|
31
|
+
...rest
|
|
32
|
+
} = Astro.props
|
|
33
|
+
|
|
34
|
+
const { classList: blockClassList, passthrough } = resolveLumenAstroProps(rest, [
|
|
35
|
+
'ui-code',
|
|
36
|
+
'ui-code--block'
|
|
37
|
+
], classProp, className)
|
|
38
|
+
const { classList: inlineClassList } = resolveLumenAstroProps(rest, [
|
|
39
|
+
'ui-code',
|
|
40
|
+
'ui-code--inline'
|
|
41
|
+
], classProp, className)
|
|
42
|
+
const shouldShowHeader = variant === 'block' && Boolean(copy || label || language)
|
|
43
|
+
const hasCode = code !== undefined
|
|
44
|
+
const renderedCode = hasCode ? renderLumenCodeHtml(code, language) : ''
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
{variant === 'block' ? (
|
|
48
|
+
<figure
|
|
49
|
+
class:list={blockClassList}
|
|
50
|
+
data-code-theme={theme}
|
|
51
|
+
data-language={language}
|
|
52
|
+
data-ui-code
|
|
53
|
+
{...passthrough}
|
|
54
|
+
>
|
|
55
|
+
{shouldShowHeader && (
|
|
56
|
+
<figcaption class="ui-code__header">
|
|
57
|
+
<span class="ui-code__dots" aria-hidden="true">
|
|
58
|
+
<span class="ui-code__dot ui-code__dot--red"></span>
|
|
59
|
+
<span class="ui-code__dot ui-code__dot--yellow"></span>
|
|
60
|
+
<span class="ui-code__dot ui-code__dot--green"></span>
|
|
61
|
+
</span>
|
|
62
|
+
<span class="ui-code__meta">
|
|
63
|
+
{language && <span class="ui-code__language">{language}</span>}
|
|
64
|
+
{label && <span class="ui-code__label">{label}</span>}
|
|
65
|
+
</span>
|
|
66
|
+
{copy && (
|
|
67
|
+
<button
|
|
68
|
+
aria-label="Copy code to clipboard"
|
|
69
|
+
class="ui-code__copy"
|
|
70
|
+
data-ui-code-copy
|
|
71
|
+
type="button"
|
|
72
|
+
>
|
|
73
|
+
<Fragment set:html={renderLumenIconSvg('copy', { className: 'ui-code__copy-icon' })} />
|
|
74
|
+
<Fragment set:html={renderLumenIconSvg('check', { className: 'ui-code__check-icon' })} />
|
|
75
|
+
</button>
|
|
76
|
+
)}
|
|
77
|
+
</figcaption>
|
|
78
|
+
)}
|
|
79
|
+
{highlighted ? (
|
|
80
|
+
<slot />
|
|
81
|
+
) : hasCode ? (
|
|
82
|
+
<pre><code set:html={renderedCode}></code></pre>
|
|
83
|
+
) : (
|
|
84
|
+
<pre><code><slot /></code></pre>
|
|
85
|
+
)}
|
|
86
|
+
</figure>
|
|
87
|
+
) : (
|
|
88
|
+
<code
|
|
89
|
+
class:list={inlineClassList}
|
|
90
|
+
data-code-theme={theme}
|
|
91
|
+
data-language={language}
|
|
92
|
+
{...passthrough}
|
|
93
|
+
>
|
|
94
|
+
{hasCode ? code : <slot />}
|
|
95
|
+
</code>
|
|
96
|
+
)}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
3
|
+
|
|
4
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
5
|
+
|
|
6
|
+
interface Props extends HTMLAttributes<'details'> {
|
|
7
|
+
class?: string
|
|
8
|
+
className?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const {
|
|
12
|
+
class: classProp = '',
|
|
13
|
+
className = '',
|
|
14
|
+
...rest
|
|
15
|
+
} = Astro.props
|
|
16
|
+
|
|
17
|
+
const { classList, passthrough } = resolveLumenAstroProps(rest, [
|
|
18
|
+
'ui-collapsible'
|
|
19
|
+
], classProp, className)
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
<details
|
|
23
|
+
data-ui-collapsible
|
|
24
|
+
class:list={classList}
|
|
25
|
+
{...passthrough}
|
|
26
|
+
>
|
|
27
|
+
<slot />
|
|
28
|
+
</details>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
3
|
+
|
|
4
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
5
|
+
|
|
6
|
+
interface Props extends HTMLAttributes<'input'> {
|
|
7
|
+
class?: string
|
|
8
|
+
className?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const { class: classProp = '', className = '', type = 'color', ...rest } = Astro.props
|
|
12
|
+
const { classList, passthrough } = resolveLumenAstroProps(rest, ['ui-color-picker'
|
|
13
|
+
], classProp, className)
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<input class:list={classList} type={type} {...passthrough} />
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
3
|
+
|
|
4
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
5
|
+
|
|
6
|
+
interface Props extends HTMLAttributes<'input'> {
|
|
7
|
+
class?: string
|
|
8
|
+
className?: string
|
|
9
|
+
label?: string
|
|
10
|
+
list: string
|
|
11
|
+
options?: ComboboxOption[]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface Option {
|
|
15
|
+
disabled?: boolean
|
|
16
|
+
label: string
|
|
17
|
+
value: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
type ComboboxOption = Option | string
|
|
21
|
+
|
|
22
|
+
const {
|
|
23
|
+
class: classProp = '',
|
|
24
|
+
className = '',
|
|
25
|
+
id,
|
|
26
|
+
label,
|
|
27
|
+
list,
|
|
28
|
+
options = [],
|
|
29
|
+
type = 'text',
|
|
30
|
+
...rest
|
|
31
|
+
} = Astro.props
|
|
32
|
+
|
|
33
|
+
const inputId = id ?? `${list}-input`
|
|
34
|
+
const normalizedOptions = options.map(option =>
|
|
35
|
+
typeof option === 'string' ? { label: option, value: option } : option
|
|
36
|
+
)
|
|
37
|
+
const { classList, passthrough } = resolveLumenAstroProps(rest, ['ui-combobox'
|
|
38
|
+
], classProp, className)
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
<div class:list={classList} data-ui-combobox>
|
|
42
|
+
{label && <label class="ui-label" for={inputId}>{label}</label>}
|
|
43
|
+
<input
|
|
44
|
+
aria-autocomplete="list"
|
|
45
|
+
aria-controls={list}
|
|
46
|
+
aria-expanded="false"
|
|
47
|
+
class="ui-input"
|
|
48
|
+
id={inputId}
|
|
49
|
+
role="combobox"
|
|
50
|
+
type={type}
|
|
51
|
+
{...passthrough}
|
|
52
|
+
/>
|
|
53
|
+
<div class="ui-combobox__list" hidden id={list} role="listbox">
|
|
54
|
+
{normalizedOptions.map(option => (
|
|
55
|
+
<button
|
|
56
|
+
aria-disabled={option.disabled ? 'true' : undefined}
|
|
57
|
+
data-ui-combobox-option
|
|
58
|
+
data-value={option.value}
|
|
59
|
+
disabled={option.disabled}
|
|
60
|
+
role="option"
|
|
61
|
+
type="button"
|
|
62
|
+
>
|
|
63
|
+
{option.label}
|
|
64
|
+
</button>
|
|
65
|
+
))}
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
3
|
+
|
|
4
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
5
|
+
|
|
6
|
+
interface Props extends HTMLAttributes<'div'> {
|
|
7
|
+
class?: string
|
|
8
|
+
className?: string
|
|
9
|
+
glass?: boolean | 'subtle' | 'strong'
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const {
|
|
13
|
+
class: classProp = '',
|
|
14
|
+
className = '',
|
|
15
|
+
glass = false,
|
|
16
|
+
...rest
|
|
17
|
+
} = Astro.props
|
|
18
|
+
|
|
19
|
+
const { classList, passthrough } = resolveLumenAstroProps(rest, [
|
|
20
|
+
'ui-command',
|
|
21
|
+
glass && 'ui-command--glass',
|
|
22
|
+
glass === 'subtle' && 'ui-glass-subtle',
|
|
23
|
+
glass === 'strong' && 'ui-glass-strong'
|
|
24
|
+
], classProp, className)
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
<div
|
|
28
|
+
data-ui-command
|
|
29
|
+
class:list={classList}
|
|
30
|
+
{...passthrough}
|
|
31
|
+
>
|
|
32
|
+
<slot />
|
|
33
|
+
</div>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { resolveLumenAstroProps, resolveLumenGlass } from '@santi020k/lumen-core'
|
|
3
|
+
|
|
4
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
5
|
+
|
|
6
|
+
interface Props extends HTMLAttributes<'menu'> {
|
|
7
|
+
class?: string
|
|
8
|
+
className?: string
|
|
9
|
+
glass?: boolean | 'subtle' | 'strong'
|
|
10
|
+
/**
|
|
11
|
+
* @deprecated Use `glass` instead. `surface="glass"` maps to `glass={true}`.
|
|
12
|
+
*/
|
|
13
|
+
surface?: 'default' | 'glass'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const {
|
|
17
|
+
class: classProp = '',
|
|
18
|
+
className = '',
|
|
19
|
+
glass = false,
|
|
20
|
+
surface = 'default',
|
|
21
|
+
...rest
|
|
22
|
+
} = Astro.props
|
|
23
|
+
|
|
24
|
+
const resolvedGlass = resolveLumenGlass(glass, surface)
|
|
25
|
+
const { classList, passthrough } = resolveLumenAstroProps(rest, [
|
|
26
|
+
'ui-menu',
|
|
27
|
+
resolvedGlass && 'ui-menu--glass',
|
|
28
|
+
glass === 'subtle' && 'ui-glass-subtle',
|
|
29
|
+
glass === 'strong' && 'ui-glass-strong'
|
|
30
|
+
], classProp, className)
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
{/* Point an element at this menu with data-ui-context-menu-trigger="<menu id>"
|
|
34
|
+
to get right-click / Shift+F10 open behavior from the runtime. Without a
|
|
35
|
+
trigger the menu renders statically. */}
|
|
36
|
+
<menu
|
|
37
|
+
data-surface={resolvedGlass ? 'glass' : 'default'}
|
|
38
|
+
data-ui-context-menu
|
|
39
|
+
role="menu"
|
|
40
|
+
class:list={classList}
|
|
41
|
+
{...passthrough}
|
|
42
|
+
>
|
|
43
|
+
<slot />
|
|
44
|
+
</menu>
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { resolveLumenAstroProps } from '@santi020k/lumen-core'
|
|
3
|
+
import type { ImageMetadata } from 'astro'
|
|
4
|
+
import { Picture } from 'astro:assets'
|
|
5
|
+
|
|
6
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
7
|
+
|
|
8
|
+
interface Props extends HTMLAttributes<'div'> {
|
|
9
|
+
alt: string
|
|
10
|
+
ariaHidden?: boolean
|
|
11
|
+
class?: string
|
|
12
|
+
className?: string
|
|
13
|
+
featured?: boolean
|
|
14
|
+
featuredMinHeightClass?: string
|
|
15
|
+
fetchpriority?: 'auto' | 'high' | 'low'
|
|
16
|
+
hover?: boolean
|
|
17
|
+
image: ImageMetadata
|
|
18
|
+
loading?: 'eager' | 'lazy'
|
|
19
|
+
mode?: 'card' | 'detail'
|
|
20
|
+
showBottomGradient?: boolean
|
|
21
|
+
showCardOverlay?: boolean
|
|
22
|
+
sizes?: string
|
|
23
|
+
transitionName?: string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const {
|
|
27
|
+
alt,
|
|
28
|
+
ariaHidden = false,
|
|
29
|
+
class: classProp = '',
|
|
30
|
+
className = '',
|
|
31
|
+
featured = false,
|
|
32
|
+
featuredMinHeightClass = 'lg:min-h-88',
|
|
33
|
+
fetchpriority = 'auto',
|
|
34
|
+
hover = false,
|
|
35
|
+
image,
|
|
36
|
+
loading = 'lazy',
|
|
37
|
+
mode = 'card',
|
|
38
|
+
showBottomGradient = false,
|
|
39
|
+
showCardOverlay = true,
|
|
40
|
+
sizes = '(min-width: 1024px) 800px, 100vw',
|
|
41
|
+
transitionName,
|
|
42
|
+
...rest
|
|
43
|
+
} = Astro.props
|
|
44
|
+
|
|
45
|
+
const effectiveTransitionName = transitionName ?? `cover:${image.src}`
|
|
46
|
+
const aspectRatio = image.width / image.height
|
|
47
|
+
let orientation: 'landscape' | 'portrait' | 'square' = 'landscape'
|
|
48
|
+
|
|
49
|
+
if (aspectRatio < 0.92) {
|
|
50
|
+
orientation = 'portrait'
|
|
51
|
+
} else if (aspectRatio <= 1.08) {
|
|
52
|
+
orientation = 'square'
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const useContainedFrame = orientation !== 'landscape'
|
|
56
|
+
let cardAspectClass = 'aspect-16/10'
|
|
57
|
+
|
|
58
|
+
if (orientation === 'portrait') {
|
|
59
|
+
cardAspectClass = 'aspect-4/5'
|
|
60
|
+
} else if (orientation === 'square') {
|
|
61
|
+
cardAspectClass = 'aspect-square'
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let cardWrapperClass = `${cardAspectClass} rounded-t-[1.75rem] border-b border-line/45`
|
|
65
|
+
|
|
66
|
+
if (featured && orientation === 'landscape') {
|
|
67
|
+
cardWrapperClass = `aspect-16/10 rounded-t-[1.75rem] border-b border-line/45`
|
|
68
|
+
} else if (useContainedFrame) {
|
|
69
|
+
cardWrapperClass = `${cardAspectClass} rounded-t-[1.75rem] flex items-center justify-center border-b border-line/45 bg-linear-to-br from-surface-muted via-surface to-brand-soft/30 p-4 sm:p-5`
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
let detailWrapperClass = 'w-full'
|
|
73
|
+
let detailImageClass = 'size-full object-contain'
|
|
74
|
+
let detailWrapperStyle: string | undefined
|
|
75
|
+
|
|
76
|
+
let cardImageClass = `size-full object-cover motion-safe:group-hover:scale-[1.03]`
|
|
77
|
+
|
|
78
|
+
if (useContainedFrame) {
|
|
79
|
+
detailWrapperClass = `flex min-h-[22rem] items-center justify-center bg-linear-to-br from-surface-muted via-surface to-brand-soft/35 p-4 sm:min-h-[28rem] sm:p-6 lg:min-h-[34rem] lg:p-8`
|
|
80
|
+
|
|
81
|
+
if (orientation === 'portrait') {
|
|
82
|
+
detailImageClass = 'mx-auto h-full w-auto max-w-full object-contain'
|
|
83
|
+
} else {
|
|
84
|
+
detailImageClass = 'mx-auto h-full w-full max-w-[34rem] object-contain'
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
cardImageClass = `mx-auto h-full w-full object-contain motion-safe:group-hover:scale-[1.02]`
|
|
88
|
+
} else {
|
|
89
|
+
detailWrapperStyle = `aspect-ratio: ${image.width} / ${image.height};`
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const wrapperClasses =
|
|
93
|
+
mode === 'card' ?
|
|
94
|
+
[
|
|
95
|
+
'relative overflow-hidden bg-surface-muted',
|
|
96
|
+
cardWrapperClass,
|
|
97
|
+
featured && orientation === 'landscape' && featuredMinHeightClass
|
|
98
|
+
] :
|
|
99
|
+
[
|
|
100
|
+
'relative overflow-hidden bg-surface-muted',
|
|
101
|
+
detailWrapperClass
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
const imageClasses = ['relative z-10 transition duration-500 motion-reduce:transition-none']
|
|
105
|
+
|
|
106
|
+
if (mode === 'detail') {
|
|
107
|
+
imageClasses.push(detailImageClass)
|
|
108
|
+
} else {
|
|
109
|
+
imageClasses.push(cardImageClass)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
let targetWidth = 1280
|
|
113
|
+
let targetHeight = 800
|
|
114
|
+
|
|
115
|
+
if (mode === 'detail') {
|
|
116
|
+
targetWidth = 1600
|
|
117
|
+
targetHeight = 1000
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (orientation === 'portrait') {
|
|
121
|
+
targetHeight = mode === 'detail' ? 1500 : 1280
|
|
122
|
+
targetWidth = Math.round(targetHeight * 0.8)
|
|
123
|
+
} else if (orientation === 'square') {
|
|
124
|
+
targetHeight = mode === 'detail' ? 1200 : 1024
|
|
125
|
+
targetWidth = targetHeight
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const widths =
|
|
129
|
+
mode === 'detail' ?
|
|
130
|
+
[400, 800, 1200, 1600] :
|
|
131
|
+
[320, 400, 560, 740, 960, 1280]
|
|
132
|
+
|
|
133
|
+
const { classList, passthrough } = resolveLumenAstroProps(rest, [
|
|
134
|
+
'ui-cover-image',
|
|
135
|
+
hover && 'ui-cover-image--hover',
|
|
136
|
+
...wrapperClasses
|
|
137
|
+
], classProp, className)
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
<div
|
|
141
|
+
class:list={classList}
|
|
142
|
+
style={mode === 'detail' ? detailWrapperStyle : undefined}
|
|
143
|
+
transition:name={effectiveTransitionName}
|
|
144
|
+
{...passthrough}
|
|
145
|
+
>
|
|
146
|
+
{mode === 'detail' && useContainedFrame && (
|
|
147
|
+
<div
|
|
148
|
+
aria-hidden="true"
|
|
149
|
+
class="grid-fade absolute inset-0 opacity-45"
|
|
150
|
+
/>
|
|
151
|
+
)}
|
|
152
|
+
|
|
153
|
+
<Picture
|
|
154
|
+
alt={ariaHidden ? '' : alt}
|
|
155
|
+
aria-hidden={ariaHidden ? 'true' : undefined}
|
|
156
|
+
class:list={imageClasses}
|
|
157
|
+
fetchpriority={fetchpriority}
|
|
158
|
+
formats={['avif', 'webp']}
|
|
159
|
+
height={targetHeight}
|
|
160
|
+
loading={loading}
|
|
161
|
+
sizes={sizes}
|
|
162
|
+
src={image}
|
|
163
|
+
width={targetWidth}
|
|
164
|
+
widths={widths}
|
|
165
|
+
/>
|
|
166
|
+
|
|
167
|
+
{mode === 'card' && !useContainedFrame && showCardOverlay && (
|
|
168
|
+
<div
|
|
169
|
+
aria-hidden="true"
|
|
170
|
+
class="absolute inset-0 bg-linear-to-t from-canvas/55 via-canvas/10 to-transparent"
|
|
171
|
+
/>
|
|
172
|
+
)}
|
|
173
|
+
|
|
174
|
+
{showBottomGradient && (
|
|
175
|
+
<div
|
|
176
|
+
aria-hidden="true"
|
|
177
|
+
class="ui-cover-image__bottom-gradient"
|
|
178
|
+
/>
|
|
179
|
+
)}
|
|
180
|
+
</div>
|