@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.
- package/README.md +14 -2
- package/{src/apply.ts → dist/apply.d.ts} +4 -23
- package/dist/apply.js +37 -0
- package/dist/classes.d.ts +13 -0
- package/dist/classes.js +22 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +58 -0
- package/dist/color.js +49 -32
- package/dist/components/Accordion.d.ts +96 -0
- package/dist/components/Accordion.js +148 -0
- package/dist/components/Alert.d.ts +60 -0
- package/dist/components/Alert.js +61 -0
- package/dist/components/Avatar.d.ts +100 -0
- package/dist/components/Avatar.js +89 -0
- package/dist/components/Badge.d.ts +44 -0
- package/dist/components/Badge.js +43 -0
- package/dist/components/Breadcrumb.d.ts +77 -0
- package/dist/components/Breadcrumb.js +126 -0
- package/dist/components/Button.d.ts +18 -0
- package/dist/components/Button.js +33 -0
- package/dist/components/ButtonGroup.d.ts +29 -0
- package/dist/components/ButtonGroup.js +37 -0
- package/dist/components/Card.d.ts +36 -0
- package/dist/components/Card.js +26 -0
- package/dist/components/Checkbox.d.ts +28 -0
- package/dist/components/Checkbox.js +38 -0
- package/dist/components/Combobox.d.ts +75 -0
- package/dist/components/Combobox.js +362 -0
- package/dist/components/CommandPalette.d.ts +92 -0
- package/dist/components/CommandPalette.js +293 -0
- package/dist/components/DatePicker.d.ts +157 -0
- package/dist/components/DatePicker.js +230 -0
- package/dist/components/Dialog.d.ts +25 -0
- package/dist/components/Dialog.js +29 -0
- package/dist/components/Divider.d.ts +23 -0
- package/dist/components/Divider.js +25 -0
- package/dist/components/Drawer.d.ts +21 -0
- package/dist/components/Drawer.js +25 -0
- package/dist/components/EmptyState.d.ts +51 -0
- package/dist/components/EmptyState.js +47 -0
- package/dist/components/Field.d.ts +27 -0
- package/dist/components/Field.js +59 -0
- package/dist/components/Heading.d.ts +26 -0
- package/dist/components/Heading.js +25 -0
- package/dist/components/HoverCard.d.ts +47 -0
- package/dist/components/HoverCard.js +53 -0
- package/dist/components/IconButton.d.ts +19 -0
- package/dist/components/IconButton.js +32 -0
- package/dist/components/Inline.d.ts +21 -0
- package/dist/components/Inline.js +24 -0
- package/dist/components/Input.d.ts +19 -0
- package/dist/components/Input.js +25 -0
- package/dist/components/Label.d.ts +46 -0
- package/dist/components/Label.js +33 -0
- package/dist/components/Link.d.ts +27 -0
- package/dist/components/Link.js +26 -0
- package/dist/components/Menu.d.ts +73 -0
- package/dist/components/Menu.js +143 -0
- package/dist/components/Modal.d.ts +45 -0
- package/dist/components/Modal.js +110 -0
- package/dist/components/NumberInput.d.ts +49 -0
- package/dist/components/NumberInput.js +130 -0
- package/dist/components/Pagination.d.ts +86 -0
- package/dist/components/Pagination.js +119 -0
- package/dist/components/Popover.d.ts +72 -0
- package/dist/components/Popover.js +87 -0
- package/dist/components/Progress.d.ts +60 -0
- package/dist/components/Progress.js +59 -0
- package/dist/components/Radio.d.ts +32 -0
- package/dist/components/Radio.js +47 -0
- package/dist/components/RadioGroup.d.ts +57 -0
- package/dist/components/RadioGroup.js +68 -0
- package/dist/components/Select.d.ts +47 -0
- package/dist/components/Select.js +138 -0
- package/dist/components/Skeleton.d.ts +46 -0
- package/dist/components/Skeleton.js +40 -0
- package/dist/components/Slider.d.ts +126 -0
- package/dist/components/Slider.js +166 -0
- package/dist/components/Spinner.d.ts +23 -0
- package/dist/components/Spinner.js +23 -0
- package/dist/components/Stack.d.ts +35 -0
- package/dist/components/Stack.js +24 -0
- package/dist/components/Switch.d.ts +27 -0
- package/dist/components/Switch.js +33 -0
- package/dist/components/Table.d.ts +71 -0
- package/dist/components/Table.js +61 -0
- package/dist/components/Tabs.d.ts +66 -0
- package/dist/components/Tabs.js +109 -0
- package/dist/components/Text.d.ts +32 -0
- package/dist/components/Text.js +28 -0
- package/dist/components/Textarea.d.ts +15 -0
- package/dist/components/Textarea.js +24 -0
- package/dist/components/Toast.d.ts +90 -0
- package/dist/components/Toast.js +156 -0
- package/dist/components/ToggleGroup.d.ts +79 -0
- package/dist/components/ToggleGroup.js +101 -0
- package/dist/components/Tooltip.d.ts +46 -0
- package/dist/components/Tooltip.js +62 -0
- package/dist/components/VisuallyHidden.d.ts +18 -0
- package/dist/components/VisuallyHidden.js +22 -0
- package/dist/contrast.d.ts +32 -0
- package/dist/css.d.ts +2 -2
- package/dist/css.js +193 -157
- package/dist/define.d.ts +40 -15
- package/dist/define.js +30 -27
- package/dist/demo.d.ts +2 -0
- package/dist/demo.js +2 -0
- package/dist/esbuild.cjs +5 -0
- package/dist/esbuild.d.ts +4 -0
- package/dist/esbuild.js +6 -0
- package/dist/field-context.d.ts +16 -0
- package/dist/field-context.js +17 -0
- package/dist/floating.d.ts +12 -0
- package/dist/floating.js +52 -0
- package/dist/hooks.d.ts +1 -0
- package/dist/hooks.js +12 -0
- package/{src/index.ts → dist/index.d.ts} +11 -33
- package/dist/index.js +50 -0
- package/dist/init.d.ts +18 -0
- package/dist/init.js +224 -0
- package/dist/plugin.d.ts +10 -26
- package/dist/plugin.js +152 -78
- package/dist/reference/DemoYarcl.d.ts +12 -0
- package/dist/reference/DemoYarcl.js +312 -0
- package/dist/reference/DesignReference.d.ts +24 -0
- package/dist/reference/DesignReference.js +403 -0
- package/dist/reference/index.js +2 -0
- package/dist/rollup.cjs +5 -0
- package/dist/rollup.d.ts +4 -0
- package/dist/rollup.js +6 -0
- package/dist/rspack.cjs +5 -0
- package/dist/rspack.d.ts +4 -0
- package/dist/rspack.js +6 -0
- package/dist/runtime.d.ts +13 -0
- package/dist/runtime.js +30 -0
- package/dist/setup.d.ts +6 -0
- package/dist/setup.js +33 -0
- package/{src → dist}/styles.css +224 -106
- package/dist/themes/bloom.d.ts +295 -0
- package/dist/themes/bloom.js +202 -0
- package/dist/themes/brutalist.d.ts +277 -0
- package/dist/themes/brutalist.js +199 -0
- package/dist/themes/compact.d.ts +274 -0
- package/dist/themes/compact.js +200 -0
- package/dist/themes/contract.d.ts +23 -0
- package/dist/themes/editorial.d.ts +277 -0
- package/dist/themes/editorial.js +183 -0
- package/dist/themes/index.d.ts +1425 -0
- package/dist/themes/index.js +45 -0
- package/{src/types.ts → dist/types.d.ts} +40 -37
- package/dist/vite.cjs +5 -0
- package/dist/vite.d.ts +4 -0
- package/dist/vite.js +6 -0
- package/dist/webpack.cjs +5 -0
- package/dist/webpack.d.ts +4 -0
- package/dist/webpack.js +6 -0
- package/dist/yarcl.config.d.ts +276 -0
- package/dist/yarcl.config.js +273 -0
- package/package.json +69 -17
- package/src/classes.ts +0 -23
- package/src/color.ts +0 -48
- package/src/components/Accordion.tsx +0 -274
- package/src/components/Alert.tsx +0 -85
- package/src/components/Badge.tsx +0 -79
- package/src/components/Breadcrumb.tsx +0 -239
- package/src/components/Button.tsx +0 -58
- package/src/components/ButtonGroup.tsx +0 -61
- package/src/components/Card.tsx +0 -50
- package/src/components/Checkbox.tsx +0 -49
- package/src/components/Combobox.tsx +0 -522
- package/src/components/CommandPalette.tsx +0 -452
- package/src/components/DatePicker.tsx +0 -432
- package/src/components/Dialog.tsx +0 -39
- package/src/components/Divider.tsx +0 -34
- package/src/components/Drawer.tsx +0 -31
- package/src/components/Field.tsx +0 -61
- package/src/components/Heading.tsx +0 -40
- package/src/components/HoverCard.tsx +0 -108
- package/src/components/IconButton.tsx +0 -59
- package/src/components/Inline.tsx +0 -42
- package/src/components/Input.tsx +0 -28
- package/src/components/Label.tsx +0 -58
- package/src/components/Link.tsx +0 -41
- package/src/components/Menu.tsx +0 -207
- package/src/components/Modal.tsx +0 -164
- package/src/components/NumberInput.tsx +0 -208
- package/src/components/Pagination.tsx +0 -227
- package/src/components/Popover.tsx +0 -140
- package/src/components/Progress.tsx +0 -122
- package/src/components/Radio.tsx +0 -59
- package/src/components/RadioGroup.tsx +0 -114
- package/src/components/Select.tsx +0 -197
- package/src/components/Skeleton.tsx +0 -95
- package/src/components/Slider.tsx +0 -315
- package/src/components/Spinner.tsx +0 -38
- package/src/components/Stack.tsx +0 -57
- package/src/components/Switch.tsx +0 -42
- package/src/components/Table.tsx +0 -99
- package/src/components/Tabs.tsx +0 -159
- package/src/components/Text.tsx +0 -67
- package/src/components/Textarea.tsx +0 -26
- package/src/components/Toast.tsx +0 -190
- package/src/components/ToggleGroup.tsx +0 -227
- package/src/components/Tooltip.tsx +0 -78
- package/src/contrast.ts +0 -82
- package/src/css.ts +0 -228
- package/src/define.check.ts +0 -259
- package/src/define.ts +0 -379
- package/src/field-context.ts +0 -31
- package/src/floating.tsx +0 -61
- package/src/hooks.ts +0 -19
- package/src/plugin.ts +0 -94
- package/src/reference/DesignReference.tsx +0 -374
- package/src/runtime.ts +0 -38
- package/src/themes/bloom.ts +0 -72
- package/src/themes/brutalist.ts +0 -63
- package/src/themes/compact.ts +0 -63
- package/src/themes/contract.ts +0 -24
- package/src/themes/editorial.ts +0 -55
- package/src/themes/index.ts +0 -47
- package/src/yarcl.config.ts +0 -104
- /package/{src/reference/index.ts → dist/reference/index.d.ts} +0 -0
- /package/{src → dist}/reference/reference.css +0 -0
|
@@ -1,274 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createContext,
|
|
3
|
-
useContext,
|
|
4
|
-
useId,
|
|
5
|
-
type ComponentProps,
|
|
6
|
-
type KeyboardEvent,
|
|
7
|
-
type ReactNode,
|
|
8
|
-
} from 'react';
|
|
9
|
-
import { colorClass, cx, radiusClass, sizeClass } from '../classes';
|
|
10
|
-
import { ChevronIcon } from '../floating';
|
|
11
|
-
import { useControllable } from '../hooks';
|
|
12
|
-
import type { Color, Radius, Size } from '../types';
|
|
13
|
-
import { useDefaults } from '../runtime';
|
|
14
|
-
|
|
15
|
-
interface AccordionContextValue {
|
|
16
|
-
open: string[];
|
|
17
|
-
toggle: (value: string) => void;
|
|
18
|
-
disabled?: boolean;
|
|
19
|
-
idFor: (kind: 'trigger' | 'content', value: string) => string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
interface AccordionItemContextValue {
|
|
23
|
-
value: string;
|
|
24
|
-
open: boolean;
|
|
25
|
-
disabled?: boolean;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const AccordionContext = createContext<AccordionContextValue | null>(null);
|
|
29
|
-
const AccordionItemContext = createContext<AccordionItemContextValue | null>(null);
|
|
30
|
-
|
|
31
|
-
function useAccordionContext(component: string) {
|
|
32
|
-
const context = useContext(AccordionContext);
|
|
33
|
-
if (!context) throw new Error(`yarcl: <${component}> must be inside <Accordion>`);
|
|
34
|
-
return context;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function useItemContext(component: string) {
|
|
38
|
-
const context = useContext(AccordionItemContext);
|
|
39
|
-
if (!context) throw new Error(`yarcl: <${component}> must be inside <Accordion.Item>`);
|
|
40
|
-
return context;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/** Props shared by both forms of {@link AccordionProps}. */
|
|
44
|
-
export interface AccordionBaseProps extends Omit<ComponentProps<'div'>, 'defaultValue' | 'color'> {
|
|
45
|
-
/**
|
|
46
|
-
* Trigger height, padding and font size, from the `sizes` config.
|
|
47
|
-
* @default config.defaults.size
|
|
48
|
-
*/
|
|
49
|
-
size?: Size;
|
|
50
|
-
/**
|
|
51
|
-
* Corner radius of the outer frame, from the `radii` config, or `'size'` to match the size.
|
|
52
|
-
* @default config.defaults.radius
|
|
53
|
-
*/
|
|
54
|
-
radius?: Radius | 'size';
|
|
55
|
-
/**
|
|
56
|
-
* Color of the open item's indicator, from the `colors` config.
|
|
57
|
-
* @default config.defaults.color
|
|
58
|
-
*/
|
|
59
|
-
color?: Color;
|
|
60
|
-
/** Disables every item. */
|
|
61
|
-
disabled?: boolean;
|
|
62
|
-
/** `Accordion.Item`s. */
|
|
63
|
-
children?: ReactNode;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/** Props for {@link Accordion}. `type` decides whether one or many items can be open. */
|
|
67
|
-
export type AccordionProps = AccordionBaseProps &
|
|
68
|
-
(
|
|
69
|
-
| {
|
|
70
|
-
/** One item open at a time. */
|
|
71
|
-
type: 'single';
|
|
72
|
-
/** Open item (controlled), or `null` when all are closed. */
|
|
73
|
-
value?: string | null;
|
|
74
|
-
/** Initially open item (uncontrolled). */
|
|
75
|
-
defaultValue?: string | null;
|
|
76
|
-
/** Called with the open item, or `null` when it closes. */
|
|
77
|
-
onValueChange?: (value: string | null) => void;
|
|
78
|
-
/**
|
|
79
|
-
* Lets the open item close, leaving all closed. When `false`, one item always stays open.
|
|
80
|
-
* @default true
|
|
81
|
-
*/
|
|
82
|
-
collapsible?: boolean;
|
|
83
|
-
}
|
|
84
|
-
| {
|
|
85
|
-
/** Any number of items open. */
|
|
86
|
-
type: 'multiple';
|
|
87
|
-
/** Open items (controlled). */
|
|
88
|
-
value?: string[];
|
|
89
|
-
/** Initially open items (uncontrolled). */
|
|
90
|
-
defaultValue?: string[];
|
|
91
|
-
/** Called with all open items. */
|
|
92
|
-
onValueChange?: (value: string[]) => void;
|
|
93
|
-
collapsible?: never;
|
|
94
|
-
}
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
const toArray = (value: string | string[] | null | undefined) => (value == null ? [] : Array.isArray(value) ? value : [value]);
|
|
98
|
-
|
|
99
|
-
function AccordionRoot(props: AccordionProps) {
|
|
100
|
-
const own = useDefaults('Accordion');
|
|
101
|
-
const {
|
|
102
|
-
type,
|
|
103
|
-
value,
|
|
104
|
-
defaultValue,
|
|
105
|
-
onValueChange,
|
|
106
|
-
collapsible = true,
|
|
107
|
-
size,
|
|
108
|
-
radius,
|
|
109
|
-
color,
|
|
110
|
-
disabled,
|
|
111
|
-
className,
|
|
112
|
-
onKeyDown,
|
|
113
|
-
...rest
|
|
114
|
-
} = props;
|
|
115
|
-
|
|
116
|
-
const [open, setOpen] = useControllable<string[]>(
|
|
117
|
-
value === undefined ? undefined : toArray(value),
|
|
118
|
-
toArray(defaultValue),
|
|
119
|
-
(next) =>
|
|
120
|
-
type === 'multiple'
|
|
121
|
-
? (onValueChange as (v: string[]) => void)?.(next)
|
|
122
|
-
: (onValueChange as (v: string | null) => void)?.(next[0] ?? null),
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
const baseId = useId();
|
|
126
|
-
const idFor = (kind: 'trigger' | 'content', v: string) => `${baseId}-${kind}-${v.replace(/[^\w-]/g, '_')}`;
|
|
127
|
-
|
|
128
|
-
function toggle(item: string) {
|
|
129
|
-
const on = open.includes(item);
|
|
130
|
-
if (type === 'multiple') setOpen(on ? open.filter((v) => v !== item) : [...open, item]);
|
|
131
|
-
else if (!on) setOpen([item]);
|
|
132
|
-
else if (collapsible) setOpen([]);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function handleKeyDown(event: KeyboardEvent<HTMLDivElement>) {
|
|
136
|
-
onKeyDown?.(event);
|
|
137
|
-
const root = event.currentTarget;
|
|
138
|
-
const triggers = [...root.querySelectorAll<HTMLButtonElement>('.yarcl-accordion-trigger:not(:disabled)')].filter(
|
|
139
|
-
(trigger) => trigger.closest('.yarcl-accordion') === root,
|
|
140
|
-
);
|
|
141
|
-
const current = triggers.indexOf(document.activeElement as HTMLButtonElement);
|
|
142
|
-
if (current === -1) return;
|
|
143
|
-
const next = {
|
|
144
|
-
ArrowDown: (current + 1) % triggers.length,
|
|
145
|
-
ArrowUp: (current - 1 + triggers.length) % triggers.length,
|
|
146
|
-
Home: 0,
|
|
147
|
-
End: triggers.length - 1,
|
|
148
|
-
}[event.key];
|
|
149
|
-
if (next === undefined) return;
|
|
150
|
-
event.preventDefault();
|
|
151
|
-
triggers[next].focus();
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const resolvedSize = size ?? own.size;
|
|
155
|
-
return (
|
|
156
|
-
<AccordionContext.Provider value={{ open, toggle, disabled, idFor }}>
|
|
157
|
-
<div
|
|
158
|
-
className={cx(
|
|
159
|
-
'yarcl-accordion',
|
|
160
|
-
sizeClass(resolvedSize),
|
|
161
|
-
radiusClass(radius ?? own.radius, resolvedSize),
|
|
162
|
-
colorClass(color ?? own.color),
|
|
163
|
-
className,
|
|
164
|
-
)}
|
|
165
|
-
onKeyDown={handleKeyDown}
|
|
166
|
-
{...rest}
|
|
167
|
-
/>
|
|
168
|
-
</AccordionContext.Provider>
|
|
169
|
-
);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/** Props for `Accordion.Item`. */
|
|
173
|
-
export interface AccordionItemProps extends Omit<ComponentProps<'div'>, 'value'> {
|
|
174
|
-
/** Identifies the item in the accordion's value. */
|
|
175
|
-
value: string;
|
|
176
|
-
/** Prevents opening or closing this item. */
|
|
177
|
-
disabled?: boolean;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
function AccordionItem({ value, disabled, className, ...props }: AccordionItemProps) {
|
|
181
|
-
const context = useAccordionContext('Accordion.Item');
|
|
182
|
-
const open = context.open.includes(value);
|
|
183
|
-
const itemDisabled = disabled || context.disabled;
|
|
184
|
-
return (
|
|
185
|
-
<AccordionItemContext.Provider value={{ value, open, disabled: itemDisabled }}>
|
|
186
|
-
<div
|
|
187
|
-
data-state={open ? 'open' : 'closed'}
|
|
188
|
-
data-disabled={itemDisabled || undefined}
|
|
189
|
-
className={cx('yarcl-accordion-item', className)}
|
|
190
|
-
{...props}
|
|
191
|
-
/>
|
|
192
|
-
</AccordionItemContext.Provider>
|
|
193
|
-
);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/** Props for `Accordion.Trigger`. */
|
|
197
|
-
export interface AccordionTriggerProps extends ComponentProps<'button'> {
|
|
198
|
-
/**
|
|
199
|
-
* Level of the heading that wraps the button, to fit the page outline.
|
|
200
|
-
* @default 3
|
|
201
|
-
*/
|
|
202
|
-
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
function AccordionTrigger({ level = 3, className, onClick, children, ...props }: AccordionTriggerProps) {
|
|
206
|
-
const context = useAccordionContext('Accordion.Trigger');
|
|
207
|
-
const item = useItemContext('Accordion.Trigger');
|
|
208
|
-
const Heading = `h${level}` as 'h3';
|
|
209
|
-
return (
|
|
210
|
-
<Heading className="yarcl-accordion-heading">
|
|
211
|
-
<button
|
|
212
|
-
type="button"
|
|
213
|
-
id={context.idFor('trigger', item.value)}
|
|
214
|
-
aria-controls={context.idFor('content', item.value)}
|
|
215
|
-
aria-expanded={item.open}
|
|
216
|
-
disabled={item.disabled}
|
|
217
|
-
className={cx('yarcl-accordion-trigger', className)}
|
|
218
|
-
onClick={(event) => {
|
|
219
|
-
onClick?.(event);
|
|
220
|
-
if (!event.defaultPrevented) context.toggle(item.value);
|
|
221
|
-
}}
|
|
222
|
-
{...props}
|
|
223
|
-
>
|
|
224
|
-
<span className="yarcl-accordion-label">{children}</span>
|
|
225
|
-
<ChevronIcon />
|
|
226
|
-
</button>
|
|
227
|
-
</Heading>
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/** Props for `Accordion.Content`. */
|
|
232
|
-
export type AccordionContentProps = ComponentProps<'div'>;
|
|
233
|
-
|
|
234
|
-
function AccordionContent({ className, children, ...props }: AccordionContentProps) {
|
|
235
|
-
const context = useAccordionContext('Accordion.Content');
|
|
236
|
-
const item = useItemContext('Accordion.Content');
|
|
237
|
-
return (
|
|
238
|
-
<div
|
|
239
|
-
role="region"
|
|
240
|
-
id={context.idFor('content', item.value)}
|
|
241
|
-
aria-labelledby={context.idFor('trigger', item.value)}
|
|
242
|
-
data-state={item.open ? 'open' : 'closed'}
|
|
243
|
-
className={cx('yarcl-accordion-content', className)}
|
|
244
|
-
{...props}
|
|
245
|
-
>
|
|
246
|
-
<div className="yarcl-accordion-body">{children}</div>
|
|
247
|
-
</div>
|
|
248
|
-
);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Stacked sections that expand and collapse. Each trigger is a button inside a heading;
|
|
253
|
-
* Up and Down move between triggers, Home and End jump to the ends. The panel height animates
|
|
254
|
-
* with the `motion` tokens, and snaps when reduced motion is preferred.
|
|
255
|
-
*
|
|
256
|
-
* @example
|
|
257
|
-
* ```tsx
|
|
258
|
-
* <Accordion type="single" defaultValue="shipping">
|
|
259
|
-
* <Accordion.Item value="shipping">
|
|
260
|
-
* <Accordion.Trigger>Shipping</Accordion.Trigger>
|
|
261
|
-
* <Accordion.Content>Orders ship within two working days.</Accordion.Content>
|
|
262
|
-
* </Accordion.Item>
|
|
263
|
-
* <Accordion.Item value="returns">
|
|
264
|
-
* <Accordion.Trigger>Returns</Accordion.Trigger>
|
|
265
|
-
* <Accordion.Content>Free returns within 30 days.</Accordion.Content>
|
|
266
|
-
* </Accordion.Item>
|
|
267
|
-
* </Accordion>
|
|
268
|
-
* ```
|
|
269
|
-
*/
|
|
270
|
-
export const Accordion = Object.assign(AccordionRoot, {
|
|
271
|
-
Item: AccordionItem,
|
|
272
|
-
Trigger: AccordionTrigger,
|
|
273
|
-
Content: AccordionContent,
|
|
274
|
-
});
|
package/src/components/Alert.tsx
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import type { ComponentProps, ReactNode } from 'react';
|
|
2
|
-
import { colorClass, cx, radiusClass, softVariantClass } from '../classes';
|
|
3
|
-
import type { Color, Radius, Variant } from '../types';
|
|
4
|
-
import { useDefaults } from '../runtime';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
/** Props for {@link Alert}. */
|
|
8
|
-
export interface AlertProps extends Omit<ComponentProps<'div'>, 'color' | 'title'> {
|
|
9
|
-
/** Bold first line. */
|
|
10
|
-
title?: ReactNode;
|
|
11
|
-
/** Icon shown before the text. */
|
|
12
|
-
icon?: ReactNode;
|
|
13
|
-
/** Actions shown after the text, e.g. a {@link Button} or {@link Link}. */
|
|
14
|
-
action?: ReactNode;
|
|
15
|
-
/**
|
|
16
|
-
* Semantic color, from the `colors` config.
|
|
17
|
-
* @default config.defaults.color
|
|
18
|
-
*/
|
|
19
|
-
color?: Color;
|
|
20
|
-
/**
|
|
21
|
-
* Style recipe, from the `variants` config.
|
|
22
|
-
* @default config.defaults.softVariant
|
|
23
|
-
*/
|
|
24
|
-
variant?: Variant;
|
|
25
|
-
/**
|
|
26
|
-
* Corner radius, from the `radii` config.
|
|
27
|
-
* @default config.defaults.radius
|
|
28
|
-
*/
|
|
29
|
-
radius?: Radius;
|
|
30
|
-
/** Shows a dismiss button. Called when it is pressed; hide the alert in response. */
|
|
31
|
-
onDismiss?: () => void;
|
|
32
|
-
/**
|
|
33
|
-
* Announces the alert when it appears: `'polite'` (`role="status"`) or `'assertive'` (`role="alert"`).
|
|
34
|
-
* Leave unset for messages present on page load.
|
|
35
|
-
*/
|
|
36
|
-
live?: 'polite' | 'assertive';
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* An inline message that stays on the page, e.g. a warning above a form.
|
|
41
|
-
* For transient messages use {@link toast}.
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* ```tsx
|
|
45
|
-
* <Alert color="warning" title="Trial ends in 3 days" action={<Button size="sm">Upgrade</Button>}>
|
|
46
|
-
* Add a payment method to keep your projects.
|
|
47
|
-
* </Alert>
|
|
48
|
-
* ```
|
|
49
|
-
*/
|
|
50
|
-
export function Alert({
|
|
51
|
-
title,
|
|
52
|
-
icon,
|
|
53
|
-
action,
|
|
54
|
-
color,
|
|
55
|
-
variant,
|
|
56
|
-
radius,
|
|
57
|
-
onDismiss,
|
|
58
|
-
live,
|
|
59
|
-
className,
|
|
60
|
-
children,
|
|
61
|
-
...props
|
|
62
|
-
}: AlertProps) {
|
|
63
|
-
const own = useDefaults('Alert');
|
|
64
|
-
return (
|
|
65
|
-
<div
|
|
66
|
-
role={live === 'assertive' ? 'alert' : live === 'polite' ? 'status' : undefined}
|
|
67
|
-
className={cx('yarcl-alert', colorClass(color ?? own.color), softVariantClass(variant ?? own.variant), radiusClass(radius ?? own.radius), className)}
|
|
68
|
-
{...props}
|
|
69
|
-
>
|
|
70
|
-
{icon != null && <span className="yarcl-alert-icon">{icon}</span>}
|
|
71
|
-
<div className="yarcl-alert-text">
|
|
72
|
-
{title != null && <div className="yarcl-alert-title">{title}</div>}
|
|
73
|
-
{children != null && <div className="yarcl-alert-body">{children}</div>}
|
|
74
|
-
</div>
|
|
75
|
-
{action != null && <div className="yarcl-alert-action">{action}</div>}
|
|
76
|
-
{onDismiss && (
|
|
77
|
-
<button type="button" className="yarcl-alert-dismiss" aria-label="Dismiss" onClick={onDismiss}>
|
|
78
|
-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" aria-hidden="true">
|
|
79
|
-
<path d="M6 6l12 12M18 6 6 18" />
|
|
80
|
-
</svg>
|
|
81
|
-
</button>
|
|
82
|
-
)}
|
|
83
|
-
</div>
|
|
84
|
-
);
|
|
85
|
-
}
|
package/src/components/Badge.tsx
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import type { ComponentProps } from 'react';
|
|
2
|
-
import { colorClass, cx, radiusClass, sizeClass, softVariantClass } from '../classes';
|
|
3
|
-
import type { Color, Radius, Size, Variant } from '../types';
|
|
4
|
-
import { useDefaults } from '../runtime';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
/** Props for {@link Badge}. */
|
|
8
|
-
export interface BadgeProps extends Omit<ComponentProps<'span'>, 'color'> {
|
|
9
|
-
/**
|
|
10
|
-
* Semantic color, from the `colors` config.
|
|
11
|
-
* @default config.defaults.color
|
|
12
|
-
*/
|
|
13
|
-
color?: Color;
|
|
14
|
-
/**
|
|
15
|
-
* Style recipe, from the `variants` config.
|
|
16
|
-
* @default config.defaults.softVariant
|
|
17
|
-
*/
|
|
18
|
-
variant?: Variant;
|
|
19
|
-
/**
|
|
20
|
-
* Scales with the size's font size, from the `sizes` config.
|
|
21
|
-
* @default config.defaults.size
|
|
22
|
-
*/
|
|
23
|
-
size?: Size;
|
|
24
|
-
/**
|
|
25
|
-
* Corner radius, from the `radii` config.
|
|
26
|
-
* @default config.defaults.radius
|
|
27
|
-
*/
|
|
28
|
-
radius?: Radius | 'size';
|
|
29
|
-
/** Shows a remove button, making the badge a removable tag. Called when it is pressed. */
|
|
30
|
-
onRemove?: () => void;
|
|
31
|
-
/**
|
|
32
|
-
* Accessible label of the remove button.
|
|
33
|
-
* @default 'Remove'
|
|
34
|
-
*/
|
|
35
|
-
removeLabel?: string;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* A small label for status, counts or categories. With `onRemove`, a removable tag.
|
|
40
|
-
* Uses the same variant recipes as {@link Button}.
|
|
41
|
-
*
|
|
42
|
-
* @example
|
|
43
|
-
* ```tsx
|
|
44
|
-
* <Badge color="success">Active</Badge>
|
|
45
|
-
* <Badge onRemove={() => removeTag('react')}>react</Badge>
|
|
46
|
-
* ```
|
|
47
|
-
*/
|
|
48
|
-
export function Badge({
|
|
49
|
-
color,
|
|
50
|
-
variant,
|
|
51
|
-
size,
|
|
52
|
-
radius,
|
|
53
|
-
onRemove,
|
|
54
|
-
removeLabel = 'Remove',
|
|
55
|
-
className,
|
|
56
|
-
children,
|
|
57
|
-
...props
|
|
58
|
-
}: BadgeProps) {
|
|
59
|
-
const own = useDefaults('Badge');
|
|
60
|
-
return (
|
|
61
|
-
<span
|
|
62
|
-
className={cx('yarcl-badge', colorClass(color ?? own.color), softVariantClass(variant ?? own.variant), sizeClass(size ?? own.size), radiusClass(radius ?? own.radius, size ?? own.size), className)}
|
|
63
|
-
{...props}
|
|
64
|
-
>
|
|
65
|
-
{children}
|
|
66
|
-
{onRemove && <BadgeRemove aria-label={removeLabel} onClick={onRemove} />}
|
|
67
|
-
</span>
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export function BadgeRemove(props: Omit<ComponentProps<'button'>, 'children'>) {
|
|
72
|
-
return (
|
|
73
|
-
<button type="button" className="yarcl-badge-remove" {...props}>
|
|
74
|
-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" aria-hidden="true">
|
|
75
|
-
<path d="M7 7l10 10M17 7 7 17" />
|
|
76
|
-
</svg>
|
|
77
|
-
</button>
|
|
78
|
-
);
|
|
79
|
-
}
|
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Children,
|
|
3
|
-
createContext,
|
|
4
|
-
isValidElement,
|
|
5
|
-
useContext,
|
|
6
|
-
useRef,
|
|
7
|
-
useState,
|
|
8
|
-
type ComponentProps,
|
|
9
|
-
type ReactNode,
|
|
10
|
-
} from 'react';
|
|
11
|
-
import { colorClass, cx, typeClass } from '../classes';
|
|
12
|
-
import type { Color, TextStyle } from '../types';
|
|
13
|
-
import { useConfig, useDefaults } from '../runtime';
|
|
14
|
-
import type { LinkProps } from './Link';
|
|
15
|
-
|
|
16
|
-
interface BreadcrumbItemContextValue {
|
|
17
|
-
current: boolean;
|
|
18
|
-
separator: ReactNode;
|
|
19
|
-
color: Color;
|
|
20
|
-
underline: NonNullable<LinkProps['underline']>;
|
|
21
|
-
itemRef?: (node: HTMLElement | null) => void;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const BreadcrumbItemContext = createContext<BreadcrumbItemContextValue | null>(null);
|
|
25
|
-
|
|
26
|
-
function ChevronIcon() {
|
|
27
|
-
return (
|
|
28
|
-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
|
29
|
-
<path d="m9 6 6 6-6 6" />
|
|
30
|
-
</svg>
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function Separator({ children }: { children: ReactNode }) {
|
|
35
|
-
return (
|
|
36
|
-
<span className="yarcl-breadcrumb-separator" aria-hidden="true">
|
|
37
|
-
{children}
|
|
38
|
-
</span>
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/** Props for {@link Breadcrumb}. Accepts all native `<nav>` attributes except `color`. */
|
|
43
|
-
export interface BreadcrumbProps extends Omit<ComponentProps<'nav'>, 'color'> {
|
|
44
|
-
/** `Breadcrumb.Item`s, from the root to the current page. */
|
|
45
|
-
children?: ReactNode;
|
|
46
|
-
/**
|
|
47
|
-
* Content between items. Hidden from screen readers.
|
|
48
|
-
* @default a chevron icon
|
|
49
|
-
* @example
|
|
50
|
-
* ```tsx
|
|
51
|
-
* <Breadcrumb separator="/">…</Breadcrumb>
|
|
52
|
-
* ```
|
|
53
|
-
*/
|
|
54
|
-
separator?: ReactNode;
|
|
55
|
-
/** Collapses the middle of the trail into an expandable ellipsis when there are more items than this. Without it, the trail never collapses. */
|
|
56
|
-
maxItems?: number;
|
|
57
|
-
/**
|
|
58
|
-
* Items shown before the ellipsis when collapsed.
|
|
59
|
-
* @default 1
|
|
60
|
-
*/
|
|
61
|
-
itemsBeforeCollapse?: number;
|
|
62
|
-
/**
|
|
63
|
-
* Items shown after the ellipsis when collapsed.
|
|
64
|
-
* @default 2
|
|
65
|
-
*/
|
|
66
|
-
itemsAfterCollapse?: number;
|
|
67
|
-
/**
|
|
68
|
-
* Accessible label of the ellipsis button.
|
|
69
|
-
* @default 'Show all breadcrumbs'
|
|
70
|
-
*/
|
|
71
|
-
expandLabel?: string;
|
|
72
|
-
/**
|
|
73
|
-
* Text style, from the `typography.styles` config.
|
|
74
|
-
* @default config.defaults.textStyle
|
|
75
|
-
*/
|
|
76
|
-
textStyle?: TextStyle;
|
|
77
|
-
/**
|
|
78
|
-
* Link color, from the `colors` config.
|
|
79
|
-
* @default config.defaults.color
|
|
80
|
-
*/
|
|
81
|
-
color?: Color;
|
|
82
|
-
/**
|
|
83
|
-
* When to underline the links.
|
|
84
|
-
* @default 'hover'
|
|
85
|
-
*/
|
|
86
|
-
underline?: LinkProps['underline'];
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function BreadcrumbRoot({
|
|
90
|
-
children,
|
|
91
|
-
separator = <ChevronIcon />,
|
|
92
|
-
maxItems,
|
|
93
|
-
itemsBeforeCollapse = 1,
|
|
94
|
-
itemsAfterCollapse = 2,
|
|
95
|
-
expandLabel = 'Show all breadcrumbs',
|
|
96
|
-
textStyle,
|
|
97
|
-
color,
|
|
98
|
-
underline = 'hover',
|
|
99
|
-
className,
|
|
100
|
-
'aria-label': ariaLabel = 'Breadcrumb',
|
|
101
|
-
...props
|
|
102
|
-
}: BreadcrumbProps) {
|
|
103
|
-
const config = useConfig();
|
|
104
|
-
const own = useDefaults('Breadcrumb');
|
|
105
|
-
const [expanded, setExpanded] = useState(false);
|
|
106
|
-
const focusNext = useRef(false);
|
|
107
|
-
const items = Children.toArray(children).filter(isValidElement);
|
|
108
|
-
const resolvedColor = color ?? own.color ?? config.defaults.color;
|
|
109
|
-
const before = Math.max(0, itemsBeforeCollapse);
|
|
110
|
-
const after = Math.max(1, itemsAfterCollapse);
|
|
111
|
-
const collapsible = maxItems !== undefined && items.length > maxItems && before + after < items.length;
|
|
112
|
-
const collapsed = collapsible && !expanded;
|
|
113
|
-
const hiddenEnd = items.length - after;
|
|
114
|
-
|
|
115
|
-
const context = (index: number): BreadcrumbItemContextValue => ({
|
|
116
|
-
current: index === items.length - 1,
|
|
117
|
-
separator,
|
|
118
|
-
color: resolvedColor,
|
|
119
|
-
underline,
|
|
120
|
-
itemRef:
|
|
121
|
-
collapsible && index === before
|
|
122
|
-
? (node) => {
|
|
123
|
-
if (node && focusNext.current) {
|
|
124
|
-
focusNext.current = false;
|
|
125
|
-
node.focus();
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
: undefined,
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
const rendered: ReactNode[] = [];
|
|
132
|
-
items.forEach((item, index) => {
|
|
133
|
-
if (collapsed && index >= before && index < hiddenEnd) {
|
|
134
|
-
if (index === before) {
|
|
135
|
-
rendered.push(
|
|
136
|
-
<li key="yarcl-breadcrumb-ellipsis" className="yarcl-breadcrumb-item">
|
|
137
|
-
<button
|
|
138
|
-
type="button"
|
|
139
|
-
className="yarcl-breadcrumb-ellipsis"
|
|
140
|
-
aria-label={expandLabel}
|
|
141
|
-
onClick={() => {
|
|
142
|
-
focusNext.current = true;
|
|
143
|
-
setExpanded(true);
|
|
144
|
-
}}
|
|
145
|
-
>
|
|
146
|
-
<span aria-hidden="true">…</span>
|
|
147
|
-
</button>
|
|
148
|
-
<Separator>{separator}</Separator>
|
|
149
|
-
</li>,
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
rendered.push(
|
|
155
|
-
<BreadcrumbItemContext.Provider key={item.key ?? index} value={context(index)}>
|
|
156
|
-
{item}
|
|
157
|
-
</BreadcrumbItemContext.Provider>,
|
|
158
|
-
);
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
return (
|
|
162
|
-
<nav
|
|
163
|
-
aria-label={ariaLabel}
|
|
164
|
-
className={cx(
|
|
165
|
-
'yarcl-breadcrumb',
|
|
166
|
-
typeClass(textStyle ?? own.textStyle ?? config.defaults.textStyle),
|
|
167
|
-
colorClass(resolvedColor),
|
|
168
|
-
className,
|
|
169
|
-
)}
|
|
170
|
-
{...props}
|
|
171
|
-
>
|
|
172
|
-
<ol className="yarcl-breadcrumb-list">{rendered}</ol>
|
|
173
|
-
</nav>
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/** Props for `Breadcrumb.Item`. Accepts all native `<a>` attributes except `color`. */
|
|
178
|
-
export interface BreadcrumbItemProps extends Omit<ComponentProps<'a'>, 'color'> {
|
|
179
|
-
/** The item's label. */
|
|
180
|
-
children?: ReactNode;
|
|
181
|
-
/** Where the item links to. Without it, the item renders as plain text. */
|
|
182
|
-
href?: string;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function BreadcrumbItem({ href, className, children, ...props }: BreadcrumbItemProps) {
|
|
186
|
-
const context = useContext(BreadcrumbItemContext);
|
|
187
|
-
if (!context) throw new Error('yarcl: <Breadcrumb.Item> must be inside <Breadcrumb>');
|
|
188
|
-
const { current, separator, color, underline, itemRef } = context;
|
|
189
|
-
return (
|
|
190
|
-
<li className="yarcl-breadcrumb-item">
|
|
191
|
-
{href ? (
|
|
192
|
-
<a
|
|
193
|
-
ref={itemRef}
|
|
194
|
-
href={href}
|
|
195
|
-
aria-current={current ? 'page' : undefined}
|
|
196
|
-
className={cx(
|
|
197
|
-
'yarcl-link',
|
|
198
|
-
current ? 'yarcl-breadcrumb-current yarcl-link-underline-none' : `yarcl-link-underline-${underline}`,
|
|
199
|
-
colorClass(color),
|
|
200
|
-
className,
|
|
201
|
-
)}
|
|
202
|
-
{...props}
|
|
203
|
-
>
|
|
204
|
-
{children}
|
|
205
|
-
</a>
|
|
206
|
-
) : (
|
|
207
|
-
<span
|
|
208
|
-
ref={itemRef}
|
|
209
|
-
tabIndex={itemRef ? -1 : undefined}
|
|
210
|
-
aria-current={current ? 'page' : undefined}
|
|
211
|
-
className={cx('yarcl-breadcrumb-text', current && 'yarcl-breadcrumb-current', className)}
|
|
212
|
-
{...(props as ComponentProps<'span'>)}
|
|
213
|
-
>
|
|
214
|
-
{children}
|
|
215
|
-
</span>
|
|
216
|
-
)}
|
|
217
|
-
{!current && <Separator>{separator}</Separator>}
|
|
218
|
-
</li>
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Shows where the current page sits in a hierarchy. The last item is the current page
|
|
224
|
-
* and gets `aria-current="page"`. Set `maxItems` to collapse long trails into an ellipsis
|
|
225
|
-
* that expands the full trail.
|
|
226
|
-
*
|
|
227
|
-
* @example
|
|
228
|
-
* ```tsx
|
|
229
|
-
* <Breadcrumb maxItems={4}>
|
|
230
|
-
* <Breadcrumb.Item href="/">Home</Breadcrumb.Item>
|
|
231
|
-
* <Breadcrumb.Item href="/projects">Projects</Breadcrumb.Item>
|
|
232
|
-
* <Breadcrumb.Item href="/projects/apollo">Apollo</Breadcrumb.Item>
|
|
233
|
-
* <Breadcrumb.Item>Settings</Breadcrumb.Item>
|
|
234
|
-
* </Breadcrumb>
|
|
235
|
-
* ```
|
|
236
|
-
*/
|
|
237
|
-
export const Breadcrumb = Object.assign(BreadcrumbRoot, {
|
|
238
|
-
Item: BreadcrumbItem,
|
|
239
|
-
});
|