@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,166 @@
1
+ import { useDefaults } from "../runtime.js";
2
+ import { colorClass, cx, radiusClass, sizeClass } from "../classes.js";
3
+ import { useControllable } from "../hooks.js";
4
+ import { FieldContext, useFieldProps } from "../field-context.js";
5
+ import { useContext, useId, useRef } from "react";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ //#region src/components/Slider.tsx
8
+ var clamp = (value, low, high) => Math.min(Math.max(value, low), high);
9
+ function decimals(value) {
10
+ const text = String(value);
11
+ const exponent = text.match(/e-(\d+)$/);
12
+ if (exponent) return Number(exponent[1]);
13
+ return text.split(".")[1]?.length ?? 0;
14
+ }
15
+ var DEFAULT_THUMB_LABELS = ["Minimum", "Maximum"];
16
+ /**
17
+ * Picks a number, or a range with two thumbs, by dragging along a track.
18
+ * Each thumb has `role="slider"` and supports the arrow keys, Home, End, PageUp and PageDown.
19
+ * Shares the size scale with the other controls. Works inside a {@link Field}; outside one, give it an `aria-label`.
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * <Field label="Volume">
24
+ * <Slider defaultValue={40} />
25
+ * </Field>
26
+ * ```
27
+ */
28
+ function SliderRoot(props) {
29
+ const own = useDefaults("Slider");
30
+ const field = useContext(FieldContext);
31
+ const uid = useId();
32
+ const { value: valueProp, defaultValue, onValueChange, min = 0, max = 100, step = 1, largeStep, disabled = false, name, formatValue, thumbLabels = DEFAULT_THUMB_LABELS, size, radius, color, className, style, id, required: _required, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, onPointerDown, onPointerMove, onPointerUp, onLostPointerCapture, ...rest } = useFieldProps(props);
33
+ const [value, setValue] = useControllable(valueProp, defaultValue ?? min, onValueChange);
34
+ const trackRef = useRef(null);
35
+ const thumbRefs = useRef([]);
36
+ const dragging = useRef(null);
37
+ const range = Array.isArray(value);
38
+ const values = (range ? value : [value]).map((v) => clamp(v, min, max));
39
+ const precision = decimals(step);
40
+ const big = largeStep ?? Math.max(step, Math.round((max - min) / 10 / step) * step);
41
+ const snap = (raw) => Number(clamp(min + Math.round((raw - min) / step) * step, min, max).toFixed(precision));
42
+ const lowerBound = (index) => range && index === 1 ? values[0] : min;
43
+ const upperBound = (index) => range && index === 0 ? values[1] : max;
44
+ const percent = (v) => max > min ? (v - min) / (max - min) * 100 : 0;
45
+ function update(index, raw) {
46
+ const next = clamp(snap(raw), lowerBound(index), upperBound(index));
47
+ if (next === values[index]) return;
48
+ const nextValues = values.slice();
49
+ nextValues[index] = next;
50
+ setValue(range ? [nextValues[0], nextValues[1]] : nextValues[0]);
51
+ }
52
+ const rtl = () => trackRef.current != null && getComputedStyle(trackRef.current).direction === "rtl";
53
+ function valueAt(clientX) {
54
+ const rect = trackRef.current.getBoundingClientRect();
55
+ const ratio = rect.width > 0 ? clamp((clientX - rect.left) / rect.width, 0, 1) : 0;
56
+ return min + (rtl() ? 1 - ratio : ratio) * (max - min);
57
+ }
58
+ function handlePointerDown(event) {
59
+ onPointerDown?.(event);
60
+ if (disabled || event.defaultPrevented || event.button !== 0) return;
61
+ event.preventDefault();
62
+ const raw = valueAt(event.clientX);
63
+ let index = 0;
64
+ if (range) {
65
+ const [start, end] = values;
66
+ const toStart = Math.abs(raw - start);
67
+ const toEnd = Math.abs(raw - end);
68
+ index = toEnd < toStart || toEnd === toStart && raw > end ? 1 : 0;
69
+ }
70
+ dragging.current = index;
71
+ event.currentTarget.setPointerCapture(event.pointerId);
72
+ thumbRefs.current[index]?.focus();
73
+ update(index, raw);
74
+ }
75
+ function handlePointerMove(event) {
76
+ onPointerMove?.(event);
77
+ if (dragging.current != null) update(dragging.current, valueAt(event.clientX));
78
+ }
79
+ function handlePointerUp(event) {
80
+ onPointerUp?.(event);
81
+ dragging.current = null;
82
+ }
83
+ function handleLostPointerCapture(event) {
84
+ onLostPointerCapture?.(event);
85
+ dragging.current = null;
86
+ }
87
+ function handleKeyDown(index, event) {
88
+ if (disabled) return;
89
+ const current = values[index];
90
+ const forward = rtl() ? -step : step;
91
+ const moves = {
92
+ ArrowRight: current + forward,
93
+ ArrowLeft: current - forward,
94
+ ArrowUp: current + step,
95
+ ArrowDown: current - step,
96
+ PageUp: current + big,
97
+ PageDown: current - big,
98
+ Home: lowerBound(index),
99
+ End: upperBound(index)
100
+ };
101
+ if (!(event.key in moves)) return;
102
+ event.preventDefault();
103
+ update(index, moves[event.key]);
104
+ }
105
+ const outerLabelledBy = ariaLabelledBy ?? (field ? field.labelId : void 0);
106
+ const start = range ? percent(values[0]) : 0;
107
+ const end = percent(values[values.length - 1]);
108
+ return /* @__PURE__ */ jsxs("div", {
109
+ className: cx("yarcl-slider", sizeClass(size ?? own.size, "Slider"), radiusClass(radius ?? own.radius, size ?? own.size), colorClass(color ?? own.color), className),
110
+ style: {
111
+ ...style,
112
+ "--yarcl-slider-start": `${start}%`,
113
+ "--yarcl-slider-end": `${end}%`
114
+ },
115
+ "data-disabled": disabled || void 0,
116
+ onPointerDown: handlePointerDown,
117
+ onPointerMove: handlePointerMove,
118
+ onPointerUp: handlePointerUp,
119
+ onLostPointerCapture: handleLostPointerCapture,
120
+ ...rest,
121
+ children: [/* @__PURE__ */ jsxs("div", {
122
+ ref: trackRef,
123
+ className: "yarcl-slider-track",
124
+ children: [/* @__PURE__ */ jsx("div", { className: "yarcl-slider-range" }), values.map((v, index) => {
125
+ const thumbId = index === 0 && id ? id : `${uid}-thumb-${index}`;
126
+ const thumbLabel = range ? thumbLabels[index] : void 0;
127
+ return /* @__PURE__ */ jsx("div", {
128
+ ref: (el) => {
129
+ thumbRefs.current[index] = el;
130
+ },
131
+ id: thumbId,
132
+ role: "slider",
133
+ tabIndex: disabled ? void 0 : 0,
134
+ className: "yarcl-slider-thumb",
135
+ style: { "--yarcl-slider-position": `${percent(v)}%` },
136
+ "aria-valuemin": lowerBound(index),
137
+ "aria-valuemax": upperBound(index),
138
+ "aria-valuenow": v,
139
+ "aria-valuetext": formatValue?.(v),
140
+ "aria-orientation": "horizontal",
141
+ "aria-disabled": disabled || void 0,
142
+ "aria-invalid": ariaInvalid,
143
+ "aria-describedby": ariaDescribedBy,
144
+ "aria-label": thumbLabel && !outerLabelledBy && ariaLabel ? `${ariaLabel} ${thumbLabel}` : thumbLabel ?? ariaLabel,
145
+ "aria-labelledby": outerLabelledBy && (thumbLabel ? `${outerLabelledBy} ${thumbId}` : outerLabelledBy),
146
+ onKeyDown: (event) => handleKeyDown(index, event)
147
+ }, index);
148
+ })]
149
+ }), name != null && values.map((v, index) => /* @__PURE__ */ jsx("input", {
150
+ type: "hidden",
151
+ name,
152
+ value: v,
153
+ disabled
154
+ }, index))]
155
+ });
156
+ }
157
+ function SliderRange(props) {
158
+ return /* @__PURE__ */ jsx(SliderRoot, { ...props });
159
+ }
160
+ /**
161
+ * Picks a number, or a range with two thumbs, by dragging along a track.
162
+ * Use `Slider.Range` for an explicitly range-only API.
163
+ */
164
+ var Slider = Object.assign(SliderRoot, { Range: SliderRange });
165
+ //#endregion
166
+ export { Slider };
@@ -0,0 +1,23 @@
1
+ import type { ComponentProps } from 'react';
2
+ import type { Color, ComponentSize } from '../types';
3
+ /** Props for {@link Spinner}. */
4
+ export interface SpinnerProps extends Omit<ComponentProps<'span'>, 'color'> {
5
+ /** Diameter from the size's `iconSize`, from the `sizes` config. Inherits the surrounding control's size when omitted. */
6
+ size?: ComponentSize<'Spinner'>;
7
+ /** Semantic color, from the `colors` config. Uses the current text color when omitted. */
8
+ color?: Color;
9
+ /**
10
+ * Accessible label announced to screen readers.
11
+ * @default 'Loading'
12
+ */
13
+ label?: string;
14
+ }
15
+ /**
16
+ * An indeterminate loading indicator. Sized like an icon, so it fits inside controls of the same size.
17
+ *
18
+ * @example
19
+ * ```tsx
20
+ * <Spinner size="lg" color="brand" />
21
+ * ```
22
+ */
23
+ export declare function Spinner({ size, color, label, className, ...props }: SpinnerProps): import("react").JSX.Element;
@@ -0,0 +1,23 @@
1
+ import { useDefaults } from "../runtime.js";
2
+ import { colorClass, cx, sizeClass } from "../classes.js";
3
+ import { jsx } from "react/jsx-runtime";
4
+ //#region src/components/Spinner.tsx
5
+ /**
6
+ * An indeterminate loading indicator. Sized like an icon, so it fits inside controls of the same size.
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * <Spinner size="lg" color="brand" />
11
+ * ```
12
+ */
13
+ function Spinner({ size, color, label = "Loading", className, ...props }) {
14
+ const own = useDefaults("Spinner");
15
+ return /* @__PURE__ */ jsx("span", {
16
+ role: "status",
17
+ "aria-label": label,
18
+ className: cx("yarcl-spinner", (size ?? own.size) && sizeClass(size ?? own.size, "Spinner"), (color ?? own.color) && cx("yarcl-spinner-colored", colorClass(color ?? own.color)), className),
19
+ ...props
20
+ });
21
+ }
22
+ //#endregion
23
+ export { Spinner };
@@ -0,0 +1,35 @@
1
+ import type { ComponentProps } from 'react';
2
+ import type { Align, Justify, Spacing } from '../types';
3
+ /** Elements layout components can render as. */
4
+ export type LayoutElement = 'div' | 'section' | 'article' | 'aside' | 'header' | 'footer' | 'main' | 'nav' | 'form' | 'ul' | 'ol';
5
+ /** Props shared by {@link Stack} and {@link Inline}. */
6
+ export interface LayoutProps extends ComponentProps<'div'> {
7
+ /**
8
+ * Element to render.
9
+ * @default 'div'
10
+ */
11
+ as?: LayoutElement;
12
+ /**
13
+ * Space between children, from the `spacing` config.
14
+ * @default config.defaults.gap
15
+ */
16
+ gap?: Spacing;
17
+ /** Cross-axis alignment of children. */
18
+ align?: Align;
19
+ /** Main-axis distribution of children. */
20
+ justify?: Justify;
21
+ }
22
+ /** Props for {@link Stack}. */
23
+ export type StackProps = LayoutProps;
24
+ /**
25
+ * Lays out children vertically with a gap from the spacing scale.
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * <Stack gap="loose">
30
+ * <Heading level={2}>Profile</Heading>
31
+ * <Field label="Name"><Input /></Field>
32
+ * </Stack>
33
+ * ```
34
+ */
35
+ export declare function Stack({ as, gap, align, justify, className, ...props }: StackProps): import("react").JSX.Element;
@@ -0,0 +1,24 @@
1
+ import { useDefaults } from "../runtime.js";
2
+ import { cx, gapClass } from "../classes.js";
3
+ import { jsx } from "react/jsx-runtime";
4
+ //#region src/components/Stack.tsx
5
+ /**
6
+ * Lays out children vertically with a gap from the spacing scale.
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * <Stack gap="loose">
11
+ * <Heading level={2}>Profile</Heading>
12
+ * <Field label="Name"><Input /></Field>
13
+ * </Stack>
14
+ * ```
15
+ */
16
+ function Stack({ as = "div", gap, align, justify, className, ...props }) {
17
+ const own = useDefaults("Stack");
18
+ return /* @__PURE__ */ jsx(as, {
19
+ className: cx("yarcl-stack", gapClass(gap ?? own.gap), align && `yarcl-align-${align}`, justify && `yarcl-justify-${justify}`, className),
20
+ ...props
21
+ });
22
+ }
23
+ //#endregion
24
+ export { Stack };
@@ -0,0 +1,27 @@
1
+ import type { ComponentProps, ReactNode } from 'react';
2
+ import type { Color, ComponentSize } from '../types';
3
+ /** Props for {@link Switch}. Accepts all native `<input>` attributes except `type`, `color` and `size`. */
4
+ export interface SwitchProps extends Omit<ComponentProps<'input'>, 'type' | 'color' | 'size' | 'children'> {
5
+ /** Label shown next to the switch. */
6
+ children?: ReactNode;
7
+ /**
8
+ * Switch size, from the `sizes` config (scaled from the size's `iconSize`).
9
+ * @default config.defaults.size
10
+ */
11
+ size?: ComponentSize<'Switch'>;
12
+ /**
13
+ * Track color when on, from the `colors` config.
14
+ * @default config.defaults.color
15
+ */
16
+ color?: Color;
17
+ }
18
+ /**
19
+ * An on/off toggle. A native checkbox with `role="switch"`, so `checked`,
20
+ * `defaultChecked` and `onChange` work as usual.
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * <Switch defaultChecked>Notifications</Switch>
25
+ * ```
26
+ */
27
+ export declare function Switch(props: SwitchProps): import("react").JSX.Element;
@@ -0,0 +1,33 @@
1
+ import { useDefaults } from "../runtime.js";
2
+ import { colorClass, cx, sizeClass } from "../classes.js";
3
+ import { useFieldProps } from "../field-context.js";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ //#region src/components/Switch.tsx
6
+ /**
7
+ * An on/off toggle. A native checkbox with `role="switch"`, so `checked`,
8
+ * `defaultChecked` and `onChange` work as usual.
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * <Switch defaultChecked>Notifications</Switch>
13
+ * ```
14
+ */
15
+ function Switch(props) {
16
+ const own = useDefaults("Switch");
17
+ const { children, size, color, className, style, ...rest } = useFieldProps(props);
18
+ return /* @__PURE__ */ jsxs("label", {
19
+ className: cx("yarcl-switch", sizeClass(size ?? own.size, "Switch"), colorClass(color ?? own.color), className),
20
+ style,
21
+ children: [/* @__PURE__ */ jsx("input", {
22
+ type: "checkbox",
23
+ role: "switch",
24
+ className: "yarcl-switch-input",
25
+ ...rest
26
+ }), children != null && /* @__PURE__ */ jsx("span", {
27
+ className: "yarcl-switch-label",
28
+ children
29
+ })]
30
+ });
31
+ }
32
+ //#endregion
33
+ export { Switch };
@@ -0,0 +1,71 @@
1
+ import type { ComponentProps, ReactNode } from 'react';
2
+ import type { Density, Radius } from '../types';
3
+ /** Props for {@link Table}. */
4
+ export interface TableProps extends ComponentProps<'table'> {
5
+ /**
6
+ * Cell padding and font size, from the `density` config.
7
+ * @default config.defaults.density
8
+ */
9
+ density?: Density;
10
+ /**
11
+ * Corner radius of the table frame, from the `radii` config.
12
+ * @default config.components.Table.radius ?? config.defaults.radius
13
+ */
14
+ radius?: Radius;
15
+ /** Shades every other row. */
16
+ striped?: boolean;
17
+ /** Highlights the row under the pointer. Use when rows are clickable. */
18
+ interactive?: boolean;
19
+ /** Visible caption describing the table. Also its accessible name. */
20
+ caption?: ReactNode;
21
+ }
22
+ declare function TableRoot({ density, radius, striped, interactive, caption, className, children, ...props }: TableProps): import("react").JSX.Element;
23
+ /** Horizontal alignment of a cell's content. `end` also uses tabular numbers, for numeric columns. */
24
+ export type CellAlign = 'start' | 'center' | 'end';
25
+ /** Props for `Table.HeaderCell`. */
26
+ export interface TableHeaderCellProps extends Omit<ComponentProps<'th'>, 'align'> {
27
+ /**
28
+ * Content alignment.
29
+ * @default 'start'
30
+ */
31
+ align?: CellAlign;
32
+ }
33
+ declare function TableHeaderCell({ align, scope, className, ...props }: TableHeaderCellProps): import("react").JSX.Element;
34
+ /** Props for `Table.Cell`. */
35
+ export interface TableCellProps extends Omit<ComponentProps<'td'>, 'align'> {
36
+ /**
37
+ * Content alignment.
38
+ * @default 'start'
39
+ */
40
+ align?: CellAlign;
41
+ }
42
+ declare function TableCell({ align, className, ...props }: TableCellProps): import("react").JSX.Element;
43
+ /**
44
+ * A data table with density from the config. Scrolls horizontally when it doesn't fit.
45
+ *
46
+ * @example
47
+ * ```tsx
48
+ * <Table density="compact" striped caption="Invoices">
49
+ * <Table.Head>
50
+ * <Table.Row>
51
+ * <Table.HeaderCell>Customer</Table.HeaderCell>
52
+ * <Table.HeaderCell align="end">Amount</Table.HeaderCell>
53
+ * </Table.Row>
54
+ * </Table.Head>
55
+ * <Table.Body>
56
+ * <Table.Row>
57
+ * <Table.Cell>Ada</Table.Cell>
58
+ * <Table.Cell align="end">$120.00</Table.Cell>
59
+ * </Table.Row>
60
+ * </Table.Body>
61
+ * </Table>
62
+ * ```
63
+ */
64
+ export declare const Table: typeof TableRoot & {
65
+ Head: (props: ComponentProps<"thead">) => import("react").JSX.Element;
66
+ Body: (props: ComponentProps<"tbody">) => import("react").JSX.Element;
67
+ Row: (props: ComponentProps<"tr">) => import("react").JSX.Element;
68
+ HeaderCell: typeof TableHeaderCell;
69
+ Cell: typeof TableCell;
70
+ };
71
+ export {};
@@ -0,0 +1,61 @@
1
+ import { useDefaults } from "../runtime.js";
2
+ import { cx, densityClass, radiusClass } from "../classes.js";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ //#region src/components/Table.tsx
5
+ function TableRoot({ density, radius, striped, interactive, caption, className, children, ...props }) {
6
+ const own = useDefaults("Table");
7
+ return /* @__PURE__ */ jsx("div", {
8
+ className: cx("yarcl-table-wrap", radiusClass(radius ?? own.radius)),
9
+ children: /* @__PURE__ */ jsxs("table", {
10
+ className: cx("yarcl-table", densityClass(density ?? own.density), striped && "yarcl-table-striped", interactive && "yarcl-table-interactive", className),
11
+ ...props,
12
+ children: [caption != null && /* @__PURE__ */ jsx("caption", {
13
+ className: "yarcl-table-caption",
14
+ children: caption
15
+ }), children]
16
+ })
17
+ });
18
+ }
19
+ function TableHeaderCell({ align = "start", scope = "col", className, ...props }) {
20
+ return /* @__PURE__ */ jsx("th", {
21
+ scope,
22
+ className: cx(`yarcl-cell-${align}`, className),
23
+ ...props
24
+ });
25
+ }
26
+ function TableCell({ align = "start", className, ...props }) {
27
+ return /* @__PURE__ */ jsx("td", {
28
+ className: cx(`yarcl-cell-${align}`, className),
29
+ ...props
30
+ });
31
+ }
32
+ /**
33
+ * A data table with density from the config. Scrolls horizontally when it doesn't fit.
34
+ *
35
+ * @example
36
+ * ```tsx
37
+ * <Table density="compact" striped caption="Invoices">
38
+ * <Table.Head>
39
+ * <Table.Row>
40
+ * <Table.HeaderCell>Customer</Table.HeaderCell>
41
+ * <Table.HeaderCell align="end">Amount</Table.HeaderCell>
42
+ * </Table.Row>
43
+ * </Table.Head>
44
+ * <Table.Body>
45
+ * <Table.Row>
46
+ * <Table.Cell>Ada</Table.Cell>
47
+ * <Table.Cell align="end">$120.00</Table.Cell>
48
+ * </Table.Row>
49
+ * </Table.Body>
50
+ * </Table>
51
+ * ```
52
+ */
53
+ var Table = Object.assign(TableRoot, {
54
+ Head: (props) => /* @__PURE__ */ jsx("thead", { ...props }),
55
+ Body: (props) => /* @__PURE__ */ jsx("tbody", { ...props }),
56
+ Row: (props) => /* @__PURE__ */ jsx("tr", { ...props }),
57
+ HeaderCell: TableHeaderCell,
58
+ Cell: TableCell
59
+ });
60
+ //#endregion
61
+ export { Table };
@@ -0,0 +1,66 @@
1
+ import { type ComponentProps, type ReactNode } from 'react';
2
+ import type { Color, ComponentSize } from '../types';
3
+ /** Props shared by both forms of {@link TabsProps}. */
4
+ export interface TabsBaseProps extends Omit<ComponentProps<'div'>, 'defaultValue' | 'color'> {
5
+ /** Called with the newly selected tab's value. */
6
+ onValueChange?: (value: string) => void;
7
+ /**
8
+ * Tab height and font size, from the `sizes` config.
9
+ * @default config.defaults.size
10
+ */
11
+ size?: ComponentSize<'Tabs'>;
12
+ /**
13
+ * Color of the selected tab's indicator, from the `colors` config.
14
+ * @default config.defaults.color
15
+ */
16
+ color?: Color;
17
+ }
18
+ /** Props for {@link Tabs}. Pass `value` (controlled) or `defaultValue` (uncontrolled). */
19
+ export type TabsProps = TabsBaseProps & ({
20
+ value: string;
21
+ defaultValue?: never;
22
+ } | {
23
+ value?: never; /** Initially selected tab (uncontrolled). */
24
+ defaultValue: string;
25
+ });
26
+ declare function TabsRoot({ value: valueProp, defaultValue, onValueChange, size, color, className, ...props }: TabsProps): import("react").JSX.Element;
27
+ /** Props for `Tabs.List`. */
28
+ export interface TabsListProps extends ComponentProps<'div'> {
29
+ /** `Tabs.Trigger`s. */
30
+ children?: ReactNode;
31
+ }
32
+ declare function TabsList({ className, onKeyDown, ...props }: TabsListProps): import("react").JSX.Element;
33
+ /** Props for `Tabs.Trigger`. */
34
+ export interface TabsTriggerProps extends Omit<ComponentProps<'button'>, 'value'> {
35
+ /** Identifies the tab; matches a `Tabs.Panel`'s `value`. */
36
+ value: string;
37
+ }
38
+ declare function TabsTrigger({ value, className, onClick, ...props }: TabsTriggerProps): import("react").JSX.Element;
39
+ /** Props for `Tabs.Panel`. */
40
+ export interface TabsPanelProps extends Omit<ComponentProps<'div'>, 'value'> {
41
+ /** Matches the `value` of the `Tabs.Trigger` that shows this panel. */
42
+ value: string;
43
+ }
44
+ declare function TabsPanel({ value, className, ...props }: TabsPanelProps): import("react").JSX.Element;
45
+ /**
46
+ * Switches between panels of content. Arrow keys move between tabs, Home and End jump to the ends.
47
+ * Tab height comes from the shared size scale.
48
+ *
49
+ * @example
50
+ * ```tsx
51
+ * <Tabs defaultValue="overview">
52
+ * <Tabs.List aria-label="Project">
53
+ * <Tabs.Trigger value="overview">Overview</Tabs.Trigger>
54
+ * <Tabs.Trigger value="settings">Settings</Tabs.Trigger>
55
+ * </Tabs.List>
56
+ * <Tabs.Panel value="overview">…</Tabs.Panel>
57
+ * <Tabs.Panel value="settings">…</Tabs.Panel>
58
+ * </Tabs>
59
+ * ```
60
+ */
61
+ export declare const Tabs: typeof TabsRoot & {
62
+ List: typeof TabsList;
63
+ Trigger: typeof TabsTrigger;
64
+ Panel: typeof TabsPanel;
65
+ };
66
+ export {};
@@ -0,0 +1,109 @@
1
+ import { useDefaults } from "../runtime.js";
2
+ import { colorClass, cx, sizeClass } from "../classes.js";
3
+ import { useControllable } from "../hooks.js";
4
+ import { createContext, useContext, useId } from "react";
5
+ import { jsx } from "react/jsx-runtime";
6
+ //#region src/components/Tabs.tsx
7
+ var TabsContext = createContext(null);
8
+ function useTabsContext(component) {
9
+ const context = useContext(TabsContext);
10
+ if (!context) throw new Error(`yarcl: <${component}> must be inside <Tabs>`);
11
+ return context;
12
+ }
13
+ function TabsRoot({ value: valueProp, defaultValue, onValueChange, size, color, className, ...props }) {
14
+ const own = useDefaults("Tabs");
15
+ const [value, select] = useControllable(valueProp, defaultValue ?? "", onValueChange);
16
+ const baseId = useId();
17
+ const idFor = (kind, v) => `${baseId}-${kind}-${v.replace(/[^\w-]/g, "_")}`;
18
+ return /* @__PURE__ */ jsx(TabsContext.Provider, {
19
+ value: {
20
+ value,
21
+ select,
22
+ idFor
23
+ },
24
+ children: /* @__PURE__ */ jsx("div", {
25
+ className: cx("yarcl-tabs", sizeClass(size ?? own.size, "Tabs"), colorClass(color ?? own.color), className),
26
+ ...props
27
+ })
28
+ });
29
+ }
30
+ function TabsList({ className, onKeyDown, ...props }) {
31
+ const { select } = useTabsContext("Tabs.List");
32
+ function handleKeyDown(event) {
33
+ onKeyDown?.(event);
34
+ const tabs = [...event.currentTarget.querySelectorAll("[role=\"tab\"]:not(:disabled)")];
35
+ const current = tabs.indexOf(document.activeElement);
36
+ if (current === -1) return;
37
+ const next = {
38
+ ArrowRight: (current + 1) % tabs.length,
39
+ ArrowLeft: (current - 1 + tabs.length) % tabs.length,
40
+ Home: 0,
41
+ End: tabs.length - 1
42
+ }[event.key];
43
+ if (next === void 0) return;
44
+ event.preventDefault();
45
+ tabs[next].focus();
46
+ select(tabs[next].dataset.value);
47
+ }
48
+ return /* @__PURE__ */ jsx("div", {
49
+ role: "tablist",
50
+ className: cx("yarcl-tabs-list", className),
51
+ onKeyDown: handleKeyDown,
52
+ ...props
53
+ });
54
+ }
55
+ function TabsTrigger({ value, className, onClick, ...props }) {
56
+ const context = useTabsContext("Tabs.Trigger");
57
+ const selected = context.value === value;
58
+ return /* @__PURE__ */ jsx("button", {
59
+ type: "button",
60
+ role: "tab",
61
+ id: context.idFor("tab", value),
62
+ "aria-controls": context.idFor("panel", value),
63
+ "aria-selected": selected,
64
+ tabIndex: selected ? 0 : -1,
65
+ "data-value": value,
66
+ className: cx("yarcl-tabs-trigger", className),
67
+ onClick: (event) => {
68
+ onClick?.(event);
69
+ context.select(value);
70
+ },
71
+ ...props
72
+ });
73
+ }
74
+ function TabsPanel({ value, className, ...props }) {
75
+ const context = useTabsContext("Tabs.Panel");
76
+ const selected = context.value === value;
77
+ return /* @__PURE__ */ jsx("div", {
78
+ role: "tabpanel",
79
+ id: context.idFor("panel", value),
80
+ "aria-labelledby": context.idFor("tab", value),
81
+ tabIndex: 0,
82
+ hidden: !selected,
83
+ className: cx("yarcl-tabs-panel", className),
84
+ ...props
85
+ });
86
+ }
87
+ /**
88
+ * Switches between panels of content. Arrow keys move between tabs, Home and End jump to the ends.
89
+ * Tab height comes from the shared size scale.
90
+ *
91
+ * @example
92
+ * ```tsx
93
+ * <Tabs defaultValue="overview">
94
+ * <Tabs.List aria-label="Project">
95
+ * <Tabs.Trigger value="overview">Overview</Tabs.Trigger>
96
+ * <Tabs.Trigger value="settings">Settings</Tabs.Trigger>
97
+ * </Tabs.List>
98
+ * <Tabs.Panel value="overview">…</Tabs.Panel>
99
+ * <Tabs.Panel value="settings">…</Tabs.Panel>
100
+ * </Tabs>
101
+ * ```
102
+ */
103
+ var Tabs = Object.assign(TabsRoot, {
104
+ List: TabsList,
105
+ Trigger: TabsTrigger,
106
+ Panel: TabsPanel
107
+ });
108
+ //#endregion
109
+ export { Tabs };
@@ -0,0 +1,32 @@
1
+ import type { ComponentProps } from 'react';
2
+ import type { Color, TextStyle } from '../types';
3
+ /** Elements {@link Text} can render as. */
4
+ export type TextElement = 'span' | 'p' | 'div' | 'strong' | 'em' | 'small' | 'code' | 'label';
5
+ /** Props for {@link Text}. */
6
+ export interface TextProps extends Omit<ComponentProps<'span'>, 'color'> {
7
+ /**
8
+ * Element to render.
9
+ * @default 'span'
10
+ */
11
+ as?: TextElement;
12
+ /**
13
+ * Text style, from the `typography.styles` config.
14
+ * @default config.defaults.textStyle
15
+ */
16
+ textStyle?: TextStyle;
17
+ /** Semantic color, from the `colors` config. Inherits the surrounding color when omitted. */
18
+ color?: Color;
19
+ /** Uses the muted neutral color, for secondary text. */
20
+ muted?: boolean;
21
+ /** Truncates with an ellipsis: `true` for one line, a number for that many lines. */
22
+ truncate?: boolean | number;
23
+ }
24
+ /**
25
+ * Text in one of the consumer's text styles.
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * <Text as="p" textStyle="caption" muted>Updated 2 minutes ago</Text>
30
+ * ```
31
+ */
32
+ export declare function Text({ as, textStyle, color, muted, truncate, className, style, ...props }: TextProps): import("react").JSX.Element;