@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.
Files changed (68) hide show
  1. package/README.md +42 -0
  2. package/package.json +25 -0
  3. package/src/Accordion.astro +79 -0
  4. package/src/Alert.astro +57 -0
  5. package/src/AppShell.astro +97 -0
  6. package/src/Avatar.astro +71 -0
  7. package/src/AvatarGroup.astro +44 -0
  8. package/src/Badge.astro +73 -0
  9. package/src/Bar.astro +83 -0
  10. package/src/Breadcrumb.astro +54 -0
  11. package/src/Button.astro +91 -0
  12. package/src/Card.astro +44 -0
  13. package/src/CardLink.astro +60 -0
  14. package/src/Carousel.astro +39 -0
  15. package/src/Checkbox.astro +68 -0
  16. package/src/CheckboxGroup.astro +54 -0
  17. package/src/Cluster.astro +46 -0
  18. package/src/Code.astro +42 -0
  19. package/src/ColorPicker.astro +184 -0
  20. package/src/Dialog.astro +69 -0
  21. package/src/Dock.astro +79 -0
  22. package/src/DockZone.astro +17 -0
  23. package/src/Eyebrow.astro +30 -0
  24. package/src/Field.astro +117 -0
  25. package/src/FormGroup.astro +71 -0
  26. package/src/Grid.astro +57 -0
  27. package/src/Heading.astro +34 -0
  28. package/src/Heatmap.astro +116 -0
  29. package/src/Hero.astro +19 -0
  30. package/src/Icon.astro +53 -0
  31. package/src/Image.astro +56 -0
  32. package/src/Kbd.astro +27 -0
  33. package/src/Link.astro +56 -0
  34. package/src/Menu.astro +38 -0
  35. package/src/NumberInput.astro +86 -0
  36. package/src/Pagination.astro +53 -0
  37. package/src/Panel.astro +68 -0
  38. package/src/Parallax.astro +18 -0
  39. package/src/Pie.astro +65 -0
  40. package/src/Progress.astro +96 -0
  41. package/src/Radio.astro +71 -0
  42. package/src/RadioGroup.astro +44 -0
  43. package/src/Section.astro +61 -0
  44. package/src/Segment.astro +15 -0
  45. package/src/Segmented.astro +95 -0
  46. package/src/Select.astro +79 -0
  47. package/src/Separator.astro +36 -0
  48. package/src/Skeleton.astro +25 -0
  49. package/src/Slider.astro +93 -0
  50. package/src/Sparkline.astro +79 -0
  51. package/src/Spinner.astro +37 -0
  52. package/src/Splitter.astro +87 -0
  53. package/src/Stack.astro +42 -0
  54. package/src/Stat.astro +70 -0
  55. package/src/Statusbar.astro +56 -0
  56. package/src/Swatch.astro +69 -0
  57. package/src/Switch.astro +89 -0
  58. package/src/Table.astro +46 -0
  59. package/src/Tabs.astro +94 -0
  60. package/src/Text.astro +54 -0
  61. package/src/Textarea.astro +81 -0
  62. package/src/Toast.astro +62 -0
  63. package/src/ToastRegion.astro +39 -0
  64. package/src/Toc.astro +35 -0
  65. package/src/Toolbar.astro +68 -0
  66. package/src/Tooltip.astro +68 -0
  67. package/src/Tree.astro +78 -0
  68. package/src/internal/palette.ts +92 -0
@@ -0,0 +1,95 @@
1
+ ---
2
+ import { normalizeSegments } from "@xtyle/core/markup";
3
+ import { renderFragmentLight } from "@xtyle/core/elements/ssr";
4
+
5
+ import type { FullTone as Tone } from "@xtyle/core";
6
+ type Size = "sm" | "md" | "lg";
7
+
8
+ interface Props {
9
+ value?: string;
10
+ options?: string | ReadonlyArray<string | { value: string; label?: string; disabled?: boolean; badge?: string }>;
11
+ disabled?: boolean;
12
+ size?: Size;
13
+ tone?: Tone;
14
+ label?: string;
15
+ labelledby?: string;
16
+ name?: 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
+ value,
26
+ options,
27
+ disabled = false,
28
+ size = "md",
29
+ tone = "accent",
30
+ label,
31
+ labelledby,
32
+ "aria-label": ariaLabel,
33
+ name,
34
+ static: isStatic = false,
35
+ class: extra,
36
+ ...rest
37
+ } = Astro.props;
38
+
39
+ const elementId = `xtyle-segmented-${Math.random().toString(36).slice(2, 8)}`;
40
+ const segments = normalizeSegments(options);
41
+ const optionsAttr = typeof options === "string" ? options : options ? JSON.stringify(options) : undefined;
42
+
43
+ // Two authoring modes, mirroring Tabs. The `options` bar renders its whole chrome light from `bindings`
44
+ // and ships no children (the zero-JS SSR path). The rich-content mode pairs `<Segment>` children by
45
+ // order — live framework markup that can't be snapshotted — so it passes them through untouched and the
46
+ // element projects them on connect (shadow `<slot>`, client-hydrated).
47
+ const useSlotted = Astro.slots.has("default");
48
+
49
+ const bindings = {
50
+ segments,
51
+ value: value ?? null,
52
+ disabled,
53
+ size,
54
+ tone,
55
+ label: label ?? null,
56
+ labelledby: labelledby ?? null,
57
+ ariaLabel: ariaLabel ?? null,
58
+ elementId,
59
+ };
60
+ const light = useSlotted ? "" : await renderFragmentLight("segmented", bindings);
61
+ ---
62
+
63
+ {useSlotted ? (
64
+ <xtyle-segmented
65
+ value={value}
66
+ disabled={disabled || undefined}
67
+ size={size}
68
+ tone={tone}
69
+ label={label}
70
+ labelledby={labelledby}
71
+ aria-label={ariaLabel}
72
+ name={name}
73
+ class={extra}
74
+ {...rest}
75
+ >
76
+ <slot />
77
+ </xtyle-segmented>
78
+ ) : (
79
+ <xtyle-segmented
80
+ value={value}
81
+ options={optionsAttr}
82
+ disabled={disabled || undefined}
83
+ size={size}
84
+ tone={tone}
85
+ label={label}
86
+ labelledby={labelledby}
87
+ aria-label={ariaLabel}
88
+ name={name}
89
+ class={extra}
90
+ {...rest}
91
+ set:html={light}
92
+ />
93
+ )}
94
+
95
+ {!isStatic && <script>import "@xtyle/core/elements";</script>}
@@ -0,0 +1,79 @@
1
+ ---
2
+ import { renderFragmentLight } from "@xtyle/core/elements/ssr";
3
+
4
+ type Size = "sm" | "md" | "lg";
5
+
6
+ interface Props {
7
+ label?: string;
8
+ name?: string;
9
+ value?: string;
10
+ size?: Size;
11
+ invalid?: boolean;
12
+ error?: string;
13
+ disabled?: boolean;
14
+ required?: boolean;
15
+ ariaLabel?: string;
16
+ /** Render zero-JS: emit the resolved light-DOM markup but never load the runtime to hydrate it. */
17
+ static?: boolean;
18
+ class?: string;
19
+ /** Any other attribute (`id`, `title`, `data-*`, `aria-*`, …) passes through to the element. */
20
+ [key: string]: unknown;
21
+ }
22
+
23
+ const {
24
+ label,
25
+ name,
26
+ value,
27
+ size = "md",
28
+ invalid = false,
29
+ error,
30
+ disabled = false,
31
+ required = false,
32
+ ariaLabel,
33
+ static: isStatic = false,
34
+ class: extra,
35
+ ...rest
36
+ } = Astro.props;
37
+
38
+ const fieldId = `xtyle-select-${Math.random().toString(36).slice(2, 9)}`;
39
+ const errorId = `${fieldId}-error`;
40
+
41
+ // The consumer's `<option>`/`<optgroup>` children populate the rendered `<select>` (via
42
+ // `bindings.optionsHtml`) AND ride along as hidden light-DOM children after the chrome, so the
43
+ // element can re-read them on a rebuild. `xtyle-select > option` is `display:none` (see
44
+ // `hostDisplayCss`), so the bare copies never show.
45
+ const optionsHtml = Astro.slots.has("default") ? await Astro.slots.render("default") : "";
46
+
47
+ const bindings = {
48
+ label: label ?? null,
49
+ value: value ?? null,
50
+ size,
51
+ disabled,
52
+ invalid,
53
+ required,
54
+ error: error ?? null,
55
+ name: name ?? null,
56
+ fieldId,
57
+ errorId,
58
+ optionsHtml,
59
+ };
60
+ const light = await renderFragmentLight("select", bindings);
61
+ const composed = light + optionsHtml;
62
+ ---
63
+
64
+ <xtyle-select
65
+ label={label}
66
+ value={value}
67
+ size={size}
68
+ name={name}
69
+ disabled={disabled || undefined}
70
+ invalid={invalid || undefined}
71
+ required={required || undefined}
72
+ error={error}
73
+ aria-label={ariaLabel}
74
+ class={extra}
75
+ set:html={composed}
76
+ {...rest}
77
+ />
78
+
79
+ {!isStatic && <script>import "@xtyle/core/elements";</script>}
@@ -0,0 +1,36 @@
1
+ ---
2
+ import { renderFragmentLight } from "@xtyle/core/elements/ssr";
3
+
4
+ type Orientation = "horizontal" | "vertical";
5
+ type SeparatorVariant = "default" | "with-label";
6
+ type SeparatorSize = "thin" | "normal";
7
+
8
+ interface Props {
9
+ orientation?: Orientation;
10
+ variant?: SeparatorVariant;
11
+ size?: SeparatorSize;
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
+ orientation = "horizontal",
21
+ variant = "default",
22
+ size = "normal",
23
+ static: isStatic = false,
24
+ class: extra,
25
+ ...rest
26
+ } = Astro.props;
27
+
28
+ const bindings = { orientation, variant, size };
29
+ const chrome = await renderFragmentLight("separator", bindings);
30
+ const slotHtml = Astro.slots.has("default") ? await Astro.slots.render("default") : "";
31
+ const composed = chrome.replace("<slot></slot>", () => slotHtml);
32
+ ---
33
+
34
+ <xtyle-separator orientation={orientation} variant={variant} size={size} class={extra} set:html={composed} {...rest} />
35
+
36
+ {!isStatic && <script>import "@xtyle/core/elements";</script>}
@@ -0,0 +1,25 @@
1
+ ---
2
+ import { renderFragmentLight } from "@xtyle/core/elements/ssr";
3
+
4
+ type SkeletonShape = "text" | "line" | "block" | "circle";
5
+ type Size = "sm" | "md" | "lg";
6
+
7
+ interface Props {
8
+ shape?: SkeletonShape;
9
+ size?: Size;
10
+ /** Render zero-JS: emit the resolved light-DOM markup 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 { shape = "text", size = "md", static: isStatic = false, class: extra, ...rest } = Astro.props;
18
+
19
+ const bindings = { shape, size };
20
+ const composed = await renderFragmentLight("skeleton", bindings);
21
+ ---
22
+
23
+ <xtyle-skeleton shape={shape} size={size} class={extra} set:html={composed} {...rest} />
24
+
25
+ {!isStatic && <script>import "@xtyle/core/elements";</script>}
@@ -0,0 +1,93 @@
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
+ value?: number;
9
+ min?: number;
10
+ max?: number;
11
+ step?: number;
12
+ disabled?: boolean;
13
+ size?: Size;
14
+ tone?: Tone;
15
+ label?: string;
16
+ labelledby?: string;
17
+ name?: string;
18
+ showValue?: boolean;
19
+ hideLabel?: boolean;
20
+ /** Reset value for a double-click on the thumb. Defaults to the initial `value`. */
21
+ default?: number;
22
+ /** Disable click-to-edit on the shown value (it is on by default when `showValue` is set). */
23
+ staticValue?: boolean;
24
+ /** Render zero-JS: emit the resolved light-DOM markup but never load the runtime to hydrate it. */
25
+ static?: boolean;
26
+ class?: string;
27
+ /** Any other attribute (`id`, `title`, `data-*`, `aria-*`, …) passes through to the element. */
28
+ [key: string]: unknown;
29
+ }
30
+
31
+ const {
32
+ value = 0,
33
+ min = 0,
34
+ max = 100,
35
+ step = 1,
36
+ disabled = false,
37
+ size = "md",
38
+ tone = "accent",
39
+ label,
40
+ labelledby,
41
+ name,
42
+ showValue = false,
43
+ hideLabel = false,
44
+ default: defaultValue,
45
+ staticValue = false,
46
+ static: isStatic = false,
47
+ class: extra,
48
+ ...rest
49
+ } = Astro.props;
50
+
51
+ const elementId = `xtyle-slider-${Math.random().toString(36).slice(2, 8)}`;
52
+ const editableValue = showValue && !staticValue;
53
+
54
+ const bindings = {
55
+ value,
56
+ min,
57
+ max,
58
+ step,
59
+ disabled,
60
+ size,
61
+ tone,
62
+ label: label ?? null,
63
+ labelledby: labelledby ?? null,
64
+ showValue,
65
+ hideLabel,
66
+ valueText: String(value),
67
+ elementId,
68
+ editableValue,
69
+ };
70
+ const light = await renderFragmentLight("slider", bindings);
71
+ ---
72
+
73
+ <xtyle-slider
74
+ value={value}
75
+ min={min}
76
+ max={max}
77
+ step={step}
78
+ disabled={disabled || undefined}
79
+ size={size}
80
+ tone={tone}
81
+ label={label}
82
+ labelledby={labelledby}
83
+ name={name}
84
+ show-value={showValue || undefined}
85
+ hide-label={hideLabel || undefined}
86
+ default={defaultValue}
87
+ static-value={staticValue || undefined}
88
+ class={extra}
89
+ {...rest}
90
+ set:html={light}
91
+ />
92
+
93
+ {!isStatic && <script>import "@xtyle/core/elements";</script>}
@@ -0,0 +1,79 @@
1
+ ---
2
+ import { renderFragmentLight } from "@xtyle/core/elements/ssr";
3
+ import { windowedPlot } from "@xtyle/core";
4
+ import type { SparklineVariant, SparklineTone, TimeSample } from "@xtyle/core";
5
+
6
+ interface Props {
7
+ values?: number[];
8
+ /** Time-windowed mode: timestamped points (`at` is epoch ms or a date string) placed on a real
9
+ * time axis instead of even spacing. Pass alongside `window` or `domain`. */
10
+ points?: TimeSample[];
11
+ /** The sliding window width in ms (default 5m), ending at now; ignored when `domain` is set. */
12
+ window?: number;
13
+ /** An explicit `[start, end]` x-axis span (epoch ms or date strings), instead of a sliding window. */
14
+ domain?: [number | string, number | string];
15
+ /** Render the line as a sample-and-hold step (for on/off or discrete series). */
16
+ step?: boolean;
17
+ variant?: SparklineVariant;
18
+ tone?: SparklineTone;
19
+ showEnd?: boolean;
20
+ min?: number;
21
+ max?: number;
22
+ label?: string;
23
+ /** Render zero-JS: emit the resolved light-DOM markup but never load the runtime to hydrate it. */
24
+ static?: boolean;
25
+ class?: string;
26
+ /** Any other attribute (`id`, `style`, `data-*`, `aria-*`, …) passes through to the element. */
27
+ [key: string]: unknown;
28
+ }
29
+
30
+ const {
31
+ values = [],
32
+ points,
33
+ window: windowMs,
34
+ domain,
35
+ step = false,
36
+ variant = "line",
37
+ tone = "accent",
38
+ showEnd = true,
39
+ min,
40
+ max,
41
+ label,
42
+ static: isStatic = false,
43
+ class: extra,
44
+ ...rest
45
+ } = Astro.props;
46
+
47
+ const plot =
48
+ points && points.length > 0 ? windowedPlot(points, { window: windowMs, domain, now: Date.now() }) : null;
49
+ const bindings = {
50
+ ...(plot ? { plot } : { values }),
51
+ variant,
52
+ tone,
53
+ showEnd,
54
+ step,
55
+ min,
56
+ max,
57
+ label: label ?? null,
58
+ };
59
+ const chrome = await renderFragmentLight("sparkline", bindings);
60
+ ---
61
+
62
+ <xtyle-sparkline
63
+ values={JSON.stringify(values)}
64
+ points={points ? JSON.stringify(points) : undefined}
65
+ window={windowMs ?? undefined}
66
+ domain={domain ? JSON.stringify(domain) : undefined}
67
+ variant={variant}
68
+ tone={tone}
69
+ show-end={showEnd ? undefined : "false"}
70
+ step={step || undefined}
71
+ min={min ?? undefined}
72
+ max={max ?? undefined}
73
+ label={label}
74
+ class={extra}
75
+ set:html={chrome}
76
+ {...rest}
77
+ />
78
+
79
+ {!isStatic && <script>import "@xtyle/core/elements";</script>}
@@ -0,0 +1,37 @@
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
+ "aria-label"?: string;
11
+ /** Render zero-JS: emit the resolved light-DOM markup but never load the runtime to hydrate it. */
12
+ static?: boolean;
13
+ class?: string;
14
+ /** Any other attribute (`id`, `title`, `data-*`, `aria-*`, …) passes through to the element. */
15
+ [key: string]: unknown;
16
+ }
17
+
18
+ const {
19
+ tone = "accent",
20
+ size = "md",
21
+ "aria-label": ariaLabel = "Loading",
22
+ static: isStatic = false,
23
+ class: extra,
24
+ ...rest
25
+ } = Astro.props;
26
+
27
+ const bindings = {
28
+ tone,
29
+ size,
30
+ label: ariaLabel,
31
+ };
32
+ const composed = await renderFragmentLight("spinner", bindings);
33
+ ---
34
+
35
+ <xtyle-spinner tone={tone} size={size} aria-label={ariaLabel} class={extra} set:html={composed} {...rest} />
36
+
37
+ {!isStatic && <script>import "@xtyle/core/elements";</script>}
@@ -0,0 +1,87 @@
1
+ ---
2
+ import { renderFragmentLight } from "@xtyle/core/elements/ssr";
3
+
4
+ type SplitterOrientation = "vertical" | "horizontal";
5
+ type SplitterSize = "sm" | "md" | "lg";
6
+
7
+ interface Props {
8
+ orientation?: SplitterOrientation;
9
+ size?: SplitterSize;
10
+ line?: boolean;
11
+ min?: number;
12
+ max?: number;
13
+ step?: number;
14
+ value: number;
15
+ default?: number;
16
+ disabled?: boolean;
17
+ reversed?: boolean;
18
+ /** The CSS custom property the splitter writes the pane size into. */
19
+ var?: string;
20
+ /** The id of the element the var is set on; defaults to the splitter's parent. */
21
+ for?: string;
22
+ label?: string;
23
+ labelledby?: string;
24
+ /** Render zero-JS: emit the resolved light-DOM markup but never load the runtime to hydrate it. */
25
+ static?: boolean;
26
+ class?: string;
27
+ /** Any other attribute (`id`, `title`, `data-*`, `aria-*`, …) passes through to the element. */
28
+ [key: string]: unknown;
29
+ }
30
+
31
+ const {
32
+ orientation = "vertical",
33
+ size = "md",
34
+ line = false,
35
+ min = 0,
36
+ max,
37
+ step = 1,
38
+ value,
39
+ default: defaultValue,
40
+ disabled = false,
41
+ reversed = false,
42
+ var: varName,
43
+ for: forId,
44
+ label,
45
+ labelledby,
46
+ static: isStatic = false,
47
+ class: extra,
48
+ ...rest
49
+ } = Astro.props;
50
+
51
+ const ariaMax = max ?? value;
52
+
53
+ const bindings = {
54
+ orientation,
55
+ size,
56
+ line,
57
+ value,
58
+ min,
59
+ max: ariaMax,
60
+ disabled,
61
+ label: label ?? null,
62
+ labelledby: labelledby ?? null,
63
+ };
64
+ const light = await renderFragmentLight("splitter", bindings);
65
+ ---
66
+
67
+ <xtyle-splitter
68
+ orientation={orientation}
69
+ size={size}
70
+ line={line || undefined}
71
+ min={min}
72
+ max={max ?? undefined}
73
+ step={step}
74
+ value={value}
75
+ default={defaultValue ?? undefined}
76
+ disabled={disabled || undefined}
77
+ reversed={reversed || undefined}
78
+ var={varName}
79
+ for={forId}
80
+ label={label}
81
+ labelledby={labelledby}
82
+ class={extra}
83
+ {...rest}
84
+ set:html={light}
85
+ />
86
+
87
+ {!isStatic && <script>import "@xtyle/core/elements";</script>}
@@ -0,0 +1,42 @@
1
+ ---
2
+ import { renderFragmentLight } from "@xtyle/core/elements/ssr";
3
+
4
+ type StackAlign = "start" | "center" | "end" | "stretch" | "baseline";
5
+ type StackJustify = "start" | "center" | "end" | "between" | "around" | "evenly";
6
+
7
+ interface Props {
8
+ gap?: number;
9
+ align?: StackAlign;
10
+ justify?: StackJustify;
11
+ inline?: 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 { gap = 4, align, justify, inline = false, static: isStatic = false, class: extra, ...rest } = Astro.props;
20
+
21
+ const bindings = {
22
+ gap,
23
+ align: align ?? null,
24
+ justify: justify ?? null,
25
+ inline,
26
+ };
27
+ const chrome = await renderFragmentLight("stack", bindings);
28
+ const slotHtml = Astro.slots.has("default") ? await Astro.slots.render("default") : "";
29
+ const composed = chrome.replace("<slot></slot>", () => slotHtml);
30
+ ---
31
+
32
+ <xtyle-stack
33
+ gap={gap}
34
+ align={align}
35
+ justify={justify}
36
+ inline={inline || undefined}
37
+ class={extra}
38
+ set:html={composed}
39
+ {...rest}
40
+ />
41
+
42
+ {!isStatic && <script>import "@xtyle/core/elements";</script>}
package/src/Stat.astro ADDED
@@ -0,0 +1,70 @@
1
+ ---
2
+ import { renderFragmentLight } from "@xtyle/core/elements/ssr";
3
+
4
+ type StatTrend = "up" | "down" | "flat";
5
+ type StatSentiment = "positive" | "negative" | "neutral";
6
+ type StatAlign = "start" | "center";
7
+ type Size = "sm" | "md" | "lg";
8
+
9
+ interface Props {
10
+ label?: string;
11
+ delta?: string;
12
+ trend?: StatTrend;
13
+ /** The delta's color reading. Omit to derive it from `trend` (up→positive, down→negative, flat→neutral). */
14
+ sentiment?: StatSentiment;
15
+ caption?: string;
16
+ size?: Size;
17
+ align?: StatAlign;
18
+ /** Lay the stat out horizontally: value, label, and trend delta on one line, like a ticker. */
19
+ inline?: boolean;
20
+ /** Render zero-JS: emit the resolved light-DOM markup but never load the runtime to hydrate it. */
21
+ static?: boolean;
22
+ class?: string;
23
+ /** Any other attribute (`id`, `title`, `data-*`, `aria-*`, …) passes through to the element. */
24
+ [key: string]: unknown;
25
+ }
26
+
27
+ const {
28
+ label,
29
+ delta,
30
+ trend = "flat",
31
+ sentiment,
32
+ caption,
33
+ size = "md",
34
+ align = "start",
35
+ inline = false,
36
+ static: isStatic = false,
37
+ class: extra,
38
+ ...rest
39
+ } = Astro.props;
40
+
41
+ const bindings = {
42
+ label: label ?? null,
43
+ delta: delta ?? null,
44
+ trend,
45
+ sentiment,
46
+ caption: caption ?? null,
47
+ size,
48
+ align,
49
+ inline,
50
+ };
51
+ const chrome = await renderFragmentLight("stat", bindings);
52
+ const slotHtml = Astro.slots.has("default") ? await Astro.slots.render("default") : "";
53
+ const composed = chrome.replace("<slot></slot>", () => slotHtml);
54
+ ---
55
+
56
+ <xtyle-stat
57
+ label={label}
58
+ delta={delta}
59
+ trend={trend}
60
+ sentiment={sentiment}
61
+ caption={caption}
62
+ size={size}
63
+ align={align}
64
+ inline={inline || undefined}
65
+ class={extra}
66
+ set:html={composed}
67
+ {...rest}
68
+ />
69
+
70
+ {!isStatic && <script>import "@xtyle/core/elements";</script>}
@@ -0,0 +1,56 @@
1
+ ---
2
+ import { renderFragmentLight } from "@xtyle/core/elements/ssr";
3
+
4
+ interface Props {
5
+ live?: boolean;
6
+ label?: string;
7
+ overflow?: "clip" | "wrap" | "scroll" | "collapse";
8
+ manualOverflow?: boolean;
9
+ /** Draw a divider between adjacent items at the bar's own spacing — so items stay
10
+ * individual (and collapse counts them independently) instead of carrying their own separators. */
11
+ separated?: 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
+ live = false,
21
+ label,
22
+ overflow = "clip",
23
+ manualOverflow = false,
24
+ separated = false,
25
+ static: isStatic = false,
26
+ class: extra,
27
+ ...rest
28
+ } = Astro.props;
29
+
30
+ const elementId = `xtyle-statusbar-${Math.random().toString(36).slice(2, 8)}`;
31
+
32
+ const bindings = {
33
+ live,
34
+ label: label ?? null,
35
+ overflow,
36
+ manualOverflow,
37
+ separated,
38
+ elementId,
39
+ };
40
+ const light = await renderFragmentLight("statusbar", bindings);
41
+ const slotHtml = Astro.slots.has("default") ? await Astro.slots.render("default") : "";
42
+ const composed = light.replace("<slot></slot>", () => slotHtml);
43
+ ---
44
+
45
+ <xtyle-statusbar
46
+ live={live || undefined}
47
+ label={label}
48
+ overflow={overflow}
49
+ manual-overflow={manualOverflow || undefined}
50
+ separated={separated || undefined}
51
+ class={extra}
52
+ set:html={composed}
53
+ {...rest}
54
+ />
55
+
56
+ {!isStatic && <script>import "@xtyle/core/elements";</script>}