@elysn/astro 0.0.2 → 0.0.4

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 (54) hide show
  1. package/LICENSE +201 -0
  2. package/index.ts +46 -0
  3. package/package.json +36 -16
  4. package/src/AccessibleIcon.astro +14 -0
  5. package/src/AspectRatio.astro +14 -0
  6. package/src/Avatar.astro +54 -0
  7. package/src/Badge.astro +34 -0
  8. package/src/Blockquote.astro +21 -0
  9. package/src/Box.astro +13 -0
  10. package/src/Button.astro +27 -8
  11. package/src/Callout.astro +34 -0
  12. package/src/CalloutIcon.astro +12 -0
  13. package/src/CalloutText.astro +12 -0
  14. package/src/Card.astro +30 -0
  15. package/src/Checkbox.astro +212 -0
  16. package/src/Code.astro +21 -0
  17. package/src/Container.astro +26 -0
  18. package/src/DecoratedBox.astro +22 -0
  19. package/src/Em.astro +10 -0
  20. package/src/Flex.astro +25 -0
  21. package/src/Grid.astro +21 -0
  22. package/src/Heading.astro +43 -0
  23. package/src/InputControl.astro +40 -0
  24. package/src/InputField.astro +10 -0
  25. package/src/InputSlot.astro +41 -0
  26. package/src/Kbd.astro +11 -0
  27. package/src/Link.astro +33 -0
  28. package/src/Panel.astro +12 -0
  29. package/src/Progress.astro +63 -0
  30. package/src/Quote.astro +10 -0
  31. package/src/RadioCards.astro +71 -0
  32. package/src/RadioCardsItem.astro +41 -0
  33. package/src/RadioGroup.astro +70 -0
  34. package/src/RadioGroupItem.astro +53 -0
  35. package/src/Section.astro +23 -0
  36. package/src/SegmentedControl.astro +189 -0
  37. package/src/Separator.astro +25 -0
  38. package/src/Skeleton.astro +30 -0
  39. package/src/Spinner.astro +31 -0
  40. package/src/Strong.astro +10 -0
  41. package/src/Switch.astro +164 -0
  42. package/src/Tabs.astro +179 -0
  43. package/src/TabsContent.astro +20 -0
  44. package/src/TabsIndicator.astro +17 -0
  45. package/src/TabsList.astro +12 -0
  46. package/src/TabsTrigger.astro +23 -0
  47. package/src/Text.astro +43 -0
  48. package/src/TextArea.astro +30 -0
  49. package/src/TextField.astro +70 -0
  50. package/src/VisuallyHidden.astro +10 -0
  51. package/src/internal/radio-group.ts +82 -0
  52. package/src/internal/ssr.ts +18 -0
  53. package/src/internal/zag.ts +24 -0
  54. package/style.css +5 -0
@@ -0,0 +1,212 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+
4
+ type Size = "xs" | "sm" | "md" | "lg";
5
+
6
+ interface Props extends Omit<HTMLAttributes<"label">, "color" | "dir" | "name"> {
7
+ className?: string;
8
+ color?: string;
9
+ defaultChecked?: boolean | "indeterminate";
10
+ dir?: "ltr" | "rtl";
11
+ disabled?: boolean;
12
+ highContrast?: boolean;
13
+ invalid?: boolean;
14
+ name?: string;
15
+ radius?: "none" | "small" | "medium" | "large" | "full";
16
+ required?: boolean;
17
+ size?: Size;
18
+ value?: string;
19
+ variant?: "surface" | "soft";
20
+ }
21
+ const {
22
+ className,
23
+ color,
24
+ defaultChecked,
25
+ dir,
26
+ disabled,
27
+ highContrast,
28
+ invalid,
29
+ name,
30
+ radius,
31
+ required,
32
+ size = "md",
33
+ value = "on",
34
+ variant = "surface",
35
+ ...rest
36
+ } = Astro.props as Props;
37
+
38
+ const sizes: Record<Size, string> = {
39
+ xs: "el-Checkbox-size-xs",
40
+ sm: "el-Checkbox-size-sm",
41
+ md: "el-Checkbox-size-md",
42
+ lg: "el-Checkbox-size-lg",
43
+ };
44
+ const indeterminate = defaultChecked === "indeterminate";
45
+ const checked = defaultChecked === true;
46
+ const state = indeterminate ? "indeterminate" : checked ? "checked" : "unchecked";
47
+ const hasLabel = Astro.slots.has("default");
48
+ ---
49
+
50
+ <!-- display: contents keeps the Zag root (a <label>) as the visual box -->
51
+ <el-checkbox
52
+ style="display: contents"
53
+ data-default-checked={defaultChecked === undefined ? undefined : String(defaultChecked)}
54
+ data-dir={dir}
55
+ >
56
+ <label
57
+ {...rest}
58
+ data-scope="checkbox"
59
+ data-part="root"
60
+ data-state={state}
61
+ data-disabled={disabled ? "" : undefined}
62
+ data-invalid={invalid ? "" : undefined}
63
+ data-accent-color={color}
64
+ data-high-contrast={highContrast ? "true" : undefined}
65
+ data-radius={radius}
66
+ data-variant={variant}
67
+ class:list={["el-Checkbox", sizes[size], className]}
68
+ >
69
+ <div data-scope="checkbox" data-part="control" data-state={state} class="el-Checkbox-control">
70
+ <div
71
+ data-scope="checkbox"
72
+ data-part="indicator"
73
+ data-indicator="checked"
74
+ data-state={state}
75
+ hidden={!checked}
76
+ >
77
+ <svg
78
+ fill="none"
79
+ height="10"
80
+ stroke="currentColor"
81
+ stroke-width="2.5"
82
+ viewBox="0 0 14 14"
83
+ width="10"
84
+ xmlns="http://www.w3.org/2000/svg"
85
+ >
86
+ <path d="M2 7L5.5 10.5L12 3" stroke-linecap="round" stroke-linejoin="round"></path>
87
+ </svg>
88
+ </div>
89
+ <div
90
+ data-scope="checkbox"
91
+ data-part="indicator"
92
+ data-indicator="indeterminate"
93
+ data-state={state}
94
+ hidden={!indeterminate}
95
+ >
96
+ <svg
97
+ fill="none"
98
+ height="10"
99
+ stroke="currentColor"
100
+ stroke-width="2.5"
101
+ viewBox="0 0 14 14"
102
+ width="10"
103
+ xmlns="http://www.w3.org/2000/svg"
104
+ >
105
+ <path d="M2 7H12" stroke-linecap="round"></path>
106
+ </svg>
107
+ </div>
108
+ </div>
109
+ {
110
+ hasLabel && (
111
+ <span data-scope="checkbox" data-part="label" data-state={state} class="el-Checkbox-label">
112
+ <slot />
113
+ </span>
114
+ )
115
+ }
116
+ <input
117
+ type="checkbox"
118
+ data-part="hidden-input"
119
+ name={name}
120
+ value={value}
121
+ checked={checked}
122
+ disabled={disabled}
123
+ required={required}
124
+ style="border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;white-space:nowrap;word-wrap:normal"
125
+ />
126
+ </label>
127
+ </el-checkbox>
128
+
129
+ <script>
130
+ import * as zcheckbox from "@zag-js/checkbox";
131
+ import { VanillaMachine, normalizeProps } from "@zag-js/vanilla";
132
+ import { createSpreader, nextId, textDirection } from "./internal/zag";
133
+
134
+ type Machine = ReturnType<typeof createMachine>;
135
+ const createMachine = (props: zcheckbox.Props) => new VanillaMachine(zcheckbox.machine, props);
136
+
137
+ class ElCheckbox extends HTMLElement {
138
+ #machine?: Machine;
139
+ #unsubscribe?: () => void;
140
+ #spread = createSpreader("");
141
+
142
+ connectedCallback() {
143
+ if (this.#machine) return;
144
+ const id = nextId("el-checkbox");
145
+ this.#spread = createSpreader(id);
146
+ const input = this.#part("hidden-input") as HTMLInputElement | undefined;
147
+ const initial = this.dataset["defaultChecked"];
148
+ const machine = createMachine({
149
+ id,
150
+ defaultChecked: initial === "indeterminate" ? "indeterminate" : initial === "true",
151
+ disabled: input?.disabled,
152
+ required: input?.required,
153
+ invalid: this.querySelector("[data-invalid]") !== null,
154
+ name: input?.name || undefined,
155
+ value: input?.value,
156
+ dir: textDirection(this),
157
+ getRootNode: () => this.getRootNode(),
158
+ onCheckedChange: ({ checked }: { checked: boolean | "indeterminate" }) =>
159
+ this.dispatchEvent(
160
+ new CustomEvent("el-checkbox:checked-change", { detail: { checked }, bubbles: true }),
161
+ ),
162
+ });
163
+ this.#machine = machine;
164
+ machine.start();
165
+ this.#render();
166
+ this.#unsubscribe = machine.subscribe(() => this.#render());
167
+ this.dataset["ready"] = "";
168
+ }
169
+
170
+ disconnectedCallback() {
171
+ this.#unsubscribe?.();
172
+ this.#spread.clear();
173
+ this.#machine?.stop();
174
+ this.#machine = undefined;
175
+ delete this.dataset["ready"];
176
+ }
177
+
178
+ /** Programmatic API: `el.checked` / `el.checked = "indeterminate"`. */
179
+ get checked() {
180
+ const api = this.#api();
181
+ return api?.indeterminate ? "indeterminate" : (api?.checked ?? false);
182
+ }
183
+ set checked(checked: boolean | "indeterminate") {
184
+ this.#api()?.setChecked(checked);
185
+ }
186
+
187
+ #api() {
188
+ return this.#machine && zcheckbox.connect(this.#machine.service, normalizeProps);
189
+ }
190
+
191
+ #part(name: string) {
192
+ return this.querySelector<HTMLElement>(`[data-part='${name}']`) ?? undefined;
193
+ }
194
+
195
+ #render() {
196
+ const api = this.#api();
197
+ if (!api) return;
198
+ // Zag never looks the root up by id, so keep the author's `id` instead of its generated one
199
+ const { id: _id, ...rootProps } = api.getRootProps();
200
+ this.#spread.apply(this.#part("root"), rootProps);
201
+ this.#spread.apply(this.#part("control"), api.getControlProps());
202
+ this.#spread.apply(this.#part("label"), api.getLabelProps());
203
+ this.#spread.apply(this.#part("hidden-input"), api.getHiddenInputProps());
204
+ for (const el of this.querySelectorAll<HTMLElement>("[data-part='indicator']")) {
205
+ this.#spread.apply(el, api.getIndicatorProps());
206
+ el.hidden = el.dataset["indicator"] === "indeterminate" ? !api.indeterminate : !api.checked;
207
+ }
208
+ }
209
+ }
210
+
211
+ if (!customElements.get("el-checkbox")) customElements.define("el-checkbox", ElCheckbox);
212
+ </script>
package/src/Code.astro ADDED
@@ -0,0 +1,21 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+
4
+ interface Props extends Omit<HTMLAttributes<"code">, "color"> {
5
+ className?: string;
6
+ color?: string;
7
+ highContrast?: boolean;
8
+ size?: "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
9
+ variant?: "solid" | "soft" | "surface";
10
+ }
11
+ const { className, color, highContrast, size, variant = "soft", ...rest } = Astro.props as Props;
12
+ ---
13
+
14
+ <code
15
+ {...rest}
16
+ data-accent-color={color}
17
+ data-high-contrast={highContrast ? true : undefined}
18
+ data-size={size}
19
+ data-variant={variant}
20
+ class:list={["el-Code", className]}><slot /></code
21
+ >
@@ -0,0 +1,26 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+
4
+ type Size = "xs" | "sm" | "md" | "lg" | "xl";
5
+
6
+ interface Props extends Omit<HTMLAttributes<"div">, "color"> {
7
+ className?: string;
8
+ color?: string;
9
+ size?: Size;
10
+ }
11
+ const { className, color, size = "xl", ...rest } = Astro.props as Props;
12
+
13
+ const sizes: Record<Size, string> = {
14
+ xs: "el-Container-size-xs",
15
+ sm: "el-Container-size-sm",
16
+ md: "el-Container-size-md",
17
+ lg: "el-Container-size-lg",
18
+ xl: "el-Container-size-xl",
19
+ };
20
+ ---
21
+
22
+ <div {...rest} data-accent-color={color} class:list={["el-Container", sizes[size], className]}>
23
+ <div class="el-ContainerInner">
24
+ <slot />
25
+ </div>
26
+ </div>
@@ -0,0 +1,22 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+
4
+ interface Props extends HTMLAttributes<"div"> {
5
+ className?: string;
6
+ }
7
+ const { className, style, ...rest } = Astro.props as Props;
8
+
9
+ const hatch =
10
+ "url(\"data:image/svg+xml,%3Csvg width='6' height='6' viewBox='0 0 6 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%239C92AC' fill-opacity='0.2' fill-rule='evenodd'%3E%3Cpath d='M5 0h1L0 6V5zM6 5v1H5z'/%3E%3C/g%3E%3C/svg%3E\")";
11
+ ---
12
+
13
+ <div
14
+ {...rest}
15
+ class:list={[
16
+ "bg-gray-a3 border-gray-a5 h-full w-full rounded-md border text-center",
17
+ className,
18
+ ]}
19
+ style={[`background-image: ${hatch}`, style].filter(Boolean).join(";")}
20
+ >
21
+ <slot />
22
+ </div>
package/src/Em.astro ADDED
@@ -0,0 +1,10 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+
4
+ interface Props extends HTMLAttributes<"em"> {
5
+ className?: string;
6
+ }
7
+ const { className, ...rest } = Astro.props as Props;
8
+ ---
9
+
10
+ <em {...rest} class:list={["el-Em", className]}><slot /></em>
package/src/Flex.astro ADDED
@@ -0,0 +1,25 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+
4
+ interface Props extends HTMLAttributes<"div"> {
5
+ align?: "start" | "center" | "end" | "stretch" | "baseline";
6
+ className?: string;
7
+ direction?: "row" | "column" | "row-reverse" | "column-reverse";
8
+ gap?: "xs" | "sm" | "md" | "lg" | "xl";
9
+ justify?: "start" | "center" | "end" | "between" | "around" | "evenly";
10
+ wrap?: "nowrap" | "wrap" | "wrap-reverse";
11
+ }
12
+ const { align, className, direction, gap, justify, wrap, ...rest } = Astro.props as Props;
13
+ ---
14
+
15
+ <div
16
+ {...rest}
17
+ data-align={align}
18
+ data-direction={direction}
19
+ data-gap={gap}
20
+ data-justify={justify}
21
+ data-wrap={wrap}
22
+ class:list={["el-Flex", className]}
23
+ >
24
+ <slot />
25
+ </div>
package/src/Grid.astro ADDED
@@ -0,0 +1,21 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+
4
+ interface Props extends Omit<HTMLAttributes<"div">, "style"> {
5
+ className?: string;
6
+ columns?: string;
7
+ gap?: "xs" | "sm" | "md" | "lg" | "xl";
8
+ style?: Record<string, string | number>;
9
+ }
10
+ const { className, columns, gap, style, ...rest } = Astro.props as Props;
11
+ ---
12
+
13
+ <div
14
+ {...rest}
15
+ data-columns={columns}
16
+ data-gap={gap}
17
+ class:list={["el-Grid", className]}
18
+ style={columns ? { gridTemplateColumns: columns, ...style } : style}
19
+ >
20
+ <slot />
21
+ </div>
@@ -0,0 +1,43 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+
4
+ interface Props extends Omit<HTMLAttributes<"h2">, "color"> {
5
+ align?: "left" | "center" | "right";
6
+ as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
7
+ className?: string;
8
+ color?: string;
9
+ highContrast?: boolean;
10
+ size?: "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
11
+ trim?: "normal" | "start" | "end" | "both";
12
+ truncate?: boolean;
13
+ weight?: "light" | "regular" | "medium" | "bold";
14
+ wrap?: "normal" | "nowrap" | "pretty" | "balance";
15
+ }
16
+ const {
17
+ align,
18
+ as: Tag = "h2",
19
+ className,
20
+ color,
21
+ highContrast,
22
+ size,
23
+ trim,
24
+ truncate,
25
+ weight,
26
+ wrap,
27
+ ...rest
28
+ } = Astro.props as Props;
29
+ ---
30
+
31
+ <Tag
32
+ {...rest}
33
+ data-accent-color={color}
34
+ data-align={align}
35
+ data-high-contrast={highContrast ? true : undefined}
36
+ data-size={size}
37
+ data-trim={trim}
38
+ data-weight={weight}
39
+ data-wrap={wrap}
40
+ class:list={["el-Heading", truncate && "el-Heading-truncate", className]}
41
+ >
42
+ <slot />
43
+ </Tag>
@@ -0,0 +1,40 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+
4
+ interface Props extends Omit<HTMLAttributes<"div">, "color"> {
5
+ className?: string;
6
+ color?: string;
7
+ /** Defaults to the surrounding `TextField` variant, else surface. */
8
+ variant?: "surface" | "soft";
9
+ }
10
+ const { className, color, variant, ...rest } = Astro.props as Props;
11
+ ---
12
+
13
+ <div
14
+ {...rest}
15
+ data-accent-color={color}
16
+ data-variant={variant}
17
+ class:list={["el-InputControl", className]}
18
+ >
19
+ <slot />
20
+ </div>
21
+
22
+ <script>
23
+ // Clicking a slot (not the input, a button or a link) focuses the input, like the React InputControl
24
+ const rightSlot =
25
+ ".el-InputSlot[data-side='right'], .el-InputSlot:not([data-side='right']) ~ .el-InputSlot:not([data-side='left'])";
26
+ document.addEventListener("pointerdown", (event) => {
27
+ const target = event.target;
28
+ if (!(target instanceof Element) || target.closest("input, button, a")) return;
29
+ const control = target.closest(".el-InputControl");
30
+ const input = control?.querySelector<HTMLInputElement>(".el-InputField");
31
+ if (!input || event.defaultPrevented) return;
32
+ const position = target.closest(rightSlot) ? input.value.length : 0;
33
+ requestAnimationFrame(() => {
34
+ try {
35
+ input.setSelectionRange(position, position);
36
+ } catch {}
37
+ input.focus();
38
+ });
39
+ });
40
+ </script>
@@ -0,0 +1,10 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+
4
+ interface Props extends HTMLAttributes<"input"> {
5
+ className?: string;
6
+ }
7
+ const { className, ...rest } = Astro.props as Props;
8
+ ---
9
+
10
+ <input {...rest} class:list={["el-InputField", className]} />
@@ -0,0 +1,41 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+
4
+ type Space = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
5
+
6
+ interface Props extends Omit<HTMLAttributes<"div">, "color" | "style"> {
7
+ className?: string;
8
+ /** Tints the slot with `--accent-a11`. */
9
+ color?: string;
10
+ /** Defaults to left; two unsided slots land left then right. */
11
+ side?: "left" | "right";
12
+ /** Space scale step (0-9) overriding the size-based defaults. */
13
+ gap?: Space;
14
+ px?: Space;
15
+ pl?: Space;
16
+ pr?: Space;
17
+ style?: string;
18
+ }
19
+ const { className, color, side, gap, px, pl, pr, style, ...rest } = Astro.props as Props;
20
+
21
+ const space = (value?: Space) => (value === undefined ? undefined : `var(--space-${value})`);
22
+ const vars = Object.entries({
23
+ "--slot-gap": space(gap),
24
+ "--slot-px": space(px),
25
+ "--slot-pl": space(pl),
26
+ "--slot-pr": space(pr),
27
+ })
28
+ .filter(([, value]) => value !== undefined)
29
+ .map(([name, value]) => `${name}: ${value}`);
30
+ const css = [...vars, style].filter(Boolean).join("; ") || undefined;
31
+ ---
32
+
33
+ <div
34
+ {...rest}
35
+ data-accent-color={color}
36
+ data-side={side}
37
+ style={css}
38
+ class:list={["el-InputSlot", className]}
39
+ >
40
+ <slot />
41
+ </div>
package/src/Kbd.astro ADDED
@@ -0,0 +1,11 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+
4
+ interface Props extends HTMLAttributes<"kbd"> {
5
+ className?: string;
6
+ size?: "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
7
+ }
8
+ const { className, size, ...rest } = Astro.props as Props;
9
+ ---
10
+
11
+ <kbd {...rest} data-size={size} class:list={["el-Kbd", className]}><slot /></kbd>
package/src/Link.astro ADDED
@@ -0,0 +1,33 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+
4
+ interface Props extends Omit<HTMLAttributes<"a">, "color"> {
5
+ className?: string;
6
+ color?: string;
7
+ highContrast?: boolean;
8
+ size?: "xs" | "sm" | "md" | "lg" | "xl";
9
+ truncate?: boolean;
10
+ underline?: "auto" | "always" | "hover" | "none";
11
+ variant?: "soft" | "surface" | "outline";
12
+ }
13
+ const {
14
+ className,
15
+ color,
16
+ highContrast,
17
+ size,
18
+ truncate,
19
+ underline = "auto",
20
+ variant,
21
+ ...rest
22
+ } = Astro.props as Props;
23
+ ---
24
+
25
+ <a
26
+ {...rest}
27
+ data-accent-color={color}
28
+ data-high-contrast={highContrast ? true : undefined}
29
+ data-size={size}
30
+ data-underline={underline}
31
+ data-variant={variant}
32
+ class:list={["el-Link", truncate && "el-Link-truncate", className]}><slot /></a
33
+ >
@@ -0,0 +1,12 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+
4
+ interface Props extends HTMLAttributes<"div"> {
5
+ className?: string;
6
+ }
7
+ const { className, ...rest } = Astro.props as Props;
8
+ ---
9
+
10
+ <div {...rest} class:list={["el-PanelBase", className]}>
11
+ <slot />
12
+ </div>
@@ -0,0 +1,63 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+
4
+ type Size = "xs" | "sm" | "md" | "lg";
5
+
6
+ interface Props extends Omit<HTMLAttributes<"div">, "color"> {
7
+ className?: string;
8
+ color?: string;
9
+ highContrast?: boolean;
10
+ max?: number;
11
+ min?: number;
12
+ radius?: "none" | "small" | "medium" | "large" | "full";
13
+ size?: Size;
14
+ /** Omit for an indeterminate progress bar */
15
+ value?: number;
16
+ variant?: "soft" | "surface";
17
+ }
18
+ const {
19
+ className,
20
+ color,
21
+ highContrast,
22
+ max = 100,
23
+ min = 0,
24
+ radius,
25
+ size = "md",
26
+ value,
27
+ variant = "surface",
28
+ ...rest
29
+ } = Astro.props as Props;
30
+
31
+ const sizes: Record<Size, string> = {
32
+ xs: "el-Progress-size-xs",
33
+ sm: "el-Progress-size-sm",
34
+ md: "el-Progress-size-md",
35
+ lg: "el-Progress-size-lg",
36
+ };
37
+
38
+ const indeterminate = value === undefined;
39
+ const percent = indeterminate ? undefined : ((value - min) / (max - min)) * 100;
40
+ const state = indeterminate ? "indeterminate" : value >= max ? "complete" : "loading";
41
+ ---
42
+
43
+ <div
44
+ {...rest}
45
+ role="progressbar"
46
+ aria-valuemin={min}
47
+ aria-valuemax={max}
48
+ aria-valuenow={value}
49
+ data-accent-color={color}
50
+ data-high-contrast={highContrast ? "true" : undefined}
51
+ data-state={state}
52
+ data-variant={variant}
53
+ class:list={["el-Progress", sizes[size], className]}
54
+ >
55
+ <div class="el-Progress-track" data-radius={radius}>
56
+ <div
57
+ class="el-Progress-range"
58
+ data-state={state}
59
+ style={percent === undefined ? undefined : { width: `${percent}%` }}
60
+ >
61
+ </div>
62
+ </div>
63
+ </div>
@@ -0,0 +1,10 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+
4
+ interface Props extends HTMLAttributes<"q"> {
5
+ className?: string;
6
+ }
7
+ const { className, ...rest } = Astro.props as Props;
8
+ ---
9
+
10
+ <q {...rest} class:list={["el-Quote", className]}><slot /></q>
@@ -0,0 +1,71 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+ import { markChecked } from "./internal/ssr";
4
+
5
+ type Size = "xs" | "sm" | "md";
6
+
7
+ interface Props extends Omit<HTMLAttributes<"div">, "color" | "dir" | "name"> {
8
+ className?: string;
9
+ color?: string;
10
+ defaultValue?: string;
11
+ dir?: "ltr" | "rtl";
12
+ disabled?: boolean;
13
+ highContrast?: boolean;
14
+ name?: string;
15
+ orientation?: "horizontal" | "vertical";
16
+ radius?: "none" | "small" | "medium" | "large" | "full";
17
+ required?: boolean;
18
+ size?: Size;
19
+ variant?: "surface";
20
+ }
21
+ const {
22
+ className,
23
+ color,
24
+ defaultValue,
25
+ dir,
26
+ disabled,
27
+ highContrast,
28
+ name,
29
+ orientation = "vertical",
30
+ radius,
31
+ required,
32
+ size = "sm",
33
+ variant = "surface",
34
+ ...rest
35
+ } = Astro.props as Props;
36
+
37
+ const sizes: Record<Size, string> = {
38
+ xs: "el-RadioCards-size-xs",
39
+ sm: "el-RadioCards-size-sm",
40
+ md: "el-RadioCards-size-md",
41
+ };
42
+ const items = markChecked(await Astro.slots.render("default"), defaultValue);
43
+ ---
44
+
45
+ <!-- Same Zag radio-group machine as RadioGroup: the custom element is shared -->
46
+ <el-radio-group
47
+ {...rest}
48
+ role="radiogroup"
49
+ data-scope="radio-group"
50
+ data-part="root"
51
+ data-slot="control"
52
+ data-accent-color={color}
53
+ data-default-value={defaultValue}
54
+ data-dir={dir}
55
+ data-disabled={disabled ? "" : undefined}
56
+ data-high-contrast={highContrast ? "true" : undefined}
57
+ data-name={name}
58
+ data-orientation={orientation}
59
+ data-radius={radius}
60
+ data-required={required ? "true" : undefined}
61
+ data-variant={variant}
62
+ class:list={["el-RadioCardsRoot", sizes[size], className]}
63
+ >
64
+ <Fragment set:html={items} />
65
+ </el-radio-group>
66
+
67
+ <script>
68
+ import { defineRadioGroup } from "./internal/radio-group";
69
+
70
+ defineRadioGroup();
71
+ </script>