@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
@@ -1,95 +0,0 @@
1
- import type { ComponentProps, CSSProperties } from 'react';
2
- import { cx, radiusClass, sizeClass, typeClass } from '../classes';
3
- import type { Radius, Size, TextStyle } from '../types';
4
- import { useDefaults } from '../runtime';
5
-
6
-
7
- /** Props for {@link Skeleton}. */
8
- export interface SkeletonProps extends Omit<ComponentProps<'span'>, 'children'> {
9
- /**
10
- * `text`: lines matching a text style; `control`: the height of a control of the given `size`;
11
- * `circle`: a circle, e.g. for an avatar; `rect`: a block sized by `width` and `height`.
12
- * @default 'text'
13
- */
14
- shape?: 'text' | 'control' | 'circle' | 'rect';
15
- /** Number of lines for `shape="text"`. The last line is shorter. */
16
- lines?: number;
17
- /**
18
- * Text style whose font size and line height the lines match, for `shape="text"`.
19
- * @default config.defaults.textStyle
20
- */
21
- textStyle?: TextStyle;
22
- /**
23
- * Control size, from the `sizes` config. Sets the height for `shape="control"` and the diameter for `shape="circle"`.
24
- * @default config.defaults.size
25
- */
26
- size?: Size;
27
- /**
28
- * Corner radius for `control` and `rect`, from the `radii` config.
29
- * @default config.defaults.radius
30
- */
31
- radius?: Radius | 'size';
32
- /** Width as a CSS length. */
33
- width?: string;
34
- /** Height as a CSS length, for `shape="rect"`. */
35
- height?: string;
36
- }
37
-
38
- /**
39
- * A placeholder shown while content loads. Hidden from assistive technology;
40
- * mark the loading region with `aria-busy` instead.
41
- *
42
- * @example
43
- * ```tsx
44
- * <Stack aria-busy>
45
- * <Skeleton shape="text" textStyle="title" width="40%" />
46
- * <Skeleton shape="text" lines={3} />
47
- * <Skeleton shape="control" width="12rem" />
48
- * </Stack>
49
- * ```
50
- */
51
- export function Skeleton({
52
- shape = 'text',
53
- lines = 1,
54
- textStyle,
55
- size,
56
- radius,
57
- width,
58
- height,
59
- className,
60
- style,
61
- ...props
62
- }: SkeletonProps) {
63
- const own = useDefaults('Skeleton');
64
- const dimensions = { width, height, ...style } as CSSProperties;
65
-
66
- if (shape === 'text') {
67
- return (
68
- <span
69
- aria-hidden="true"
70
- className={cx('yarcl-skeleton-text', textStyle && typeClass(textStyle), className)}
71
- style={dimensions}
72
- {...props}
73
- >
74
- {Array.from({ length: lines }, (_, i) => (
75
- <span key={i} className="yarcl-skeleton yarcl-skeleton-line" />
76
- ))}
77
- </span>
78
- );
79
- }
80
-
81
- return (
82
- <span
83
- aria-hidden="true"
84
- className={cx(
85
- 'yarcl-skeleton',
86
- `yarcl-skeleton-${shape}`,
87
- shape !== 'rect' && sizeClass(size ?? own.size),
88
- shape !== 'circle' && radiusClass(radius ?? own.radius, size ?? own.size),
89
- className,
90
- )}
91
- style={dimensions}
92
- {...props}
93
- />
94
- );
95
- }
@@ -1,315 +0,0 @@
1
- import {
2
- useContext,
3
- useId,
4
- useRef,
5
- type ComponentProps,
6
- type CSSProperties,
7
- type KeyboardEvent,
8
- type PointerEvent,
9
- } from 'react';
10
- import { colorClass, cx, radiusClass, sizeClass } from '../classes';
11
- import { FieldContext, useFieldProps } from '../field-context';
12
- import { useControllable } from '../hooks';
13
- import type { TokenProps } from '../types';
14
- import { useDefaults } from '../runtime';
15
-
16
- /** A {@link Slider} value: one number, or a `[start, end]` pair for a range. */
17
- export type SliderValue = number | [number, number];
18
-
19
- /** Props for {@link Slider}. Accepts all native `<div>` attributes except `color`, `defaultValue`, `onChange` and `children`. */
20
- export interface SliderProps<V extends SliderValue = number>
21
- extends TokenProps,
22
- Omit<ComponentProps<'div'>, 'color' | 'defaultValue' | 'onChange' | 'children'> {
23
- /**
24
- * Controlled value. Pass a `[start, end]` pair for a range with two thumbs.
25
- * @example
26
- * ```tsx
27
- * <Slider value={volume} onValueChange={setVolume} aria-label="Volume" />
28
- * ```
29
- */
30
- value?: V;
31
- /**
32
- * Initial value when uncontrolled. Pass a `[start, end]` pair for a range with two thumbs.
33
- * @default min
34
- * @example
35
- * ```tsx
36
- * <Slider defaultValue={[20, 80]} aria-label="Price" />
37
- * ```
38
- */
39
- defaultValue?: V;
40
- /**
41
- * Called with the new value while the user drags or presses a key.
42
- * @example
43
- * ```tsx
44
- * <Slider onValueChange={(value) => setVolume(value)} aria-label="Volume" />
45
- * ```
46
- */
47
- onValueChange?: (value: V) => void;
48
- /**
49
- * Lowest value.
50
- * @default 0
51
- * @example
52
- * ```tsx
53
- * <Slider min={-10} max={10} aria-label="Offset" />
54
- * ```
55
- */
56
- min?: number;
57
- /**
58
- * Highest value.
59
- * @default 100
60
- * @example
61
- * ```tsx
62
- * <Slider max={10} aria-label="Rating" />
63
- * ```
64
- */
65
- max?: number;
66
- /**
67
- * Interval between values. Values snap to multiples of it, counted from `min`.
68
- * @default 1
69
- * @example
70
- * ```tsx
71
- * <Slider step={5} aria-label="Opacity" />
72
- * ```
73
- */
74
- step?: number;
75
- /**
76
- * Jump for PageUp and PageDown.
77
- * @default a tenth of the range, rounded to a whole number of steps
78
- * @example
79
- * ```tsx
80
- * <Slider step={1} largeStep={25} aria-label="Progress" />
81
- * ```
82
- */
83
- largeStep?: number;
84
- /**
85
- * Prevents interaction and dims the slider.
86
- * @default false
87
- * @example
88
- * ```tsx
89
- * <Slider disabled defaultValue={40} aria-label="Volume" />
90
- * ```
91
- */
92
- disabled?: boolean;
93
- /**
94
- * Form field name. Renders a hidden input per thumb with its value.
95
- * @example
96
- * ```tsx
97
- * <Slider name="volume" aria-label="Volume" />
98
- * ```
99
- */
100
- name?: string;
101
- /**
102
- * Formats a value for screen readers (`aria-valuetext`).
103
- * @example
104
- * ```tsx
105
- * <Slider formatValue={(value) => `${value} percent`} aria-label="Volume" />
106
- * ```
107
- */
108
- formatValue?: (value: number) => string;
109
- /**
110
- * Names of the two thumbs of a range, added to the slider's label.
111
- * @default ['Minimum', 'Maximum']
112
- * @example
113
- * ```tsx
114
- * <Slider defaultValue={[9, 17]} thumbLabels={['Opens', 'Closes']} aria-label="Hours" />
115
- * ```
116
- */
117
- thumbLabels?: readonly [string, string];
118
- }
119
-
120
- const clamp = (value: number, low: number, high: number) => Math.min(Math.max(value, low), high);
121
-
122
- function decimals(value: number): number {
123
- const text = String(value);
124
- const exponent = text.match(/e-(\d+)$/);
125
- if (exponent) return Number(exponent[1]);
126
- return text.split('.')[1]?.length ?? 0;
127
- }
128
-
129
- const DEFAULT_THUMB_LABELS = ['Minimum', 'Maximum'] as const;
130
-
131
- /**
132
- * Picks a number, or a range with two thumbs, by dragging along a track.
133
- * Each thumb has `role="slider"` and supports the arrow keys, Home, End, PageUp and PageDown.
134
- * Shares the size scale with the other controls. Works inside a {@link Field}; outside one, give it an `aria-label`.
135
- *
136
- * @example
137
- * ```tsx
138
- * <Field label="Volume">
139
- * <Slider defaultValue={40} />
140
- * </Field>
141
- * ```
142
- */
143
- export function Slider<V extends SliderValue = number>(props: SliderProps<V>) {
144
- const own = useDefaults('Slider');
145
- const field = useContext(FieldContext);
146
- const uid = useId();
147
- const {
148
- value: valueProp,
149
- defaultValue,
150
- onValueChange,
151
- min = 0,
152
- max = 100,
153
- step = 1,
154
- largeStep,
155
- disabled = false,
156
- name,
157
- formatValue,
158
- thumbLabels = DEFAULT_THUMB_LABELS,
159
- size,
160
- radius,
161
- color,
162
- className,
163
- style,
164
- id,
165
- required: _required,
166
- 'aria-label': ariaLabel,
167
- 'aria-labelledby': ariaLabelledBy,
168
- 'aria-describedby': ariaDescribedBy,
169
- 'aria-invalid': ariaInvalid,
170
- onPointerDown,
171
- onPointerMove,
172
- onPointerUp,
173
- onLostPointerCapture,
174
- ...rest
175
- } = useFieldProps(props) as SliderProps<V> & { required?: boolean };
176
-
177
- const [value, setValue] = useControllable<V>(valueProp, defaultValue ?? (min as V), onValueChange);
178
- const trackRef = useRef<HTMLDivElement>(null);
179
- const thumbRefs = useRef<(HTMLDivElement | null)[]>([]);
180
- const dragging = useRef<number | null>(null);
181
-
182
- const range = Array.isArray(value);
183
- const values = (range ? value : [value]).map((v) => clamp(v, min, max));
184
- const precision = decimals(step);
185
- const big = largeStep ?? Math.max(step, Math.round((max - min) / 10 / step) * step);
186
-
187
- const snap = (raw: number) => Number(clamp(min + Math.round((raw - min) / step) * step, min, max).toFixed(precision));
188
- const lowerBound = (index: number) => (range && index === 1 ? values[0] : min);
189
- const upperBound = (index: number) => (range && index === 0 ? values[1] : max);
190
- const percent = (v: number) => (max > min ? ((v - min) / (max - min)) * 100 : 0);
191
-
192
- function update(index: number, raw: number) {
193
- const next = clamp(snap(raw), lowerBound(index), upperBound(index));
194
- if (next === values[index]) return;
195
- const nextValues = values.slice();
196
- nextValues[index] = next;
197
- setValue((range ? [nextValues[0], nextValues[1]] : nextValues[0]) as V);
198
- }
199
-
200
- const rtl = () => trackRef.current != null && getComputedStyle(trackRef.current).direction === 'rtl';
201
-
202
- function valueAt(clientX: number): number {
203
- const rect = trackRef.current!.getBoundingClientRect();
204
- const ratio = rect.width > 0 ? clamp((clientX - rect.left) / rect.width, 0, 1) : 0;
205
- return min + (rtl() ? 1 - ratio : ratio) * (max - min);
206
- }
207
-
208
- function handlePointerDown(event: PointerEvent<HTMLDivElement>) {
209
- onPointerDown?.(event);
210
- if (disabled || event.defaultPrevented || event.button !== 0) return;
211
- event.preventDefault();
212
- const raw = valueAt(event.clientX);
213
- let index = 0;
214
- if (range) {
215
- const [start, end] = values;
216
- const toStart = Math.abs(raw - start);
217
- const toEnd = Math.abs(raw - end);
218
- index = toEnd < toStart || (toEnd === toStart && raw > end) ? 1 : 0;
219
- }
220
- dragging.current = index;
221
- event.currentTarget.setPointerCapture(event.pointerId);
222
- thumbRefs.current[index]?.focus();
223
- update(index, raw);
224
- }
225
-
226
- function handlePointerMove(event: PointerEvent<HTMLDivElement>) {
227
- onPointerMove?.(event);
228
- if (dragging.current != null) update(dragging.current, valueAt(event.clientX));
229
- }
230
-
231
- function handlePointerUp(event: PointerEvent<HTMLDivElement>) {
232
- onPointerUp?.(event);
233
- dragging.current = null;
234
- }
235
-
236
- function handleLostPointerCapture(event: PointerEvent<HTMLDivElement>) {
237
- onLostPointerCapture?.(event);
238
- dragging.current = null;
239
- }
240
-
241
- function handleKeyDown(index: number, event: KeyboardEvent<HTMLDivElement>) {
242
- if (disabled) return;
243
- const current = values[index];
244
- const forward = rtl() ? -step : step;
245
- const moves: Record<string, number> = {
246
- ArrowRight: current + forward,
247
- ArrowLeft: current - forward,
248
- ArrowUp: current + step,
249
- ArrowDown: current - step,
250
- PageUp: current + big,
251
- PageDown: current - big,
252
- Home: lowerBound(index),
253
- End: upperBound(index),
254
- };
255
- if (!(event.key in moves)) return;
256
- event.preventDefault();
257
- update(index, moves[event.key]);
258
- }
259
-
260
- const outerLabelledBy = ariaLabelledBy ?? (field ? field.labelId : undefined);
261
- const start = range ? percent(values[0]) : 0;
262
- const end = percent(values[values.length - 1]);
263
-
264
- return (
265
- <div
266
- className={cx(
267
- 'yarcl-slider',
268
- sizeClass(size ?? own.size),
269
- radiusClass(radius ?? own.radius, size ?? own.size),
270
- colorClass(color ?? own.color),
271
- className,
272
- )}
273
- style={{ ...style, '--yarcl-slider-start': `${start}%`, '--yarcl-slider-end': `${end}%` } as CSSProperties}
274
- data-disabled={disabled || undefined}
275
- onPointerDown={handlePointerDown}
276
- onPointerMove={handlePointerMove}
277
- onPointerUp={handlePointerUp}
278
- onLostPointerCapture={handleLostPointerCapture}
279
- {...rest}
280
- >
281
- <div ref={trackRef} className="yarcl-slider-track">
282
- <div className="yarcl-slider-range" />
283
- {values.map((v, index) => {
284
- const thumbId = index === 0 && id ? id : `${uid}-thumb-${index}`;
285
- const thumbLabel = range ? thumbLabels[index] : undefined;
286
- return (
287
- <div
288
- key={index}
289
- ref={(el) => {
290
- thumbRefs.current[index] = el;
291
- }}
292
- id={thumbId}
293
- role="slider"
294
- tabIndex={disabled ? undefined : 0}
295
- className="yarcl-slider-thumb"
296
- style={{ '--yarcl-slider-position': `${percent(v)}%` } as CSSProperties}
297
- aria-valuemin={lowerBound(index)}
298
- aria-valuemax={upperBound(index)}
299
- aria-valuenow={v}
300
- aria-valuetext={formatValue?.(v)}
301
- aria-orientation="horizontal"
302
- aria-disabled={disabled || undefined}
303
- aria-invalid={ariaInvalid}
304
- aria-describedby={ariaDescribedBy}
305
- aria-label={thumbLabel && !outerLabelledBy && ariaLabel ? `${ariaLabel} ${thumbLabel}` : (thumbLabel ?? ariaLabel)}
306
- aria-labelledby={outerLabelledBy && (thumbLabel ? `${outerLabelledBy} ${thumbId}` : outerLabelledBy)}
307
- onKeyDown={(event) => handleKeyDown(index, event)}
308
- />
309
- );
310
- })}
311
- </div>
312
- {name != null && values.map((v, index) => <input key={index} type="hidden" name={name} value={v} disabled={disabled} />)}
313
- </div>
314
- );
315
- }
@@ -1,38 +0,0 @@
1
- import type { ComponentProps } from 'react';
2
- import { colorClass, cx, sizeClass } from '../classes';
3
- import type { Color, Size } from '../types';
4
- import { useDefaults } from '../runtime';
5
-
6
-
7
- /** Props for {@link Spinner}. */
8
- export interface SpinnerProps extends Omit<ComponentProps<'span'>, 'color'> {
9
- /** Diameter from the size's `iconSize`, from the `sizes` config. Inherits the surrounding control's size when omitted. */
10
- size?: Size;
11
- /** Semantic color, from the `colors` config. Uses the current text color when omitted. */
12
- color?: Color;
13
- /**
14
- * Accessible label announced to screen readers.
15
- * @default 'Loading'
16
- */
17
- label?: string;
18
- }
19
-
20
- /**
21
- * An indeterminate loading indicator. Sized like an icon, so it fits inside controls of the same size.
22
- *
23
- * @example
24
- * ```tsx
25
- * <Spinner size="lg" color="brand" />
26
- * ```
27
- */
28
- export function Spinner({ size, color, label = 'Loading', className, ...props }: SpinnerProps) {
29
- const own = useDefaults('Spinner');
30
- return (
31
- <span
32
- role="status"
33
- aria-label={label}
34
- className={cx('yarcl-spinner', (size ?? own.size) && sizeClass(size ?? own.size), (color ?? own.color) && cx('yarcl-spinner-colored', colorClass(color ?? own.color)), className)}
35
- {...props}
36
- />
37
- );
38
- }
@@ -1,57 +0,0 @@
1
- import type { ComponentProps } from 'react';
2
- import { cx, gapClass } from '../classes';
3
- import type { Align, Justify, Spacing } from '../types';
4
- import { useDefaults } from '../runtime';
5
-
6
-
7
- /** Elements layout components can render as. */
8
- export type LayoutElement = 'div' | 'section' | 'article' | 'aside' | 'header' | 'footer' | 'main' | 'nav' | 'form' | 'ul' | 'ol';
9
-
10
- /** Props shared by {@link Stack} and {@link Inline}. */
11
- export interface LayoutProps extends ComponentProps<'div'> {
12
- /**
13
- * Element to render.
14
- * @default 'div'
15
- */
16
- as?: LayoutElement;
17
- /**
18
- * Space between children, from the `spacing` config.
19
- * @default config.defaults.gap
20
- */
21
- gap?: Spacing;
22
- /** Cross-axis alignment of children. */
23
- align?: Align;
24
- /** Main-axis distribution of children. */
25
- justify?: Justify;
26
- }
27
-
28
- /** Props for {@link Stack}. */
29
- export type StackProps = LayoutProps;
30
-
31
- /**
32
- * Lays out children vertically with a gap from the spacing scale.
33
- *
34
- * @example
35
- * ```tsx
36
- * <Stack gap="loose">
37
- * <Heading level={2}>Profile</Heading>
38
- * <Field label="Name"><Input /></Field>
39
- * </Stack>
40
- * ```
41
- */
42
- export function Stack({ as = 'div', gap, align, justify, className, ...props }: StackProps) {
43
- const own = useDefaults('Stack');
44
- const Tag = as as 'div';
45
- return (
46
- <Tag
47
- className={cx(
48
- 'yarcl-stack',
49
- gapClass(gap ?? own.gap),
50
- align && `yarcl-align-${align}`,
51
- justify && `yarcl-justify-${justify}`,
52
- className,
53
- )}
54
- {...props}
55
- />
56
- );
57
- }
@@ -1,42 +0,0 @@
1
- import type { ComponentProps, ReactNode } from 'react';
2
- import { colorClass, cx, sizeClass } from '../classes';
3
- import { useFieldProps } from '../field-context';
4
- import type { Color, Size } from '../types';
5
- import { useDefaults } from '../runtime';
6
-
7
-
8
- /** Props for {@link Switch}. Accepts all native `<input>` attributes except `type`, `color` and `size`. */
9
- export interface SwitchProps extends Omit<ComponentProps<'input'>, 'type' | 'color' | 'size' | 'children'> {
10
- /** Label shown next to the switch. */
11
- children?: ReactNode;
12
- /**
13
- * Switch size, from the `sizes` config (scaled from the size's `iconSize`).
14
- * @default config.defaults.size
15
- */
16
- size?: Size;
17
- /**
18
- * Track color when on, from the `colors` config.
19
- * @default config.defaults.color
20
- */
21
- color?: Color;
22
- }
23
-
24
- /**
25
- * An on/off toggle. A native checkbox with `role="switch"`, so `checked`,
26
- * `defaultChecked` and `onChange` work as usual.
27
- *
28
- * @example
29
- * ```tsx
30
- * <Switch defaultChecked>Notifications</Switch>
31
- * ```
32
- */
33
- export function Switch(props: SwitchProps) {
34
- const own = useDefaults('Switch');
35
- const { children, size, color, className, style, ...rest } = useFieldProps(props);
36
- return (
37
- <label className={cx('yarcl-switch', sizeClass(size ?? own.size), colorClass(color ?? own.color), className)} style={style}>
38
- <input type="checkbox" role="switch" className="yarcl-switch-input" {...rest} />
39
- {children != null && <span className="yarcl-switch-label">{children}</span>}
40
- </label>
41
- );
42
- }
@@ -1,99 +0,0 @@
1
- import type { ComponentProps, ReactNode } from 'react';
2
- import { cx, densityClass } from '../classes';
3
- import type { Density } from '../types';
4
- import { useDefaults } from '../runtime';
5
-
6
-
7
- /** Props for {@link Table}. */
8
- export interface TableProps extends ComponentProps<'table'> {
9
- /**
10
- * Cell padding and font size, from the `density` config.
11
- * @default config.defaults.density
12
- */
13
- density?: Density;
14
- /** Shades every other row. */
15
- striped?: boolean;
16
- /** Highlights the row under the pointer. Use when rows are clickable. */
17
- interactive?: boolean;
18
- /** Visible caption describing the table. Also its accessible name. */
19
- caption?: ReactNode;
20
- }
21
-
22
- function TableRoot({ density, striped, interactive, caption, className, children, ...props }: TableProps) {
23
- const own = useDefaults('Table');
24
- return (
25
- <div className="yarcl-table-wrap">
26
- <table
27
- className={cx(
28
- 'yarcl-table',
29
- densityClass(density ?? own.density),
30
- striped && 'yarcl-table-striped',
31
- interactive && 'yarcl-table-interactive',
32
- className,
33
- )}
34
- {...props}
35
- >
36
- {caption != null && <caption className="yarcl-table-caption">{caption}</caption>}
37
- {children}
38
- </table>
39
- </div>
40
- );
41
- }
42
-
43
- /** Horizontal alignment of a cell's content. `end` also uses tabular numbers, for numeric columns. */
44
- export type CellAlign = 'start' | 'center' | 'end';
45
-
46
- /** Props for `Table.HeaderCell`. */
47
- export interface TableHeaderCellProps extends Omit<ComponentProps<'th'>, 'align'> {
48
- /**
49
- * Content alignment.
50
- * @default 'start'
51
- */
52
- align?: CellAlign;
53
- }
54
-
55
- function TableHeaderCell({ align = 'start', scope = 'col', className, ...props }: TableHeaderCellProps) {
56
- return <th scope={scope} className={cx(`yarcl-cell-${align}`, className)} {...props} />;
57
- }
58
-
59
- /** Props for `Table.Cell`. */
60
- export interface TableCellProps extends Omit<ComponentProps<'td'>, 'align'> {
61
- /**
62
- * Content alignment.
63
- * @default 'start'
64
- */
65
- align?: CellAlign;
66
- }
67
-
68
- function TableCell({ align = 'start', className, ...props }: TableCellProps) {
69
- return <td className={cx(`yarcl-cell-${align}`, className)} {...props} />;
70
- }
71
-
72
- /**
73
- * A data table with density from the config. Scrolls horizontally when it doesn't fit.
74
- *
75
- * @example
76
- * ```tsx
77
- * <Table density="compact" striped caption="Invoices">
78
- * <Table.Head>
79
- * <Table.Row>
80
- * <Table.HeaderCell>Customer</Table.HeaderCell>
81
- * <Table.HeaderCell align="end">Amount</Table.HeaderCell>
82
- * </Table.Row>
83
- * </Table.Head>
84
- * <Table.Body>
85
- * <Table.Row>
86
- * <Table.Cell>Ada</Table.Cell>
87
- * <Table.Cell align="end">$120.00</Table.Cell>
88
- * </Table.Row>
89
- * </Table.Body>
90
- * </Table>
91
- * ```
92
- */
93
- export const Table = Object.assign(TableRoot, {
94
- Head: (props: ComponentProps<'thead'>) => <thead {...props} />,
95
- Body: (props: ComponentProps<'tbody'>) => <tbody {...props} />,
96
- Row: (props: ComponentProps<'tr'>) => <tr {...props} />,
97
- HeaderCell: TableHeaderCell,
98
- Cell: TableCell,
99
- });