@xaroth.nl/design 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.
Files changed (193) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +62 -0
  3. package/dist/all.css +2536 -0
  4. package/dist/astro.d.ts +41 -0
  5. package/dist/astro.js +41 -0
  6. package/dist/bem.d.ts +12 -0
  7. package/dist/bem.js +19 -0
  8. package/dist/components/alert/alert.astro +46 -0
  9. package/dist/components/alert/alert.css +68 -0
  10. package/dist/components/alert/alert.d.ts +11 -0
  11. package/dist/components/alert/alert.js +6 -0
  12. package/dist/components/alert/index.d.ts +14 -0
  13. package/dist/components/alert/index.js +27 -0
  14. package/dist/components/avatar/avatar.astro +23 -0
  15. package/dist/components/avatar/avatar.css +35 -0
  16. package/dist/components/avatar/avatar.d.ts +5 -0
  17. package/dist/components/avatar/avatar.js +7 -0
  18. package/dist/components/avatar/index.d.ts +32 -0
  19. package/dist/components/avatar/index.js +24 -0
  20. package/dist/components/badge/badge.astro +11 -0
  21. package/dist/components/badge/badge.css +46 -0
  22. package/dist/components/badge/badge.d.ts +5 -0
  23. package/dist/components/badge/badge.js +6 -0
  24. package/dist/components/badge/index.d.ts +6 -0
  25. package/dist/components/badge/index.js +3 -0
  26. package/dist/components/breadcrumbs/breadcrumbs.astro +27 -0
  27. package/dist/components/breadcrumbs/breadcrumbs.css +33 -0
  28. package/dist/components/breadcrumbs/breadcrumbs.d.ts +9 -0
  29. package/dist/components/breadcrumbs/breadcrumbs.js +11 -0
  30. package/dist/components/breadcrumbs/index.d.ts +37 -0
  31. package/dist/components/breadcrumbs/index.js +16 -0
  32. package/dist/components/button/button.astro +36 -0
  33. package/dist/components/button/button.css +117 -0
  34. package/dist/components/button/button.d.ts +18 -0
  35. package/dist/components/button/button.js +23 -0
  36. package/dist/components/button/index.d.ts +59 -0
  37. package/dist/components/button/index.js +26 -0
  38. package/dist/components/card/card.astro +98 -0
  39. package/dist/components/card/card.css +91 -0
  40. package/dist/components/card/card.d.ts +19 -0
  41. package/dist/components/card/card.js +7 -0
  42. package/dist/components/card/index.d.ts +11 -0
  43. package/dist/components/card/index.js +7 -0
  44. package/dist/components/description-list/description-list.astro +39 -0
  45. package/dist/components/description-list/description-list.css +72 -0
  46. package/dist/components/description-list/description-list.d.ts +7 -0
  47. package/dist/components/description-list/description-list.js +6 -0
  48. package/dist/components/description-list/index.d.ts +12 -0
  49. package/dist/components/description-list/index.js +5 -0
  50. package/dist/components/divider/divider.astro +27 -0
  51. package/dist/components/divider/divider.css +40 -0
  52. package/dist/components/divider/divider.d.ts +5 -0
  53. package/dist/components/divider/divider.js +11 -0
  54. package/dist/components/divider/index.d.ts +22 -0
  55. package/dist/components/divider/index.js +11 -0
  56. package/dist/components/empty-state/empty-state.astro +47 -0
  57. package/dist/components/empty-state/empty-state.css +38 -0
  58. package/dist/components/empty-state/empty-state.d.ts +12 -0
  59. package/dist/components/empty-state/empty-state.js +7 -0
  60. package/dist/components/empty-state/index.d.ts +5 -0
  61. package/dist/components/empty-state/index.js +3 -0
  62. package/dist/components/field/checkbox-group.astro +58 -0
  63. package/dist/components/field/checkbox.astro +17 -0
  64. package/dist/components/field/field.astro +51 -0
  65. package/dist/components/field/field.css +336 -0
  66. package/dist/components/field/field.d.ts +47 -0
  67. package/dist/components/field/field.js +51 -0
  68. package/dist/components/field/index.d.ts +53 -0
  69. package/dist/components/field/index.js +54 -0
  70. package/dist/components/field/input.astro +27 -0
  71. package/dist/components/field/radio-group.astro +58 -0
  72. package/dist/components/field/radio.astro +17 -0
  73. package/dist/components/field/select.astro +13 -0
  74. package/dist/components/field/switch.astro +17 -0
  75. package/dist/components/field/textarea.astro +24 -0
  76. package/dist/components/filters/filter-layout.astro +72 -0
  77. package/dist/components/filters/filter-panel.astro +13 -0
  78. package/dist/components/filters/filters.css +230 -0
  79. package/dist/components/filters/filters.d.ts +20 -0
  80. package/dist/components/filters/filters.js +24 -0
  81. package/dist/components/filters/index.d.ts +27 -0
  82. package/dist/components/filters/index.js +25 -0
  83. package/dist/components/footer/footer.astro +70 -0
  84. package/dist/components/footer/footer.css +128 -0
  85. package/dist/components/footer/footer.d.ts +16 -0
  86. package/dist/components/footer/footer.js +7 -0
  87. package/dist/components/footer/index.d.ts +35 -0
  88. package/dist/components/footer/index.js +18 -0
  89. package/dist/components/header/header.astro +89 -0
  90. package/dist/components/header/header.css +163 -0
  91. package/dist/components/header/header.d.ts +18 -0
  92. package/dist/components/header/header.js +9 -0
  93. package/dist/components/header/index.d.ts +39 -0
  94. package/dist/components/header/index.js +25 -0
  95. package/dist/components/icon/icon.astro +21 -0
  96. package/dist/components/icon/icon.css +15 -0
  97. package/dist/components/icon/icon.d.ts +5 -0
  98. package/dist/components/icon/icon.js +6 -0
  99. package/dist/components/icon/index.d.ts +57 -0
  100. package/dist/components/icon/index.js +72 -0
  101. package/dist/components/layout/container.astro +15 -0
  102. package/dist/components/layout/grid.astro +14 -0
  103. package/dist/components/layout/index.d.ts +33 -0
  104. package/dist/components/layout/index.js +13 -0
  105. package/dist/components/layout/layout.css +262 -0
  106. package/dist/components/layout/layout.d.ts +24 -0
  107. package/dist/components/layout/layout.js +17 -0
  108. package/dist/components/layout/section-head.astro +42 -0
  109. package/dist/components/layout/section.astro +15 -0
  110. package/dist/components/page-head/index.d.ts +18 -0
  111. package/dist/components/page-head/index.js +14 -0
  112. package/dist/components/page-head/page-head.astro +60 -0
  113. package/dist/components/page-head/page-head.css +79 -0
  114. package/dist/components/page-head/page-head.d.ts +18 -0
  115. package/dist/components/page-head/page-head.js +8 -0
  116. package/dist/components/pagination/index.d.ts +73 -0
  117. package/dist/components/pagination/index.js +87 -0
  118. package/dist/components/pagination/pagination.astro +81 -0
  119. package/dist/components/pagination/pagination.css +70 -0
  120. package/dist/components/pagination/pagination.d.ts +8 -0
  121. package/dist/components/pagination/pagination.js +19 -0
  122. package/dist/components/panel/index.d.ts +11 -0
  123. package/dist/components/panel/index.js +3 -0
  124. package/dist/components/panel/panel.astro +15 -0
  125. package/dist/components/panel/panel.css +48 -0
  126. package/dist/components/panel/panel.d.ts +7 -0
  127. package/dist/components/panel/panel.js +6 -0
  128. package/dist/components/progress/index.d.ts +37 -0
  129. package/dist/components/progress/index.js +44 -0
  130. package/dist/components/progress/progress.astro +18 -0
  131. package/dist/components/progress/progress.css +115 -0
  132. package/dist/components/progress/progress.d.ts +5 -0
  133. package/dist/components/progress/progress.js +7 -0
  134. package/dist/components/prose/code-block.astro +26 -0
  135. package/dist/components/prose/index.d.ts +14 -0
  136. package/dist/components/prose/index.js +67 -0
  137. package/dist/components/prose/prose.astro +14 -0
  138. package/dist/components/prose/prose.css +156 -0
  139. package/dist/components/prose/prose.d.ts +12 -0
  140. package/dist/components/prose/prose.js +11 -0
  141. package/dist/components/stat/index.d.ts +15 -0
  142. package/dist/components/stat/index.js +5 -0
  143. package/dist/components/stat/stat-group.astro +11 -0
  144. package/dist/components/stat/stat.astro +43 -0
  145. package/dist/components/stat/stat.css +51 -0
  146. package/dist/components/stat/stat.d.ts +15 -0
  147. package/dist/components/stat/stat.js +10 -0
  148. package/dist/components/table/index.d.ts +38 -0
  149. package/dist/components/table/index.js +18 -0
  150. package/dist/components/table/table.astro +111 -0
  151. package/dist/components/table/table.css +78 -0
  152. package/dist/components/table/table.d.ts +11 -0
  153. package/dist/components/table/table.js +10 -0
  154. package/dist/components/tabs/index.d.ts +21 -0
  155. package/dist/components/tabs/index.js +13 -0
  156. package/dist/components/tabs/tabs.astro +30 -0
  157. package/dist/components/tabs/tabs.css +59 -0
  158. package/dist/components/tabs/tabs.d.ts +9 -0
  159. package/dist/components/tabs/tabs.js +6 -0
  160. package/dist/components/tag/index.d.ts +19 -0
  161. package/dist/components/tag/index.js +7 -0
  162. package/dist/components/tag/tag.astro +17 -0
  163. package/dist/components/tag/tag.css +30 -0
  164. package/dist/components/tag/tag.d.ts +9 -0
  165. package/dist/components/tag/tag.js +12 -0
  166. package/dist/components/timeline/index.d.ts +22 -0
  167. package/dist/components/timeline/index.js +5 -0
  168. package/dist/components/timeline/timeline.astro +40 -0
  169. package/dist/components/timeline/timeline.css +92 -0
  170. package/dist/components/timeline/timeline.d.ts +9 -0
  171. package/dist/components/timeline/timeline.js +7 -0
  172. package/dist/components/tooltip/index.d.ts +15 -0
  173. package/dist/components/tooltip/index.js +41 -0
  174. package/dist/components/tooltip/tooltip.astro +25 -0
  175. package/dist/components/tooltip/tooltip.css +84 -0
  176. package/dist/components/tooltip/tooltip.d.ts +12 -0
  177. package/dist/components/tooltip/tooltip.js +34 -0
  178. package/dist/config.d.ts +9 -0
  179. package/dist/config.js +6 -0
  180. package/dist/env.d.ts +2 -0
  181. package/dist/html.d.ts +37 -0
  182. package/dist/html.js +126 -0
  183. package/dist/parts.d.ts +27 -0
  184. package/dist/parts.js +28 -0
  185. package/dist/react.d.ts +27 -0
  186. package/dist/react.js +28 -0
  187. package/dist/scss/_chamfer.scss +37 -0
  188. package/dist/scss/_layers.scss +2 -0
  189. package/dist/scss/_theme.scss +15 -0
  190. package/dist/themes/eve-online.css +1945 -0
  191. package/dist/themes/xaroth.css +1974 -0
  192. package/dist/themes.css +3919 -0
  193. package/package.json +80 -0
@@ -0,0 +1,12 @@
1
+ export type DescriptionListLayout = 'stacked' | 'inline' | 'columns';
2
+ export type DescriptionListItem<T = string> = {
3
+ term: string;
4
+ value: T;
5
+ };
6
+ export type DescriptionListOptions = {
7
+ layout?: DescriptionListLayout;
8
+ dividers?: boolean;
9
+ className?: string;
10
+ };
11
+ export declare const descriptionListClass: ({ layout, dividers, className, }?: DescriptionListOptions) => string;
12
+ export declare const descriptionListValueSlot: (index: number) => string;
@@ -0,0 +1,5 @@
1
+ import { bem } from "../../bem.js";
2
+ const descriptionList = bem('x-description-list', { defaults: { layout: 'stacked' } });
3
+ export const descriptionListClass = ({ layout = 'stacked', dividers, className, } = {}) => descriptionList({ layout, dividers }, className);
4
+ // Astro: markup for one value goes in a named slot, overriding the item value.
5
+ export const descriptionListValueSlot = (index) => `value-${index}`;
@@ -0,0 +1,27 @@
1
+ ---
2
+ import './divider.css'
3
+ import type { HTMLAttributes } from 'astro/types'
4
+ import { dividerClass, dividerState, type DividerOptions } from './index.js'
5
+
6
+ type Props = Omit<HTMLAttributes<'div'>, 'class'> & Omit<DividerOptions, 'className'> & { class?: string }
7
+
8
+ const { variant, class: className, slot: _slot, ...rest } = Astro.props
9
+ const { tag: Tag, attrs: state } = dividerState({ variant })
10
+ const attrs = { ...rest, ...state }
11
+ ---
12
+
13
+ {
14
+ Tag === 'hr' ? (
15
+ <hr {...rest} class={dividerClass({ variant, className })} />
16
+ ) : (
17
+ <Tag {...attrs} class={dividerClass({ variant, className })}>
18
+ {variant === 'label' ? (
19
+ <span class="x-divider__label">
20
+ <slot />
21
+ </span>
22
+ ) : (
23
+ <span class="x-divider__mark" />
24
+ )}
25
+ </Tag>
26
+ )
27
+ }
@@ -0,0 +1,40 @@
1
+ @layer x.reset, x.core, x.theme, x.utility;
2
+ @layer x.core {
3
+ .x-divider {
4
+ --x-divider-line: var(--x-color-line);
5
+ width: 100%;
6
+ height: 1px;
7
+ margin-block: var(--x-divider-space, var(--x-space-6));
8
+ background: var(--x-divider-line);
9
+ border: 0;
10
+ }
11
+ .x-divider--ornament, .x-divider--label {
12
+ display: flex;
13
+ gap: var(--x-divider-gap, var(--x-space-3));
14
+ align-items: center;
15
+ justify-content: center;
16
+ height: auto;
17
+ background: none;
18
+ }
19
+ .x-divider--ornament::before, .x-divider--ornament::after, .x-divider--label::before, .x-divider--label::after {
20
+ content: "";
21
+ flex: 1 1 0;
22
+ height: 1px;
23
+ background: var(--x-divider-line);
24
+ }
25
+ .x-divider__mark {
26
+ flex: none;
27
+ }
28
+ .x-divider__label {
29
+ flex: none;
30
+ max-width: 70%;
31
+ font-family: var(--x-font-ui);
32
+ font-size: var(--x-fs-label);
33
+ font-weight: 600;
34
+ line-height: 1.3;
35
+ letter-spacing: var(--x-track-label);
36
+ text-align: center;
37
+ text-transform: uppercase;
38
+ color: var(--x-color-text-muted);
39
+ }
40
+ }
@@ -0,0 +1,5 @@
1
+ import './divider.scss';
2
+ import type { HTMLAttributes } from 'react';
3
+ import { type DividerOptions } from './index.ts';
4
+ export type DividerProps = Omit<DividerOptions, 'className'> & HTMLAttributes<HTMLElement>;
5
+ export declare function Divider({ variant, className, children, ...rest }: DividerProps): import("react").JSX.Element;
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import './divider.css';
3
+ import { dividerClass, dividerState } from "./index.js";
4
+ export function Divider({ variant, className, children, ...rest }) {
5
+ const { tag: Tag, attrs } = dividerState({ variant });
6
+ const classes = dividerClass({ variant, className });
7
+ if (Tag === 'hr') {
8
+ return (_jsx("hr", { ...rest, className: classes }));
9
+ }
10
+ return (_jsx(Tag, { ...rest, ...attrs, className: classes, children: variant === 'label' ? (_jsx("span", { className: "x-divider__label", children: children })) : (_jsx("span", { className: "x-divider__mark" })) }));
11
+ }
@@ -0,0 +1,22 @@
1
+ export type DividerVariant = 'plain' | 'ornament' | 'label';
2
+ export type DividerOptions = {
3
+ variant?: DividerVariant;
4
+ className?: string;
5
+ };
6
+ export declare const dividerClass: ({ variant, className }?: DividerOptions) => string;
7
+ export declare const dividerState: ({ variant }: Pick<DividerOptions, "variant">) => {
8
+ tag: "hr";
9
+ attrs: {
10
+ role?: undefined;
11
+ };
12
+ } | {
13
+ tag: "div";
14
+ attrs: {
15
+ role: "separator";
16
+ };
17
+ } | {
18
+ tag: "div";
19
+ attrs: {
20
+ role?: undefined;
21
+ };
22
+ };
@@ -0,0 +1,11 @@
1
+ import { bem } from "../../bem.js";
2
+ const divider = bem('x-divider', { defaults: { variant: 'plain' } });
3
+ export const dividerClass = ({ variant = 'plain', className } = {}) => divider({ variant }, className);
4
+ // A plain rule is an <hr>. The ornament needs a child, which <hr> cannot hold, so it is a div with the
5
+ // separator role. A label is readable text, and separator children are hidden from assistive tech, so the
6
+ // label variant is a plain div.
7
+ export const dividerState = ({ variant = 'plain' }) => variant === 'plain'
8
+ ? { tag: 'hr', attrs: {} }
9
+ : variant === 'ornament'
10
+ ? { tag: 'div', attrs: { role: 'separator' } }
11
+ : { tag: 'div', attrs: {} };
@@ -0,0 +1,47 @@
1
+ ---
2
+ import './empty-state.css'
3
+ import type { HTMLAttributes } from 'astro/types'
4
+ import { emptyStateClass, type EmptyStateHeadingLevel } from './index.js'
5
+
6
+ type Props = Omit<HTMLAttributes<'div'>, 'class' | 'title'> & {
7
+ class?: string
8
+ /** Plain-text title; the `title` slot takes markup. */
9
+ title?: string
10
+ headingLevel?: EmptyStateHeadingLevel
11
+ }
12
+
13
+ const { title, headingLevel = 3, class: className, slot: _slot, ...rest } = Astro.props
14
+ const H = `h${headingLevel}` as const
15
+ const hasTitle = title !== undefined || Astro.slots.has('title')
16
+ ---
17
+
18
+ <div {...rest} class={emptyStateClass({ className })}>
19
+ {
20
+ Astro.slots.has('icon') && (
21
+ <span class="x-empty-state__icon" aria-hidden="true">
22
+ <slot name="icon" />
23
+ </span>
24
+ )
25
+ }
26
+ {
27
+ hasTitle && (
28
+ <H class="x-empty-state__title">
29
+ <slot name="title">{title}</slot>
30
+ </H>
31
+ )
32
+ }
33
+ {
34
+ Astro.slots.has('default') && (
35
+ <div class="x-empty-state__text">
36
+ <slot />
37
+ </div>
38
+ )
39
+ }
40
+ {
41
+ Astro.slots.has('actions') && (
42
+ <div class="x-empty-state__actions">
43
+ <slot name="actions" />
44
+ </div>
45
+ )
46
+ }
47
+ </div>
@@ -0,0 +1,38 @@
1
+ @layer x.reset, x.core, x.theme, x.utility;
2
+ @layer x.core {
3
+ .x-empty-state {
4
+ display: grid;
5
+ gap: var(--x-space-3);
6
+ justify-items: center;
7
+ padding: var(--x-space-7) var(--x-space-5);
8
+ text-align: center;
9
+ }
10
+ .x-empty-state__icon {
11
+ display: inline-flex;
12
+ width: var(--x-empty-state-icon, 48px);
13
+ height: var(--x-empty-state-icon, 48px);
14
+ color: var(--x-color-field-edge);
15
+ }
16
+ .x-empty-state__icon svg {
17
+ width: 100%;
18
+ height: 100%;
19
+ }
20
+ .x-empty-state__title {
21
+ font-size: var(--x-fs-h3);
22
+ line-height: 1.3;
23
+ }
24
+ .x-empty-state__text {
25
+ max-width: var(--x-empty-state-measure, 36rem);
26
+ color: var(--x-color-text-muted);
27
+ }
28
+ .x-empty-state__text > * + * {
29
+ margin-top: var(--x-space-2);
30
+ }
31
+ .x-empty-state__actions {
32
+ display: flex;
33
+ flex-wrap: wrap;
34
+ gap: var(--x-space-2);
35
+ justify-content: center;
36
+ margin-top: var(--x-space-2);
37
+ }
38
+ }
@@ -0,0 +1,12 @@
1
+ import './empty-state.scss';
2
+ import type { HTMLAttributes, ReactNode } from 'react';
3
+ import { type EmptyStateHeadingLevel } from './index.ts';
4
+ export type EmptyStateProps = Omit<HTMLAttributes<HTMLDivElement>, 'title'> & {
5
+ /** Decorative line icon; hidden from screen readers. */
6
+ icon?: ReactNode;
7
+ title?: ReactNode;
8
+ headingLevel?: EmptyStateHeadingLevel;
9
+ /** Row under the text, usually one button that clears what caused the empty result. */
10
+ actions?: ReactNode;
11
+ };
12
+ export declare function EmptyState({ icon, title, headingLevel, actions, className, children, ...rest }: EmptyStateProps): import("react").JSX.Element;
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import './empty-state.css';
3
+ import { emptyStateClass } from "./index.js";
4
+ export function EmptyState({ icon, title, headingLevel = 3, actions, className, children, ...rest }) {
5
+ const H = `h${headingLevel}`;
6
+ return (_jsxs("div", { ...rest, className: emptyStateClass({ className }), children: [icon != null && (_jsx("span", { className: "x-empty-state__icon", "aria-hidden": "true", children: icon })), title != null && _jsx(H, { className: "x-empty-state__title", children: title }), children != null && _jsx("div", { className: "x-empty-state__text", children: children }), actions != null && _jsx("div", { className: "x-empty-state__actions", children: actions })] }));
7
+ }
@@ -0,0 +1,5 @@
1
+ export type EmptyStateHeadingLevel = 2 | 3 | 4 | 5 | 6;
2
+ export type EmptyStateOptions = {
3
+ className?: string;
4
+ };
5
+ export declare const emptyStateClass: ({ className }?: EmptyStateOptions) => string;
@@ -0,0 +1,3 @@
1
+ import { bem } from "../../bem.js";
2
+ const emptyState = bem('x-empty-state');
3
+ export const emptyStateClass = ({ className } = {}) => emptyState({}, className);
@@ -0,0 +1,58 @@
1
+ ---
2
+ import './field.css'
3
+ import type { HTMLAttributes } from 'astro/types'
4
+ import { defined } from '../../html.js'
5
+ import { choiceGroupAttrs, choiceGroupClass, fieldIds, type ChoiceGroupOrientation } from './index.js'
6
+
7
+ type Props = Omit<HTMLAttributes<'fieldset'>, 'class' | 'id' | 'role'> & {
8
+ /** Help and error text get `${id}-help` and `${id}-error`. */
9
+ id: string
10
+ legend?: string
11
+ description?: string
12
+ error?: string
13
+ required?: boolean
14
+ orientation?: ChoiceGroupOrientation
15
+ class?: string
16
+ }
17
+
18
+ const { id, legend, description, error, required, orientation, class: className, ...rest } = Astro.props
19
+ const hasLegend = Boolean(legend) || Astro.slots.has('legend')
20
+ const hasDescription = Boolean(description) || Astro.slots.has('description')
21
+ const hasError = Boolean(error) || Astro.slots.has('error')
22
+ const ids = fieldIds(id)
23
+ const recipe = choiceGroupAttrs({
24
+ id,
25
+ hasDescription,
26
+ hasError,
27
+ required,
28
+ kind: 'checkbox',
29
+ describedBy: rest['aria-describedby'] ?? undefined,
30
+ })
31
+ const attrs = { ...rest, ...defined(recipe), class: choiceGroupClass({ orientation, invalid: hasError, className }) }
32
+ ---
33
+
34
+ <fieldset {...attrs}>
35
+ {
36
+ hasLegend && (
37
+ <legend class="x-choice-group__legend">
38
+ {Astro.slots.has('legend') ? <slot name="legend" /> : legend}
39
+ {required && <span class="x-field__required" aria-hidden="true">*</span>}
40
+ </legend>
41
+ )
42
+ }
43
+ <div class="x-choice-group__options"><slot /></div>
44
+ {
45
+ hasDescription && (
46
+ <p class="x-field__help" id={ids.help}>
47
+ {Astro.slots.has('description') ? <slot name="description" /> : description}
48
+ </p>
49
+ )
50
+ }
51
+ {
52
+ hasError && (
53
+ <p class="x-field__error" id={ids.error}>
54
+ {Astro.slots.has('error') ? <slot name="error" /> : error}
55
+ </p>
56
+ )
57
+ }
58
+ </fieldset>
@@ -0,0 +1,17 @@
1
+ ---
2
+ import './field.css'
3
+ import type { HTMLAttributes } from 'astro/types'
4
+ import { choiceClass } from './index.js'
5
+
6
+ type Props = Omit<HTMLAttributes<'input'>, 'class' | 'type' | 'role'> & {
7
+ class?: string
8
+ }
9
+
10
+ const { class: className, ...rest } = Astro.props
11
+ const input = { ...rest, type: 'checkbox' as const, class: 'x-checkbox__input' }
12
+ ---
13
+
14
+ <label class={choiceClass('checkbox', { className })}>
15
+ <input {...input} />
16
+ <span class="x-checkbox__label"><slot /></span>
17
+ </label>
@@ -0,0 +1,51 @@
1
+ ---
2
+ import './field.css'
3
+ import type { HTMLAttributes } from 'astro/types'
4
+ import { fieldClass, fieldControlAttrs, fieldIds, wireControlHtml } from './index.js'
5
+
6
+ type Props = Omit<HTMLAttributes<'div'>, 'class' | 'id'> & {
7
+ /** Id of the control inside. Help and error text get `${id}-help` and `${id}-error`. */
8
+ id: string
9
+ label?: string
10
+ description?: string
11
+ error?: string
12
+ required?: boolean
13
+ class?: string
14
+ }
15
+
16
+ const { id, label, description, error, required, class: className, ...rest } = Astro.props
17
+ const hasLabel = Boolean(label) || Astro.slots.has('label')
18
+ const hasDescription = Boolean(description) || Astro.slots.has('description')
19
+ const hasError = Boolean(error) || Astro.slots.has('error')
20
+ const ids = fieldIds(id)
21
+ const control = wireControlHtml(
22
+ await Astro.slots.render('default'),
23
+ fieldControlAttrs({ id, hasDescription, hasError, required }),
24
+ )
25
+ ---
26
+
27
+ <div {...{ ...rest, class: fieldClass({ invalid: hasError, className }) }}>
28
+ {
29
+ hasLabel && (
30
+ <label class="x-field__label" for={id}>
31
+ {Astro.slots.has('label') ? <slot name="label" /> : label}
32
+ {required && <span class="x-field__required" aria-hidden="true">*</span>}
33
+ </label>
34
+ )
35
+ }
36
+ <Fragment set:html={control} />
37
+ {
38
+ hasDescription && (
39
+ <p class="x-field__help" id={ids.help}>
40
+ {Astro.slots.has('description') ? <slot name="description" /> : description}
41
+ </p>
42
+ )
43
+ }
44
+ {
45
+ hasError && (
46
+ <p class="x-field__error" id={ids.error}>
47
+ {Astro.slots.has('error') ? <slot name="error" /> : error}
48
+ </p>
49
+ )
50
+ }
51
+ </div>