@xtyle/astro 0.5.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 +42 -0
- package/package.json +25 -0
- package/src/Accordion.astro +79 -0
- package/src/Alert.astro +57 -0
- package/src/AppShell.astro +97 -0
- package/src/Avatar.astro +71 -0
- package/src/AvatarGroup.astro +44 -0
- package/src/Badge.astro +73 -0
- package/src/Bar.astro +83 -0
- package/src/Breadcrumb.astro +54 -0
- package/src/Button.astro +91 -0
- package/src/Card.astro +44 -0
- package/src/CardLink.astro +60 -0
- package/src/Carousel.astro +39 -0
- package/src/Checkbox.astro +68 -0
- package/src/CheckboxGroup.astro +54 -0
- package/src/Cluster.astro +46 -0
- package/src/Code.astro +42 -0
- package/src/ColorPicker.astro +184 -0
- package/src/Dialog.astro +69 -0
- package/src/Dock.astro +79 -0
- package/src/DockZone.astro +17 -0
- package/src/Eyebrow.astro +30 -0
- package/src/Field.astro +117 -0
- package/src/FormGroup.astro +71 -0
- package/src/Grid.astro +57 -0
- package/src/Heading.astro +34 -0
- package/src/Heatmap.astro +116 -0
- package/src/Hero.astro +19 -0
- package/src/Icon.astro +53 -0
- package/src/Image.astro +56 -0
- package/src/Kbd.astro +27 -0
- package/src/Link.astro +56 -0
- package/src/Menu.astro +38 -0
- package/src/NumberInput.astro +86 -0
- package/src/Pagination.astro +53 -0
- package/src/Panel.astro +68 -0
- package/src/Parallax.astro +18 -0
- package/src/Pie.astro +65 -0
- package/src/Progress.astro +96 -0
- package/src/Radio.astro +71 -0
- package/src/RadioGroup.astro +44 -0
- package/src/Section.astro +61 -0
- package/src/Segment.astro +15 -0
- package/src/Segmented.astro +95 -0
- package/src/Select.astro +79 -0
- package/src/Separator.astro +36 -0
- package/src/Skeleton.astro +25 -0
- package/src/Slider.astro +93 -0
- package/src/Sparkline.astro +79 -0
- package/src/Spinner.astro +37 -0
- package/src/Splitter.astro +87 -0
- package/src/Stack.astro +42 -0
- package/src/Stat.astro +70 -0
- package/src/Statusbar.astro +56 -0
- package/src/Swatch.astro +69 -0
- package/src/Switch.astro +89 -0
- package/src/Table.astro +46 -0
- package/src/Tabs.astro +94 -0
- package/src/Text.astro +54 -0
- package/src/Textarea.astro +81 -0
- package/src/Toast.astro +62 -0
- package/src/ToastRegion.astro +39 -0
- package/src/Toc.astro +35 -0
- package/src/Toolbar.astro +68 -0
- package/src/Tooltip.astro +68 -0
- package/src/Tree.astro +78 -0
- package/src/internal/palette.ts +92 -0
package/src/Link.astro
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { renderFragmentLight } from "@xtyle/core/elements/ssr";
|
|
3
|
+
|
|
4
|
+
type LinkVariant = "default" | "muted" | "quiet";
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
variant?: LinkVariant;
|
|
8
|
+
href?: string;
|
|
9
|
+
target?: string;
|
|
10
|
+
rel?: string;
|
|
11
|
+
externalIcon?: boolean;
|
|
12
|
+
/** Render zero-JS: emit the resolved light-DOM markup but never load the runtime to hydrate it. */
|
|
13
|
+
static?: boolean;
|
|
14
|
+
class?: string;
|
|
15
|
+
/** Any other attribute (`id`, `title`, `data-*`, `aria-*`, …) passes through to the element. */
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const {
|
|
20
|
+
variant = "default",
|
|
21
|
+
href,
|
|
22
|
+
target,
|
|
23
|
+
rel,
|
|
24
|
+
externalIcon,
|
|
25
|
+
static: isStatic = false,
|
|
26
|
+
class: extra,
|
|
27
|
+
...rest
|
|
28
|
+
} = Astro.props;
|
|
29
|
+
|
|
30
|
+
const isExternal = target === "_blank";
|
|
31
|
+
const showExternalIcon = externalIcon ?? isExternal;
|
|
32
|
+
|
|
33
|
+
const bindings = {
|
|
34
|
+
variant,
|
|
35
|
+
href: href ?? null,
|
|
36
|
+
target: target ?? null,
|
|
37
|
+
rel: rel ?? null,
|
|
38
|
+
showExternalIcon,
|
|
39
|
+
};
|
|
40
|
+
const chrome = await renderFragmentLight("link", bindings);
|
|
41
|
+
const slotHtml = Astro.slots.has("default") ? await Astro.slots.render("default") : "";
|
|
42
|
+
const composed = chrome.replace("<slot></slot>", () => slotHtml);
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
<xtyle-link
|
|
46
|
+
variant={variant}
|
|
47
|
+
href={href ?? undefined}
|
|
48
|
+
target={target ?? undefined}
|
|
49
|
+
rel={rel ?? undefined}
|
|
50
|
+
external-icon={String(showExternalIcon)}
|
|
51
|
+
class={extra}
|
|
52
|
+
set:html={composed}
|
|
53
|
+
{...rest}
|
|
54
|
+
/>
|
|
55
|
+
|
|
56
|
+
{!isStatic && <script>import "@xtyle/core/elements";</script>}
|
package/src/Menu.astro
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { type MenuItem } from "@xtyle/core/markup";
|
|
3
|
+
import { renderFragmentLight } from "@xtyle/core/elements/ssr";
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
items?: MenuItem[];
|
|
7
|
+
label?: string;
|
|
8
|
+
open?: boolean;
|
|
9
|
+
/** Render zero-JS: emit the resolved light-DOM markup but never load the runtime to hydrate it. */
|
|
10
|
+
static?: boolean;
|
|
11
|
+
class?: string;
|
|
12
|
+
/** Any other attribute (`id`, `title`, `data-*`, `aria-*`, …) passes through to the element. */
|
|
13
|
+
[key: string]: unknown;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const { items = [], label, open = false, static: isStatic = false, class: extra, ...rest } = Astro.props;
|
|
17
|
+
|
|
18
|
+
const popupId = `xtyle-menu-${Math.random().toString(36).slice(2, 9)}-popup`;
|
|
19
|
+
|
|
20
|
+
const bindings = {
|
|
21
|
+
items,
|
|
22
|
+
label: label ?? null,
|
|
23
|
+
open,
|
|
24
|
+
popupId,
|
|
25
|
+
};
|
|
26
|
+
const light = await renderFragmentLight("menu", bindings);
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
<xtyle-menu
|
|
30
|
+
items={items && items.length > 0 ? JSON.stringify(items) : undefined}
|
|
31
|
+
label={label}
|
|
32
|
+
open={open || undefined}
|
|
33
|
+
class={extra}
|
|
34
|
+
{...rest}
|
|
35
|
+
set:html={light}
|
|
36
|
+
/>
|
|
37
|
+
|
|
38
|
+
{!isStatic && <script>import "@xtyle/core/elements";</script>}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { renderFragmentLight } from "@xtyle/core/elements/ssr";
|
|
3
|
+
|
|
4
|
+
type Size = "sm" | "md" | "lg";
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
value?: number | string;
|
|
8
|
+
min?: number;
|
|
9
|
+
max?: number;
|
|
10
|
+
/** A positive number, or `"any"` for unstepped free-form entry (no snapping, no precision cap). */
|
|
11
|
+
step?: number | "any";
|
|
12
|
+
altStep?: number;
|
|
13
|
+
altDefault?: boolean;
|
|
14
|
+
modifier?: "shift" | "alt" | "ctrl" | "meta";
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
size?: Size;
|
|
17
|
+
label?: string;
|
|
18
|
+
labelledby?: string;
|
|
19
|
+
name?: string;
|
|
20
|
+
placeholder?: string;
|
|
21
|
+
/** Render zero-JS: emit the resolved light-DOM markup but never load the runtime to hydrate it. */
|
|
22
|
+
static?: boolean;
|
|
23
|
+
class?: string;
|
|
24
|
+
/** Any other attribute (`id`, `title`, `data-*`, `aria-*`, …) passes through to the element. */
|
|
25
|
+
[key: string]: unknown;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const {
|
|
29
|
+
value,
|
|
30
|
+
min,
|
|
31
|
+
max,
|
|
32
|
+
step,
|
|
33
|
+
altStep,
|
|
34
|
+
altDefault = false,
|
|
35
|
+
modifier,
|
|
36
|
+
disabled = false,
|
|
37
|
+
size = "md",
|
|
38
|
+
label,
|
|
39
|
+
labelledby,
|
|
40
|
+
name,
|
|
41
|
+
placeholder,
|
|
42
|
+
static: isStatic = false,
|
|
43
|
+
class: extra,
|
|
44
|
+
...rest
|
|
45
|
+
} = Astro.props;
|
|
46
|
+
|
|
47
|
+
const valueStr = value === undefined || value === "" ? undefined : String(value);
|
|
48
|
+
const elementId = `xtyle-number-${Math.random().toString(36).slice(2, 8)}`;
|
|
49
|
+
|
|
50
|
+
const numeric = valueStr !== undefined && !Number.isNaN(Number(valueStr)) ? Number(valueStr) : (min ?? 0);
|
|
51
|
+
const bindings = {
|
|
52
|
+
value: valueStr ?? "",
|
|
53
|
+
min,
|
|
54
|
+
max,
|
|
55
|
+
disabled,
|
|
56
|
+
size,
|
|
57
|
+
label: label ?? null,
|
|
58
|
+
labelledby: labelledby ?? null,
|
|
59
|
+
placeholder: placeholder ?? null,
|
|
60
|
+
elementId,
|
|
61
|
+
canDec: !(disabled || (min !== undefined && numeric <= min)),
|
|
62
|
+
canInc: !(disabled || (max !== undefined && numeric >= max)),
|
|
63
|
+
};
|
|
64
|
+
const light = await renderFragmentLight("number-input", bindings);
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
<xtyle-number-input
|
|
68
|
+
value={valueStr}
|
|
69
|
+
min={min}
|
|
70
|
+
max={max}
|
|
71
|
+
step={step}
|
|
72
|
+
alt-step={altStep}
|
|
73
|
+
alt-default={altDefault || undefined}
|
|
74
|
+
modifier={modifier}
|
|
75
|
+
disabled={disabled || undefined}
|
|
76
|
+
size={size}
|
|
77
|
+
label={label}
|
|
78
|
+
labelledby={labelledby}
|
|
79
|
+
name={name}
|
|
80
|
+
placeholder={placeholder}
|
|
81
|
+
class={extra}
|
|
82
|
+
{...rest}
|
|
83
|
+
set:html={light}
|
|
84
|
+
/>
|
|
85
|
+
|
|
86
|
+
{!isStatic && <script>import "@xtyle/core/elements";</script>}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { renderFragmentLight } from "@xtyle/core/elements/ssr";
|
|
3
|
+
import type { FullTone, Size } from "@xtyle/core";
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
page?: number;
|
|
7
|
+
total?: number;
|
|
8
|
+
siblings?: number;
|
|
9
|
+
boundaries?: number;
|
|
10
|
+
href?: string;
|
|
11
|
+
tone?: FullTone;
|
|
12
|
+
size?: Size;
|
|
13
|
+
label?: string;
|
|
14
|
+
/** Render zero-JS: emit the resolved light-DOM markup but never load the runtime to hydrate it. */
|
|
15
|
+
static?: boolean;
|
|
16
|
+
class?: string;
|
|
17
|
+
/** Any other attribute (`id`, `title`, `data-*`, `aria-*`, …) passes through to the element. */
|
|
18
|
+
[key: string]: unknown;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const {
|
|
22
|
+
page = 1,
|
|
23
|
+
total = 1,
|
|
24
|
+
siblings = 1,
|
|
25
|
+
boundaries = 1,
|
|
26
|
+
href,
|
|
27
|
+
tone = "accent",
|
|
28
|
+
size = "md",
|
|
29
|
+
label = "Pagination",
|
|
30
|
+
static: isStatic = false,
|
|
31
|
+
class: extra,
|
|
32
|
+
...rest
|
|
33
|
+
} = Astro.props;
|
|
34
|
+
|
|
35
|
+
const bindings = { page, total, siblings, boundaries, href, tone, size, label };
|
|
36
|
+
const light = await renderFragmentLight("pagination", bindings);
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
<xtyle-pagination
|
|
40
|
+
page={page}
|
|
41
|
+
total={total}
|
|
42
|
+
siblings={siblings}
|
|
43
|
+
boundaries={boundaries}
|
|
44
|
+
href={href}
|
|
45
|
+
tone={tone}
|
|
46
|
+
size={size}
|
|
47
|
+
label={label}
|
|
48
|
+
class={extra}
|
|
49
|
+
set:html={light}
|
|
50
|
+
{...rest}
|
|
51
|
+
/>
|
|
52
|
+
|
|
53
|
+
{!isStatic && <script>import "@xtyle/core/elements";</script>}
|
package/src/Panel.astro
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { renderFragmentLight } from "@xtyle/core/elements/ssr";
|
|
3
|
+
|
|
4
|
+
type PanelVariant = "default" | "collapsible";
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
title?: string;
|
|
8
|
+
/** Accessible name for a panel with no visible `title` — names the region without rendering a heading. */
|
|
9
|
+
label?: string;
|
|
10
|
+
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
11
|
+
variant?: PanelVariant;
|
|
12
|
+
open?: boolean;
|
|
13
|
+
scroll?: boolean;
|
|
14
|
+
/** Render zero-JS: emit the resolved light-DOM markup but never load the runtime to hydrate it. */
|
|
15
|
+
static?: boolean;
|
|
16
|
+
class?: string;
|
|
17
|
+
/** Any other attribute (`id`, `title`, `data-*`, `aria-*`, …) passes through to the element. */
|
|
18
|
+
[key: string]: unknown;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const {
|
|
22
|
+
title,
|
|
23
|
+
label,
|
|
24
|
+
level = 2,
|
|
25
|
+
variant = "default",
|
|
26
|
+
open = false,
|
|
27
|
+
scroll = false,
|
|
28
|
+
static: isStatic = false,
|
|
29
|
+
class: extra,
|
|
30
|
+
...rest
|
|
31
|
+
} = Astro.props;
|
|
32
|
+
|
|
33
|
+
const hasActions = Astro.slots.has("actions");
|
|
34
|
+
const titleId = `xtyle-panel-${Math.random().toString(36).slice(2, 9)}`;
|
|
35
|
+
|
|
36
|
+
const bindings = {
|
|
37
|
+
title: title ?? null,
|
|
38
|
+
level,
|
|
39
|
+
variant,
|
|
40
|
+
open,
|
|
41
|
+
scrollable: scroll,
|
|
42
|
+
hasActions,
|
|
43
|
+
titleId,
|
|
44
|
+
label: label ?? null,
|
|
45
|
+
};
|
|
46
|
+
const chrome = await renderFragmentLight("panel", bindings);
|
|
47
|
+
const actionsHtml = hasActions ? await Astro.slots.render("actions") : "";
|
|
48
|
+
const bodyHtml = Astro.slots.has("default") ? await Astro.slots.render("default") : "";
|
|
49
|
+
const footerHtml = Astro.slots.has("footer") ? await Astro.slots.render("footer") : "";
|
|
50
|
+
const composed = chrome
|
|
51
|
+
.replace('<slot name="actions"></slot>', () => actionsHtml)
|
|
52
|
+
.replace('<slot name="footer"></slot>', () => footerHtml)
|
|
53
|
+
.replace("<slot></slot>", () => bodyHtml);
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
<xtyle-panel
|
|
57
|
+
title={title}
|
|
58
|
+
label={label}
|
|
59
|
+
level={level}
|
|
60
|
+
variant={variant}
|
|
61
|
+
open={open || undefined}
|
|
62
|
+
scroll={scroll || undefined}
|
|
63
|
+
class={extra}
|
|
64
|
+
set:html={composed}
|
|
65
|
+
{...rest}
|
|
66
|
+
/>
|
|
67
|
+
|
|
68
|
+
{!isStatic && <script>import "@xtyle/core/elements";</script>}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Props {
|
|
3
|
+
minHeight?: string;
|
|
4
|
+
amplitude?: number;
|
|
5
|
+
mode?: "scroll" | "cursor";
|
|
6
|
+
class?: string;
|
|
7
|
+
/** Any other attribute (`id`, `title`, `data-*`, `aria-*`, …) passes through to the element. */
|
|
8
|
+
[key: string]: unknown;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const { minHeight, amplitude, mode, class: extra, ...rest } = Astro.props;
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
<xtyle-parallax min-height={minHeight} amplitude={amplitude} mode={mode} class={extra} {...rest}>
|
|
15
|
+
<slot />
|
|
16
|
+
</xtyle-parallax>
|
|
17
|
+
|
|
18
|
+
<script>import "@xtyle/core/elements";</script>
|
package/src/Pie.astro
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { renderFragmentLight } from "@xtyle/core/elements/ssr";
|
|
3
|
+
import { resolveSeriesColorsFor } from "./internal/palette.ts";
|
|
4
|
+
import type { PieDatum, PieScheme } from "@xtyle/core";
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
data?: PieDatum[];
|
|
8
|
+
scheme?: PieScheme;
|
|
9
|
+
reverse?: boolean;
|
|
10
|
+
variant?: "pie" | "donut";
|
|
11
|
+
showValues?: boolean;
|
|
12
|
+
legend?: boolean;
|
|
13
|
+
size?: number;
|
|
14
|
+
label?: string;
|
|
15
|
+
/** Render zero-JS: emit the resolved light-DOM markup but never load the runtime to hydrate it. */
|
|
16
|
+
static?: boolean;
|
|
17
|
+
class?: string;
|
|
18
|
+
/** Any other attribute (`id`, `style`, `data-*`, `aria-*`, …) passes through to the element. */
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const {
|
|
23
|
+
data = [],
|
|
24
|
+
scheme = "skittles",
|
|
25
|
+
reverse = false,
|
|
26
|
+
variant = "pie",
|
|
27
|
+
showValues = false,
|
|
28
|
+
legend = true,
|
|
29
|
+
size = 200,
|
|
30
|
+
label,
|
|
31
|
+
static: isStatic = false,
|
|
32
|
+
class: extra,
|
|
33
|
+
...rest
|
|
34
|
+
} = Astro.props;
|
|
35
|
+
|
|
36
|
+
const slices = data.filter((d) => Number(d.value) > 0);
|
|
37
|
+
const colors = await resolveSeriesColorsFor(scheme, slices, reverse);
|
|
38
|
+
const bindings = {
|
|
39
|
+
data: slices,
|
|
40
|
+
colors,
|
|
41
|
+
variant,
|
|
42
|
+
showValues,
|
|
43
|
+
legend,
|
|
44
|
+
size,
|
|
45
|
+
title: label ?? null,
|
|
46
|
+
ariaLabel: label ?? null,
|
|
47
|
+
};
|
|
48
|
+
const chrome = await renderFragmentLight("pie", bindings);
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
<xtyle-pie
|
|
52
|
+
data={JSON.stringify(data)}
|
|
53
|
+
scheme={Array.isArray(scheme) ? JSON.stringify(scheme) : scheme}
|
|
54
|
+
variant={variant}
|
|
55
|
+
reverse={reverse || undefined}
|
|
56
|
+
show-values={showValues || undefined}
|
|
57
|
+
legend={legend ? undefined : "false"}
|
|
58
|
+
size={size}
|
|
59
|
+
label={label}
|
|
60
|
+
class={extra}
|
|
61
|
+
set:html={chrome}
|
|
62
|
+
{...rest}
|
|
63
|
+
/>
|
|
64
|
+
|
|
65
|
+
{!isStatic && <script>import "@xtyle/core/elements";</script>}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { renderFragmentLight, composeFallbackSlot } from "@xtyle/core/elements/ssr";
|
|
3
|
+
|
|
4
|
+
import type { FullTone as Tone } from "@xtyle/core";
|
|
5
|
+
type ProgressVariant = "linear" | "circular";
|
|
6
|
+
type ProgressSize = "sm" | "md" | "lg";
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
variant?: ProgressVariant;
|
|
10
|
+
tone?: Tone;
|
|
11
|
+
size?: ProgressSize;
|
|
12
|
+
value?: number;
|
|
13
|
+
min?: number;
|
|
14
|
+
max?: number;
|
|
15
|
+
indeterminate?: boolean;
|
|
16
|
+
showValue?: boolean;
|
|
17
|
+
/** How `showValue` renders the readout: `percent` (33%), `value` (123), or `value-max` (123/456). */
|
|
18
|
+
valueFormat?: "percent" | "value" | "value-max";
|
|
19
|
+
/** Tint the readout with the active tone instead of the muted default. */
|
|
20
|
+
colorizeValue?: boolean;
|
|
21
|
+
/** `end` (after the bar) or `inset` (centered in the track, contrast-flipping as the fill crosses). */
|
|
22
|
+
valuePosition?: "end" | "inset";
|
|
23
|
+
/** Report `role="meter"` (a capacity measurement) instead of `role="progressbar"` (a task). */
|
|
24
|
+
meter?: boolean;
|
|
25
|
+
"aria-label"?: string;
|
|
26
|
+
/** Render zero-JS: emit the resolved light-DOM markup but never load the runtime to hydrate it. */
|
|
27
|
+
static?: boolean;
|
|
28
|
+
class?: string;
|
|
29
|
+
/** Any other attribute (`id`, `title`, `data-*`, `aria-*`, …) passes through to the element. */
|
|
30
|
+
[key: string]: unknown;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const {
|
|
34
|
+
variant = "linear",
|
|
35
|
+
tone = "accent",
|
|
36
|
+
size = "md",
|
|
37
|
+
value = 0,
|
|
38
|
+
min = 0,
|
|
39
|
+
max = 100,
|
|
40
|
+
indeterminate = false,
|
|
41
|
+
showValue = false,
|
|
42
|
+
valueFormat = "percent",
|
|
43
|
+
colorizeValue = false,
|
|
44
|
+
valuePosition = "end",
|
|
45
|
+
meter = false,
|
|
46
|
+
"aria-label": ariaLabel,
|
|
47
|
+
static: isStatic = false,
|
|
48
|
+
class: extra,
|
|
49
|
+
...rest
|
|
50
|
+
} = Astro.props;
|
|
51
|
+
|
|
52
|
+
const bindings = {
|
|
53
|
+
variant,
|
|
54
|
+
tone,
|
|
55
|
+
size,
|
|
56
|
+
value,
|
|
57
|
+
min,
|
|
58
|
+
max,
|
|
59
|
+
indeterminate,
|
|
60
|
+
showValue,
|
|
61
|
+
valueFormat,
|
|
62
|
+
colorizeValue,
|
|
63
|
+
valuePosition,
|
|
64
|
+
pulse: null,
|
|
65
|
+
role: meter ? "meter" : "progressbar",
|
|
66
|
+
ariaLabel: ariaLabel ?? null,
|
|
67
|
+
ariaLabelledby: null,
|
|
68
|
+
};
|
|
69
|
+
const light = await renderFragmentLight("progress", bindings);
|
|
70
|
+
const valueHtml = Astro.slots.has("value") ? await Astro.slots.render("value") : null;
|
|
71
|
+
// the default slot carries `<threshold>` config elements — re-emit them as hidden direct children
|
|
72
|
+
// so the hydrating element can read `:scope > threshold` (the global sheet hides them from view)
|
|
73
|
+
const thresholdHtml = Astro.slots.has("default") ? await Astro.slots.render("default") : "";
|
|
74
|
+
const composed = composeFallbackSlot(light, "value", valueHtml) + thresholdHtml;
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
<xtyle-progress
|
|
78
|
+
variant={variant}
|
|
79
|
+
tone={tone}
|
|
80
|
+
size={size}
|
|
81
|
+
value={value}
|
|
82
|
+
min={min}
|
|
83
|
+
max={max}
|
|
84
|
+
indeterminate={indeterminate || undefined}
|
|
85
|
+
show-value={showValue || undefined}
|
|
86
|
+
value-format={valueFormat !== "percent" ? valueFormat : undefined}
|
|
87
|
+
colorize-value={colorizeValue || undefined}
|
|
88
|
+
value-position={valuePosition !== "end" ? valuePosition : undefined}
|
|
89
|
+
meter={meter || undefined}
|
|
90
|
+
aria-label={ariaLabel}
|
|
91
|
+
class={extra}
|
|
92
|
+
set:html={composed}
|
|
93
|
+
{...rest}
|
|
94
|
+
/>
|
|
95
|
+
|
|
96
|
+
{!isStatic && <script>import "@xtyle/core/elements";</script>}
|
package/src/Radio.astro
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { renderFragmentLight } from "@xtyle/core/elements/ssr";
|
|
3
|
+
|
|
4
|
+
import type { FullTone as Tone } from "@xtyle/core";
|
|
5
|
+
type Size = "sm" | "md" | "lg";
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
tone?: Tone;
|
|
9
|
+
size?: Size;
|
|
10
|
+
name?: string;
|
|
11
|
+
value?: string;
|
|
12
|
+
checked?: boolean;
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
invalid?: boolean;
|
|
15
|
+
label?: string;
|
|
16
|
+
labelledby?: string;
|
|
17
|
+
/** Render zero-JS: emit the resolved light-DOM markup but never load the runtime to hydrate it. */
|
|
18
|
+
static?: boolean;
|
|
19
|
+
class?: string;
|
|
20
|
+
/** Any other attribute (`id`, `title`, `data-*`, `aria-*`, …) passes through to the element. */
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const {
|
|
25
|
+
tone = "accent",
|
|
26
|
+
size = "md",
|
|
27
|
+
name,
|
|
28
|
+
value,
|
|
29
|
+
checked = false,
|
|
30
|
+
disabled = false,
|
|
31
|
+
invalid = false,
|
|
32
|
+
label,
|
|
33
|
+
labelledby,
|
|
34
|
+
static: isStatic = false,
|
|
35
|
+
class: extra,
|
|
36
|
+
...rest
|
|
37
|
+
} = Astro.props;
|
|
38
|
+
|
|
39
|
+
const bindings = {
|
|
40
|
+
tone,
|
|
41
|
+
size,
|
|
42
|
+
name: name ?? null,
|
|
43
|
+
value,
|
|
44
|
+
checked,
|
|
45
|
+
disabled,
|
|
46
|
+
invalid,
|
|
47
|
+
label: label ?? null,
|
|
48
|
+
labelledby: labelledby ?? null,
|
|
49
|
+
};
|
|
50
|
+
const light = await renderFragmentLight("radio", bindings);
|
|
51
|
+
const slotHtml = Astro.slots.has("default") ? await Astro.slots.render("default") : null;
|
|
52
|
+
// the label slot carries the `label` text as its fallback; a consumer's slotted label replaces it
|
|
53
|
+
const composed = slotHtml !== null ? light.replace(/<slot>[\s\S]*?<\/slot>/, () => slotHtml) : light.replace(/<slot>([\s\S]*?)<\/slot>/, "$1");
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
<xtyle-radio
|
|
57
|
+
tone={tone}
|
|
58
|
+
size={size}
|
|
59
|
+
name={name}
|
|
60
|
+
value={value}
|
|
61
|
+
checked={checked || undefined}
|
|
62
|
+
disabled={disabled || undefined}
|
|
63
|
+
invalid={invalid || undefined}
|
|
64
|
+
label={label}
|
|
65
|
+
labelledby={labelledby}
|
|
66
|
+
class={extra}
|
|
67
|
+
set:html={composed}
|
|
68
|
+
{...rest}
|
|
69
|
+
/>
|
|
70
|
+
|
|
71
|
+
{!isStatic && <script>import "@xtyle/core/elements";</script>}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { radioGroupMarkup, radioGroupHostCss } from "@xtyle/core/markup";
|
|
3
|
+
import { radioCss } from "@xtyle/core/css";
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
orientation?: "vertical" | "horizontal";
|
|
7
|
+
label?: string;
|
|
8
|
+
labelledby?: string;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
/** Render zero-JS: emit the declarative shadow but never load the runtime to hydrate it. */
|
|
11
|
+
static?: boolean;
|
|
12
|
+
class?: string;
|
|
13
|
+
/** Any other attribute (`id`, `title`, `data-*`, `aria-*`, …) passes through to the element. */
|
|
14
|
+
[key: string]: unknown;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
orientation = "vertical",
|
|
19
|
+
label,
|
|
20
|
+
labelledby,
|
|
21
|
+
disabled = false,
|
|
22
|
+
static: isStatic = false,
|
|
23
|
+
class: extra,
|
|
24
|
+
...rest
|
|
25
|
+
} = Astro.props;
|
|
26
|
+
|
|
27
|
+
const labelId = `xtyle-radio-group-${Math.random().toString(36).slice(2, 8)}-label`;
|
|
28
|
+
|
|
29
|
+
const shadow = `<style>${radioGroupHostCss}${radioCss}</style>${radioGroupMarkup({ orientation, label, labelledby, disabled, labelId })}`;
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
<xtyle-radio-group
|
|
33
|
+
orientation={orientation}
|
|
34
|
+
label={label}
|
|
35
|
+
labelledby={labelledby}
|
|
36
|
+
disabled={disabled || undefined}
|
|
37
|
+
class={extra}
|
|
38
|
+
{...rest}
|
|
39
|
+
>
|
|
40
|
+
<template shadowrootmode="open" set:html={shadow}></template>
|
|
41
|
+
<slot />
|
|
42
|
+
</xtyle-radio-group>
|
|
43
|
+
|
|
44
|
+
{!isStatic && <script>import "@xtyle/core/elements";</script>}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { renderFragmentLight } from "@xtyle/core/elements/ssr";
|
|
3
|
+
import type { FullTone } from "@xtyle/core";
|
|
4
|
+
|
|
5
|
+
type SectionTag = "section" | "div" | "header" | "footer";
|
|
6
|
+
type SectionVariant = "band" | "stage";
|
|
7
|
+
type SectionTone = "plain" | "quiet" | FullTone;
|
|
8
|
+
type SectionPadding = "none" | "sm" | "md" | "lg";
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
as?: SectionTag;
|
|
12
|
+
variant?: SectionVariant;
|
|
13
|
+
tone?: SectionTone;
|
|
14
|
+
bordered?: boolean;
|
|
15
|
+
padding?: SectionPadding;
|
|
16
|
+
label?: string;
|
|
17
|
+
/** Render zero-JS: emit the resolved light-DOM markup but never load the runtime to hydrate it. */
|
|
18
|
+
static?: boolean;
|
|
19
|
+
class?: string;
|
|
20
|
+
/** Any other attribute (`id`, `title`, `data-*`, `aria-*`, …) passes through to the element. */
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const {
|
|
25
|
+
as = "section",
|
|
26
|
+
variant = "band",
|
|
27
|
+
tone = "plain",
|
|
28
|
+
bordered = false,
|
|
29
|
+
padding = "lg",
|
|
30
|
+
label,
|
|
31
|
+
static: isStatic = false,
|
|
32
|
+
class: extra,
|
|
33
|
+
...rest
|
|
34
|
+
} = Astro.props;
|
|
35
|
+
|
|
36
|
+
const bindings = {
|
|
37
|
+
as,
|
|
38
|
+
variant,
|
|
39
|
+
tone,
|
|
40
|
+
bordered,
|
|
41
|
+
padding,
|
|
42
|
+
label: label ?? null,
|
|
43
|
+
};
|
|
44
|
+
const chrome = await renderFragmentLight("section", bindings);
|
|
45
|
+
const slotHtml = Astro.slots.has("default") ? await Astro.slots.render("default") : "";
|
|
46
|
+
const composed = chrome.replace("<slot></slot>", () => slotHtml);
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
<xtyle-section
|
|
50
|
+
as={as}
|
|
51
|
+
variant={variant}
|
|
52
|
+
tone={tone}
|
|
53
|
+
bordered={bordered || undefined}
|
|
54
|
+
padding={padding}
|
|
55
|
+
label={label ?? undefined}
|
|
56
|
+
class={extra}
|
|
57
|
+
set:html={composed}
|
|
58
|
+
{...rest}
|
|
59
|
+
/>
|
|
60
|
+
|
|
61
|
+
{!isStatic && <script>import "@xtyle/core/elements";</script>}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Props {
|
|
3
|
+
/** The value this segment selects; emitted on `change` and submitted with the form. */
|
|
4
|
+
value: string;
|
|
5
|
+
/** Accessible name for the segment, since its content is markup (an icon) rather than text. */
|
|
6
|
+
label?: string;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
/** Any other attribute (`title`, `id`, `data-*`, `aria-*`, …) passes through to the segment. */
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { value, label, disabled = false, ...rest } = Astro.props;
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
<span slot="segment" value={value} label={label} disabled={disabled || undefined} {...rest}><slot /></span>
|