@yarcl/react 0.1.0 → 0.2.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 (223) hide show
  1. package/README.md +14 -2
  2. package/{src/apply.ts → dist/apply.d.ts} +4 -23
  3. package/dist/apply.js +37 -0
  4. package/dist/classes.d.ts +13 -0
  5. package/dist/classes.js +22 -0
  6. package/dist/cli.d.ts +2 -0
  7. package/dist/cli.js +58 -0
  8. package/dist/color.js +49 -32
  9. package/dist/components/Accordion.d.ts +96 -0
  10. package/dist/components/Accordion.js +148 -0
  11. package/dist/components/Alert.d.ts +60 -0
  12. package/dist/components/Alert.js +61 -0
  13. package/dist/components/Avatar.d.ts +100 -0
  14. package/dist/components/Avatar.js +89 -0
  15. package/dist/components/Badge.d.ts +44 -0
  16. package/dist/components/Badge.js +43 -0
  17. package/dist/components/Breadcrumb.d.ts +77 -0
  18. package/dist/components/Breadcrumb.js +126 -0
  19. package/dist/components/Button.d.ts +18 -0
  20. package/dist/components/Button.js +33 -0
  21. package/dist/components/ButtonGroup.d.ts +29 -0
  22. package/dist/components/ButtonGroup.js +37 -0
  23. package/dist/components/Card.d.ts +36 -0
  24. package/dist/components/Card.js +26 -0
  25. package/dist/components/Checkbox.d.ts +28 -0
  26. package/dist/components/Checkbox.js +38 -0
  27. package/dist/components/Combobox.d.ts +75 -0
  28. package/dist/components/Combobox.js +362 -0
  29. package/dist/components/CommandPalette.d.ts +92 -0
  30. package/dist/components/CommandPalette.js +293 -0
  31. package/dist/components/DatePicker.d.ts +157 -0
  32. package/dist/components/DatePicker.js +230 -0
  33. package/dist/components/Dialog.d.ts +25 -0
  34. package/dist/components/Dialog.js +29 -0
  35. package/dist/components/Divider.d.ts +23 -0
  36. package/dist/components/Divider.js +25 -0
  37. package/dist/components/Drawer.d.ts +21 -0
  38. package/dist/components/Drawer.js +25 -0
  39. package/dist/components/EmptyState.d.ts +51 -0
  40. package/dist/components/EmptyState.js +47 -0
  41. package/dist/components/Field.d.ts +27 -0
  42. package/dist/components/Field.js +59 -0
  43. package/dist/components/Heading.d.ts +26 -0
  44. package/dist/components/Heading.js +25 -0
  45. package/dist/components/HoverCard.d.ts +47 -0
  46. package/dist/components/HoverCard.js +53 -0
  47. package/dist/components/IconButton.d.ts +19 -0
  48. package/dist/components/IconButton.js +32 -0
  49. package/dist/components/Inline.d.ts +21 -0
  50. package/dist/components/Inline.js +24 -0
  51. package/dist/components/Input.d.ts +19 -0
  52. package/dist/components/Input.js +25 -0
  53. package/dist/components/Label.d.ts +46 -0
  54. package/dist/components/Label.js +33 -0
  55. package/dist/components/Link.d.ts +27 -0
  56. package/dist/components/Link.js +26 -0
  57. package/dist/components/Menu.d.ts +73 -0
  58. package/dist/components/Menu.js +143 -0
  59. package/dist/components/Modal.d.ts +45 -0
  60. package/dist/components/Modal.js +110 -0
  61. package/dist/components/NumberInput.d.ts +49 -0
  62. package/dist/components/NumberInput.js +130 -0
  63. package/dist/components/Pagination.d.ts +86 -0
  64. package/dist/components/Pagination.js +119 -0
  65. package/dist/components/Popover.d.ts +72 -0
  66. package/dist/components/Popover.js +87 -0
  67. package/dist/components/Progress.d.ts +60 -0
  68. package/dist/components/Progress.js +59 -0
  69. package/dist/components/Radio.d.ts +32 -0
  70. package/dist/components/Radio.js +47 -0
  71. package/dist/components/RadioGroup.d.ts +57 -0
  72. package/dist/components/RadioGroup.js +68 -0
  73. package/dist/components/Select.d.ts +47 -0
  74. package/dist/components/Select.js +138 -0
  75. package/dist/components/Skeleton.d.ts +46 -0
  76. package/dist/components/Skeleton.js +40 -0
  77. package/dist/components/Slider.d.ts +126 -0
  78. package/dist/components/Slider.js +166 -0
  79. package/dist/components/Spinner.d.ts +23 -0
  80. package/dist/components/Spinner.js +23 -0
  81. package/dist/components/Stack.d.ts +35 -0
  82. package/dist/components/Stack.js +24 -0
  83. package/dist/components/Switch.d.ts +27 -0
  84. package/dist/components/Switch.js +33 -0
  85. package/dist/components/Table.d.ts +71 -0
  86. package/dist/components/Table.js +61 -0
  87. package/dist/components/Tabs.d.ts +66 -0
  88. package/dist/components/Tabs.js +109 -0
  89. package/dist/components/Text.d.ts +32 -0
  90. package/dist/components/Text.js +28 -0
  91. package/dist/components/Textarea.d.ts +15 -0
  92. package/dist/components/Textarea.js +24 -0
  93. package/dist/components/Toast.d.ts +90 -0
  94. package/dist/components/Toast.js +156 -0
  95. package/dist/components/ToggleGroup.d.ts +79 -0
  96. package/dist/components/ToggleGroup.js +101 -0
  97. package/dist/components/Tooltip.d.ts +46 -0
  98. package/dist/components/Tooltip.js +62 -0
  99. package/dist/components/VisuallyHidden.d.ts +18 -0
  100. package/dist/components/VisuallyHidden.js +22 -0
  101. package/dist/contrast.d.ts +32 -0
  102. package/dist/css.d.ts +2 -2
  103. package/dist/css.js +193 -157
  104. package/dist/define.d.ts +40 -15
  105. package/dist/define.js +30 -27
  106. package/dist/demo.d.ts +2 -0
  107. package/dist/demo.js +2 -0
  108. package/dist/esbuild.cjs +5 -0
  109. package/dist/esbuild.d.ts +4 -0
  110. package/dist/esbuild.js +6 -0
  111. package/dist/field-context.d.ts +16 -0
  112. package/dist/field-context.js +17 -0
  113. package/dist/floating.d.ts +12 -0
  114. package/dist/floating.js +52 -0
  115. package/dist/hooks.d.ts +1 -0
  116. package/dist/hooks.js +12 -0
  117. package/{src/index.ts → dist/index.d.ts} +11 -33
  118. package/dist/index.js +50 -0
  119. package/dist/init.d.ts +18 -0
  120. package/dist/init.js +224 -0
  121. package/dist/plugin.d.ts +10 -26
  122. package/dist/plugin.js +152 -78
  123. package/dist/reference/DemoYarcl.d.ts +12 -0
  124. package/dist/reference/DemoYarcl.js +312 -0
  125. package/dist/reference/DesignReference.d.ts +24 -0
  126. package/dist/reference/DesignReference.js +403 -0
  127. package/dist/reference/index.js +2 -0
  128. package/dist/rollup.cjs +5 -0
  129. package/dist/rollup.d.ts +4 -0
  130. package/dist/rollup.js +6 -0
  131. package/dist/rspack.cjs +5 -0
  132. package/dist/rspack.d.ts +4 -0
  133. package/dist/rspack.js +6 -0
  134. package/dist/runtime.d.ts +13 -0
  135. package/dist/runtime.js +30 -0
  136. package/dist/setup.d.ts +6 -0
  137. package/dist/setup.js +33 -0
  138. package/{src → dist}/styles.css +224 -106
  139. package/dist/themes/bloom.d.ts +295 -0
  140. package/dist/themes/bloom.js +202 -0
  141. package/dist/themes/brutalist.d.ts +277 -0
  142. package/dist/themes/brutalist.js +199 -0
  143. package/dist/themes/compact.d.ts +274 -0
  144. package/dist/themes/compact.js +200 -0
  145. package/dist/themes/contract.d.ts +23 -0
  146. package/dist/themes/editorial.d.ts +277 -0
  147. package/dist/themes/editorial.js +183 -0
  148. package/dist/themes/index.d.ts +1425 -0
  149. package/dist/themes/index.js +45 -0
  150. package/{src/types.ts → dist/types.d.ts} +40 -37
  151. package/dist/vite.cjs +5 -0
  152. package/dist/vite.d.ts +4 -0
  153. package/dist/vite.js +6 -0
  154. package/dist/webpack.cjs +5 -0
  155. package/dist/webpack.d.ts +4 -0
  156. package/dist/webpack.js +6 -0
  157. package/dist/yarcl.config.d.ts +276 -0
  158. package/dist/yarcl.config.js +273 -0
  159. package/package.json +69 -17
  160. package/src/classes.ts +0 -23
  161. package/src/color.ts +0 -48
  162. package/src/components/Accordion.tsx +0 -274
  163. package/src/components/Alert.tsx +0 -85
  164. package/src/components/Badge.tsx +0 -79
  165. package/src/components/Breadcrumb.tsx +0 -239
  166. package/src/components/Button.tsx +0 -58
  167. package/src/components/ButtonGroup.tsx +0 -61
  168. package/src/components/Card.tsx +0 -50
  169. package/src/components/Checkbox.tsx +0 -49
  170. package/src/components/Combobox.tsx +0 -522
  171. package/src/components/CommandPalette.tsx +0 -452
  172. package/src/components/DatePicker.tsx +0 -432
  173. package/src/components/Dialog.tsx +0 -39
  174. package/src/components/Divider.tsx +0 -34
  175. package/src/components/Drawer.tsx +0 -31
  176. package/src/components/Field.tsx +0 -61
  177. package/src/components/Heading.tsx +0 -40
  178. package/src/components/HoverCard.tsx +0 -108
  179. package/src/components/IconButton.tsx +0 -59
  180. package/src/components/Inline.tsx +0 -42
  181. package/src/components/Input.tsx +0 -28
  182. package/src/components/Label.tsx +0 -58
  183. package/src/components/Link.tsx +0 -41
  184. package/src/components/Menu.tsx +0 -207
  185. package/src/components/Modal.tsx +0 -164
  186. package/src/components/NumberInput.tsx +0 -208
  187. package/src/components/Pagination.tsx +0 -227
  188. package/src/components/Popover.tsx +0 -140
  189. package/src/components/Progress.tsx +0 -122
  190. package/src/components/Radio.tsx +0 -59
  191. package/src/components/RadioGroup.tsx +0 -114
  192. package/src/components/Select.tsx +0 -197
  193. package/src/components/Skeleton.tsx +0 -95
  194. package/src/components/Slider.tsx +0 -315
  195. package/src/components/Spinner.tsx +0 -38
  196. package/src/components/Stack.tsx +0 -57
  197. package/src/components/Switch.tsx +0 -42
  198. package/src/components/Table.tsx +0 -99
  199. package/src/components/Tabs.tsx +0 -159
  200. package/src/components/Text.tsx +0 -67
  201. package/src/components/Textarea.tsx +0 -26
  202. package/src/components/Toast.tsx +0 -190
  203. package/src/components/ToggleGroup.tsx +0 -227
  204. package/src/components/Tooltip.tsx +0 -78
  205. package/src/contrast.ts +0 -82
  206. package/src/css.ts +0 -228
  207. package/src/define.check.ts +0 -259
  208. package/src/define.ts +0 -379
  209. package/src/field-context.ts +0 -31
  210. package/src/floating.tsx +0 -61
  211. package/src/hooks.ts +0 -19
  212. package/src/plugin.ts +0 -94
  213. package/src/reference/DesignReference.tsx +0 -374
  214. package/src/runtime.ts +0 -38
  215. package/src/themes/bloom.ts +0 -72
  216. package/src/themes/brutalist.ts +0 -63
  217. package/src/themes/compact.ts +0 -63
  218. package/src/themes/contract.ts +0 -24
  219. package/src/themes/editorial.ts +0 -55
  220. package/src/themes/index.ts +0 -47
  221. package/src/yarcl.config.ts +0 -104
  222. /package/{src/reference/index.ts → dist/reference/index.d.ts} +0 -0
  223. /package/{src → dist}/reference/reference.css +0 -0
@@ -0,0 +1,47 @@
1
+ import { useDefaults } from "../runtime.js";
2
+ import { colorClass, cx, sizeClass } from "../classes.js";
3
+ import { useRadioGroup } from "./RadioGroup.js";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ //#region src/components/Radio.tsx
6
+ /**
7
+ * A radio button with an optional label. Place inside a {@link RadioGroup}, or group standalone
8
+ * radios with the same `name`.
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * <RadioGroup label="Plan" defaultValue="pro">
13
+ * <Radio value="free">Free</Radio>
14
+ * <Radio value="pro">Pro</Radio>
15
+ * </RadioGroup>
16
+ * ```
17
+ */
18
+ function Radio({ children, size, color, value, className, style, onChange, ...props }) {
19
+ const own = useDefaults("Radio");
20
+ const group = useRadioGroup();
21
+ const groupProps = group && {
22
+ name: group.name,
23
+ checked: value !== void 0 && group.value === value,
24
+ "aria-invalid": group.invalid || void 0,
25
+ onChange: (event) => {
26
+ onChange?.(event);
27
+ if (event.target.checked && value !== void 0) group.select(value);
28
+ }
29
+ };
30
+ return /* @__PURE__ */ jsxs("label", {
31
+ className: cx("yarcl-radio", sizeClass(size ?? group?.size ?? own.size, "Radio"), colorClass(color ?? group?.color ?? own.color), className),
32
+ style,
33
+ children: [/* @__PURE__ */ jsx("input", {
34
+ type: "radio",
35
+ className: "yarcl-radio-input",
36
+ value,
37
+ onChange,
38
+ ...props,
39
+ ...groupProps
40
+ }), children != null && /* @__PURE__ */ jsx("span", {
41
+ className: "yarcl-radio-label",
42
+ children
43
+ })]
44
+ });
45
+ }
46
+ //#endregion
47
+ export { Radio };
@@ -0,0 +1,57 @@
1
+ import { type ComponentProps, type ReactNode } from 'react';
2
+ import type { Color, ComponentSize, Size } from '../types';
3
+ interface RadioGroupContextValue {
4
+ name: string;
5
+ value: string | null;
6
+ select: (value: string) => void;
7
+ size?: Size;
8
+ color?: Color;
9
+ invalid: boolean;
10
+ disabled?: boolean;
11
+ }
12
+ export declare function useRadioGroup(): RadioGroupContextValue | null;
13
+ /** Props for {@link RadioGroup}. */
14
+ export interface RadioGroupProps extends Omit<ComponentProps<'fieldset'>, 'defaultValue' | 'onChange' | 'color'> {
15
+ /** Visible group label, rendered as the `<legend>`. */
16
+ label: ReactNode;
17
+ /** Helper text shown below the options. */
18
+ description?: ReactNode;
19
+ /** Error message. Marks the options invalid and styles them with `defaults.errorColor`. */
20
+ error?: ReactNode;
21
+ /** Form field name shared by the radios. Generated when omitted. */
22
+ name?: string;
23
+ /** Controlled selected value. */
24
+ value?: string | null;
25
+ /**
26
+ * Initially selected value when uncontrolled.
27
+ * @default null
28
+ */
29
+ defaultValue?: string | null;
30
+ /** Called with the selected radio's `value`. */
31
+ onValueChange?: (value: string) => void;
32
+ /** Size of every radio, from the `sizes` config. */
33
+ size?: ComponentSize<'Radio'>;
34
+ /** Color of every radio, from the `colors` config. */
35
+ color?: Color;
36
+ /**
37
+ * Lays the radios out in a row or a column.
38
+ * @default 'vertical'
39
+ */
40
+ orientation?: 'horizontal' | 'vertical';
41
+ /** {@link Radio}s, each with a `value`. */
42
+ children: ReactNode;
43
+ }
44
+ /**
45
+ * A labelled group of {@link Radio}s. Renders a `<fieldset>` and `<legend>`, shares one `name`,
46
+ * and tracks the selected value. Radios inside don't need `name` or `checked`.
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * <RadioGroup label="Plan" defaultValue="pro" orientation="horizontal">
51
+ * <Radio value="free">Free</Radio>
52
+ * <Radio value="pro">Pro</Radio>
53
+ * </RadioGroup>
54
+ * ```
55
+ */
56
+ export declare function RadioGroup({ label, description, error, name, value: valueProp, defaultValue, onValueChange, size, color, orientation, disabled, className, children, ...props }: RadioGroupProps): import("react").JSX.Element;
57
+ export {};
@@ -0,0 +1,68 @@
1
+ import { useConfig } from "../runtime.js";
2
+ import { cx, typeClass } from "../classes.js";
3
+ import { useControllable } from "../hooks.js";
4
+ import { createContext, useContext, useId } from "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ //#region src/components/RadioGroup.tsx
7
+ var RadioGroupContext = createContext(null);
8
+ function useRadioGroup() {
9
+ return useContext(RadioGroupContext);
10
+ }
11
+ /**
12
+ * A labelled group of {@link Radio}s. Renders a `<fieldset>` and `<legend>`, shares one `name`,
13
+ * and tracks the selected value. Radios inside don't need `name` or `checked`.
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * <RadioGroup label="Plan" defaultValue="pro" orientation="horizontal">
18
+ * <Radio value="free">Free</Radio>
19
+ * <Radio value="pro">Pro</Radio>
20
+ * </RadioGroup>
21
+ * ```
22
+ */
23
+ function RadioGroup({ label, description, error, name, value: valueProp, defaultValue = null, onValueChange, size, color, orientation = "vertical", disabled, className, children, ...props }) {
24
+ const config = useConfig();
25
+ const id = useId();
26
+ const [value, setValue] = useControllable(valueProp, defaultValue, (v) => v != null && onValueChange?.(v));
27
+ const descriptionId = description != null ? `${id}-description` : void 0;
28
+ const errorId = error != null && error !== false ? `${id}-error` : void 0;
29
+ return /* @__PURE__ */ jsx(RadioGroupContext.Provider, {
30
+ value: {
31
+ name: name ?? id,
32
+ value,
33
+ select: setValue,
34
+ size,
35
+ color,
36
+ invalid: errorId != null,
37
+ disabled
38
+ },
39
+ children: /* @__PURE__ */ jsxs("fieldset", {
40
+ className: cx("yarcl-field yarcl-radio-group", className),
41
+ "aria-describedby": cx(descriptionId, errorId) || void 0,
42
+ disabled,
43
+ ...props,
44
+ children: [
45
+ /* @__PURE__ */ jsx("legend", {
46
+ className: cx("yarcl-field-label", typeClass(config.defaults.labelStyle)),
47
+ children: label
48
+ }),
49
+ /* @__PURE__ */ jsx("div", {
50
+ className: cx("yarcl-radio-group-options", `yarcl-radio-group-${orientation}`),
51
+ children
52
+ }),
53
+ descriptionId && /* @__PURE__ */ jsx("p", {
54
+ className: cx("yarcl-field-description", typeClass(config.defaults.helperStyle)),
55
+ id: descriptionId,
56
+ children: description
57
+ }),
58
+ errorId && /* @__PURE__ */ jsx("p", {
59
+ className: cx("yarcl-field-error", typeClass(config.defaults.helperStyle)),
60
+ id: errorId,
61
+ children: error
62
+ })
63
+ ]
64
+ })
65
+ });
66
+ }
67
+ //#endregion
68
+ export { RadioGroup, useRadioGroup };
@@ -0,0 +1,47 @@
1
+ import { type ComponentProps, type ReactNode } from 'react';
2
+ import type { TokenProps } from '../types';
3
+ /** An option of a {@link Select} or {@link Combobox}. */
4
+ export interface SelectOption<V extends string = string> {
5
+ /** Value reported by `onValueChange` and submitted with forms. */
6
+ value: V;
7
+ /** Text shown to the user. Also used for type-to-select and filtering. */
8
+ label: string;
9
+ /** Prevents choosing this option. */
10
+ disabled?: boolean;
11
+ }
12
+ /** Props for {@link Select}. */
13
+ export interface SelectProps<V extends string = string> extends TokenProps<'Select'>, Omit<ComponentProps<'button'>, 'color' | 'value' | 'defaultValue' | 'onChange' | 'children'> {
14
+ /** The options to choose from. */
15
+ options: readonly SelectOption<V>[];
16
+ /** Controlled value. `null` means nothing is selected. */
17
+ value?: V | null;
18
+ /**
19
+ * Initial value when uncontrolled.
20
+ * @default null
21
+ */
22
+ defaultValue?: V | null;
23
+ /** Called with the chosen option's value. */
24
+ onValueChange?: (value: V | null) => void;
25
+ /** Text shown when nothing is selected. */
26
+ placeholder?: ReactNode;
27
+ /** Form field name. Renders a hidden input with the value. */
28
+ name?: string;
29
+ }
30
+ /**
31
+ * Picks one value from a list, like a native `<select>` but styled from the design tokens.
32
+ * Arrow keys and type-to-select work both open and closed.
33
+ * Shares the size scale with {@link Input} and {@link Button}. Works inside a {@link Field}.
34
+ *
35
+ * @example
36
+ * ```tsx
37
+ * <Select
38
+ * placeholder="Choose a plan"
39
+ * options={[
40
+ * { value: 'free', label: 'Free' },
41
+ * { value: 'pro', label: 'Pro' },
42
+ * ]}
43
+ * onValueChange={setPlan}
44
+ * />
45
+ * ```
46
+ */
47
+ export declare function Select<V extends string = string>(props: SelectProps<V>): import("react").JSX.Element;
@@ -0,0 +1,138 @@
1
+ import { useDefaults } from "../runtime.js";
2
+ import { colorClass, cx, radiusClass, sizeClass } from "../classes.js";
3
+ import { useControllable } from "../hooks.js";
4
+ import { useFieldProps } from "../field-context.js";
5
+ import { CheckIcon, ChevronIcon, floatingMiddleware } from "../floating.js";
6
+ import { useRef, useState } from "react";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
+ import { FloatingFocusManager, FloatingPortal, autoUpdate, useClick, useDismiss, useFloating, useInteractions, useListNavigation, useMergeRefs, useRole, useTypeahead } from "@floating-ui/react";
9
+ //#region src/components/Select.tsx
10
+ /**
11
+ * Picks one value from a list, like a native `<select>` but styled from the design tokens.
12
+ * Arrow keys and type-to-select work both open and closed.
13
+ * Shares the size scale with {@link Input} and {@link Button}. Works inside a {@link Field}.
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * <Select
18
+ * placeholder="Choose a plan"
19
+ * options={[
20
+ * { value: 'free', label: 'Free' },
21
+ * { value: 'pro', label: 'Pro' },
22
+ * ]}
23
+ * onValueChange={setPlan}
24
+ * />
25
+ * ```
26
+ */
27
+ function Select(props) {
28
+ const own = useDefaults("Select");
29
+ const { options, value: valueProp, defaultValue = null, onValueChange, placeholder, name, size, radius, color, className, disabled, ...rest } = useFieldProps(props);
30
+ const [value, setValue] = useControllable(valueProp, defaultValue, onValueChange);
31
+ const [open, setOpen] = useState(false);
32
+ const [activeIndex, setActiveIndex] = useState(null);
33
+ const listRef = useRef([]);
34
+ const labelsRef = useRef([]);
35
+ const typingRef = useRef(false);
36
+ labelsRef.current = options.map((option) => option.disabled ? null : option.label);
37
+ const selectedIndex = options.findIndex((option) => option.value === value);
38
+ const selected = selectedIndex >= 0 ? options[selectedIndex] : void 0;
39
+ const disabledIndices = options.flatMap((option, i) => option.disabled ? [i] : []);
40
+ function choose(index) {
41
+ const option = options[index];
42
+ if (!option || option.disabled) return;
43
+ setValue(option.value);
44
+ setOpen(false);
45
+ }
46
+ const { refs, floatingStyles, context } = useFloating({
47
+ open,
48
+ onOpenChange: setOpen,
49
+ placement: "bottom-start",
50
+ transform: false,
51
+ whileElementsMounted: autoUpdate,
52
+ middleware: floatingMiddleware({
53
+ gap: 4,
54
+ matchWidth: true
55
+ })
56
+ });
57
+ const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions([
58
+ useClick(context, { enabled: !disabled }),
59
+ useDismiss(context),
60
+ useRole(context, { role: "select" }),
61
+ useListNavigation(context, {
62
+ listRef,
63
+ activeIndex,
64
+ selectedIndex: selectedIndex >= 0 ? selectedIndex : null,
65
+ onNavigate: setActiveIndex,
66
+ disabledIndices,
67
+ loop: true
68
+ }),
69
+ useTypeahead(context, {
70
+ listRef: labelsRef,
71
+ activeIndex,
72
+ selectedIndex: selectedIndex >= 0 ? selectedIndex : null,
73
+ onMatch: open ? setActiveIndex : choose,
74
+ onTypingChange: (typing) => {
75
+ typingRef.current = typing;
76
+ }
77
+ })
78
+ ]);
79
+ const buttonRef = useMergeRefs([refs.setReference, rest.ref]);
80
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
81
+ /* @__PURE__ */ jsxs("button", {
82
+ ref: buttonRef,
83
+ type: "button",
84
+ disabled,
85
+ className: cx("yarcl-input yarcl-select", sizeClass(size ?? own.size, "Select"), radiusClass(radius ?? own.radius, size ?? own.size), colorClass(color ?? own.color), className),
86
+ ...getReferenceProps(rest),
87
+ children: [/* @__PURE__ */ jsx("span", {
88
+ className: cx("yarcl-select-value", !selected && "yarcl-select-placeholder"),
89
+ children: selected ? selected.label : placeholder
90
+ }), /* @__PURE__ */ jsx(ChevronIcon, {})]
91
+ }),
92
+ name && /* @__PURE__ */ jsx("input", {
93
+ type: "hidden",
94
+ name,
95
+ value: value ?? ""
96
+ }),
97
+ open && /* @__PURE__ */ jsx(FloatingPortal, { children: /* @__PURE__ */ jsx(FloatingFocusManager, {
98
+ context,
99
+ modal: false,
100
+ children: /* @__PURE__ */ jsx("div", {
101
+ ref: refs.setFloating,
102
+ style: floatingStyles,
103
+ className: cx("yarcl-floating yarcl-panel yarcl-listbox", sizeClass(size ?? own.size, "Select"), colorClass(color ?? own.color)),
104
+ ...getFloatingProps(),
105
+ children: options.map((option, i) => {
106
+ const isSelected = i === selectedIndex;
107
+ const isActive = i === activeIndex;
108
+ return /* @__PURE__ */ jsxs("div", {
109
+ ref: (node) => {
110
+ listRef.current[i] = node;
111
+ },
112
+ tabIndex: isActive ? 0 : -1,
113
+ "aria-disabled": option.disabled || void 0,
114
+ "data-active": isActive || void 0,
115
+ className: "yarcl-option",
116
+ ...getItemProps({
117
+ active: isActive,
118
+ selected: isSelected,
119
+ onClick: () => choose(i),
120
+ onKeyDown(event) {
121
+ if (event.key === "Enter" || event.key === " " && !typingRef.current) {
122
+ event.preventDefault();
123
+ choose(i);
124
+ }
125
+ }
126
+ }),
127
+ children: [/* @__PURE__ */ jsx("span", {
128
+ className: "yarcl-option-label",
129
+ children: option.label
130
+ }), isSelected && /* @__PURE__ */ jsx(CheckIcon, {})]
131
+ }, option.value);
132
+ })
133
+ })
134
+ }) })
135
+ ] });
136
+ }
137
+ //#endregion
138
+ export { Select };
@@ -0,0 +1,46 @@
1
+ import type { ComponentProps } from 'react';
2
+ import type { ComponentSize, Radius, TextStyle } from '../types';
3
+ /** Props for {@link Skeleton}. */
4
+ export interface SkeletonProps extends Omit<ComponentProps<'span'>, 'children'> {
5
+ /**
6
+ * `text`: lines matching a text style; `control`: the height of a control of the given `size`;
7
+ * `circle`: a circle, e.g. for an avatar; `rect`: a block sized by `width` and `height`.
8
+ * @default 'text'
9
+ */
10
+ shape?: 'text' | 'control' | 'circle' | 'rect';
11
+ /** Number of lines for `shape="text"`. The last line is shorter. */
12
+ lines?: number;
13
+ /**
14
+ * Text style whose font size and line height the lines match, for `shape="text"`.
15
+ * @default config.defaults.textStyle
16
+ */
17
+ textStyle?: TextStyle;
18
+ /**
19
+ * Control size, from the `sizes` config. Sets the height for `shape="control"` and the diameter for `shape="circle"`.
20
+ * @default config.defaults.size
21
+ */
22
+ size?: ComponentSize<'Skeleton'>;
23
+ /**
24
+ * Corner radius for `control` and `rect`, from the `radii` config.
25
+ * @default config.defaults.radius
26
+ */
27
+ radius?: Radius | 'size';
28
+ /** Width as a CSS length. */
29
+ width?: string;
30
+ /** Height as a CSS length, for `shape="rect"`. */
31
+ height?: string;
32
+ }
33
+ /**
34
+ * A placeholder shown while content loads. Hidden from assistive technology;
35
+ * mark the loading region with `aria-busy` instead.
36
+ *
37
+ * @example
38
+ * ```tsx
39
+ * <Stack aria-busy>
40
+ * <Skeleton shape="text" textStyle="title" width="40%" />
41
+ * <Skeleton shape="text" lines={3} />
42
+ * <Skeleton shape="control" width="12rem" />
43
+ * </Stack>
44
+ * ```
45
+ */
46
+ export declare function Skeleton({ shape, lines, textStyle, size, radius, width, height, className, style, ...props }: SkeletonProps): import("react").JSX.Element;
@@ -0,0 +1,40 @@
1
+ import { useDefaults } from "../runtime.js";
2
+ import { cx, radiusClass, sizeClass, typeClass } from "../classes.js";
3
+ import { jsx } from "react/jsx-runtime";
4
+ //#region src/components/Skeleton.tsx
5
+ /**
6
+ * A placeholder shown while content loads. Hidden from assistive technology;
7
+ * mark the loading region with `aria-busy` instead.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * <Stack aria-busy>
12
+ * <Skeleton shape="text" textStyle="title" width="40%" />
13
+ * <Skeleton shape="text" lines={3} />
14
+ * <Skeleton shape="control" width="12rem" />
15
+ * </Stack>
16
+ * ```
17
+ */
18
+ function Skeleton({ shape = "text", lines = 1, textStyle, size, radius, width, height, className, style, ...props }) {
19
+ const own = useDefaults("Skeleton");
20
+ const dimensions = {
21
+ width,
22
+ height,
23
+ ...style
24
+ };
25
+ if (shape === "text") return /* @__PURE__ */ jsx("span", {
26
+ "aria-hidden": "true",
27
+ className: cx("yarcl-skeleton-text", textStyle && typeClass(textStyle), className),
28
+ style: dimensions,
29
+ ...props,
30
+ children: Array.from({ length: lines }, (_, i) => /* @__PURE__ */ jsx("span", { className: "yarcl-skeleton yarcl-skeleton-line" }, i))
31
+ });
32
+ return /* @__PURE__ */ jsx("span", {
33
+ "aria-hidden": "true",
34
+ className: cx("yarcl-skeleton", `yarcl-skeleton-${shape}`, shape !== "rect" && sizeClass(size ?? own.size, "Skeleton"), shape !== "circle" && radiusClass(radius ?? own.radius, size ?? own.size), className),
35
+ style: dimensions,
36
+ ...props
37
+ });
38
+ }
39
+ //#endregion
40
+ export { Skeleton };
@@ -0,0 +1,126 @@
1
+ import { type ComponentProps } from 'react';
2
+ import type { TokenProps } from '../types';
3
+ /** A {@link Slider} value: one number, or a `[start, end]` pair for a range. */
4
+ export type SliderValue = number | [number, number];
5
+ /** Props for {@link Slider}. Accepts all native `<div>` attributes except `color`, `defaultValue`, `onChange` and `children`. */
6
+ export interface SliderProps<V extends SliderValue = number> extends TokenProps<'Slider'>, Omit<ComponentProps<'div'>, 'color' | 'defaultValue' | 'onChange' | 'children'> {
7
+ /**
8
+ * Controlled value. Pass a `[start, end]` pair for a range with two thumbs.
9
+ * @example
10
+ * ```tsx
11
+ * <Slider value={volume} onValueChange={setVolume} aria-label="Volume" />
12
+ * ```
13
+ */
14
+ value?: V;
15
+ /**
16
+ * Initial value when uncontrolled. Pass a `[start, end]` pair for a range with two thumbs.
17
+ * @default min
18
+ * @example
19
+ * ```tsx
20
+ * <Slider defaultValue={[20, 80]} aria-label="Price" />
21
+ * ```
22
+ */
23
+ defaultValue?: V;
24
+ /**
25
+ * Called with the new value while the user drags or presses a key.
26
+ * @example
27
+ * ```tsx
28
+ * <Slider onValueChange={(value) => setVolume(value)} aria-label="Volume" />
29
+ * ```
30
+ */
31
+ onValueChange?: (value: V) => void;
32
+ /**
33
+ * Lowest value.
34
+ * @default 0
35
+ * @example
36
+ * ```tsx
37
+ * <Slider min={-10} max={10} aria-label="Offset" />
38
+ * ```
39
+ */
40
+ min?: number;
41
+ /**
42
+ * Highest value.
43
+ * @default 100
44
+ * @example
45
+ * ```tsx
46
+ * <Slider max={10} aria-label="Rating" />
47
+ * ```
48
+ */
49
+ max?: number;
50
+ /**
51
+ * Interval between values. Values snap to multiples of it, counted from `min`.
52
+ * @default 1
53
+ * @example
54
+ * ```tsx
55
+ * <Slider step={5} aria-label="Opacity" />
56
+ * ```
57
+ */
58
+ step?: number;
59
+ /**
60
+ * Jump for PageUp and PageDown.
61
+ * @default a tenth of the range, rounded to a whole number of steps
62
+ * @example
63
+ * ```tsx
64
+ * <Slider step={1} largeStep={25} aria-label="Progress" />
65
+ * ```
66
+ */
67
+ largeStep?: number;
68
+ /**
69
+ * Prevents interaction and dims the slider.
70
+ * @default false
71
+ * @example
72
+ * ```tsx
73
+ * <Slider disabled defaultValue={40} aria-label="Volume" />
74
+ * ```
75
+ */
76
+ disabled?: boolean;
77
+ /**
78
+ * Form field name. Renders a hidden input per thumb with its value.
79
+ * @example
80
+ * ```tsx
81
+ * <Slider name="volume" aria-label="Volume" />
82
+ * ```
83
+ */
84
+ name?: string;
85
+ /**
86
+ * Formats a value for screen readers (`aria-valuetext`).
87
+ * @example
88
+ * ```tsx
89
+ * <Slider formatValue={(value) => `${value} percent`} aria-label="Volume" />
90
+ * ```
91
+ */
92
+ formatValue?: (value: number) => string;
93
+ /**
94
+ * Names of the two thumbs of a range, added to the slider's label.
95
+ * @default ['Minimum', 'Maximum']
96
+ * @example
97
+ * ```tsx
98
+ * <Slider defaultValue={[9, 17]} thumbLabels={['Opens', 'Closes']} aria-label="Hours" />
99
+ * ```
100
+ */
101
+ thumbLabels?: readonly [string, string];
102
+ }
103
+ /** Props for `Slider.Range`. */
104
+ export type SliderRangeProps = SliderProps<[number, number]>;
105
+ /**
106
+ * Picks a number, or a range with two thumbs, by dragging along a track.
107
+ * Each thumb has `role="slider"` and supports the arrow keys, Home, End, PageUp and PageDown.
108
+ * Shares the size scale with the other controls. Works inside a {@link Field}; outside one, give it an `aria-label`.
109
+ *
110
+ * @example
111
+ * ```tsx
112
+ * <Field label="Volume">
113
+ * <Slider defaultValue={40} />
114
+ * </Field>
115
+ * ```
116
+ */
117
+ declare function SliderRoot<V extends SliderValue = number>(props: SliderProps<V>): import("react").JSX.Element;
118
+ declare function SliderRange(props: SliderRangeProps): import("react").JSX.Element;
119
+ /**
120
+ * Picks a number, or a range with two thumbs, by dragging along a track.
121
+ * Use `Slider.Range` for an explicitly range-only API.
122
+ */
123
+ export declare const Slider: typeof SliderRoot & {
124
+ Range: typeof SliderRange;
125
+ };
126
+ export {};