@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,108 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
autoUpdate,
|
|
3
|
-
FloatingPortal,
|
|
4
|
-
safePolygon,
|
|
5
|
-
useDismiss,
|
|
6
|
-
useFloating,
|
|
7
|
-
useFocus,
|
|
8
|
-
useHover,
|
|
9
|
-
useInteractions,
|
|
10
|
-
type Placement,
|
|
11
|
-
} from '@floating-ui/react';
|
|
12
|
-
import { useState, type ReactElement, type ReactNode } from 'react';
|
|
13
|
-
import { cx, paddingClass, radiusClass } from '../classes';
|
|
14
|
-
import { floatingMiddleware, useTrigger } from '../floating';
|
|
15
|
-
import type { Radius, Spacing } from '../types';
|
|
16
|
-
import { useConfig, useDefaults } from '../runtime';
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
/** Props for {@link HoverCard}. */
|
|
20
|
-
export interface HoverCardProps {
|
|
21
|
-
/** Rich preview content. Can contain links; the pointer can move into the card without closing it. */
|
|
22
|
-
content: ReactNode;
|
|
23
|
-
/** A single focusable element, usually a {@link Link}. */
|
|
24
|
-
children: ReactElement;
|
|
25
|
-
/**
|
|
26
|
-
* Preferred side. Flips when there isn't room.
|
|
27
|
-
* @default 'bottom'
|
|
28
|
-
*/
|
|
29
|
-
placement?: Placement;
|
|
30
|
-
/**
|
|
31
|
-
* Delay before opening, in ms.
|
|
32
|
-
* @default config.timing.hoverOpenDelay
|
|
33
|
-
*/
|
|
34
|
-
openDelay?: number;
|
|
35
|
-
/**
|
|
36
|
-
* Delay before closing after the pointer leaves, in ms.
|
|
37
|
-
* @default config.timing.hoverCloseDelay
|
|
38
|
-
*/
|
|
39
|
-
closeDelay?: number;
|
|
40
|
-
/**
|
|
41
|
-
* Inner padding, from the `spacing` config.
|
|
42
|
-
* @default config.defaults.padding
|
|
43
|
-
*/
|
|
44
|
-
padding?: Spacing;
|
|
45
|
-
/**
|
|
46
|
-
* Corner radius, from the `radii` config.
|
|
47
|
-
* @default config.defaults.radius
|
|
48
|
-
*/
|
|
49
|
-
radius?: Radius;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* A preview card shown on hover or focus, e.g. for a user or a link.
|
|
54
|
-
* Supplementary only: don't put content here that isn't reachable elsewhere.
|
|
55
|
-
*
|
|
56
|
-
* @example
|
|
57
|
-
* ```tsx
|
|
58
|
-
* <HoverCard content={<UserPreview id="ada" />}>
|
|
59
|
-
* <Link href="/users/ada">@ada</Link>
|
|
60
|
-
* </HoverCard>
|
|
61
|
-
* ```
|
|
62
|
-
*/
|
|
63
|
-
export function HoverCard({
|
|
64
|
-
content,
|
|
65
|
-
children,
|
|
66
|
-
placement = 'bottom',
|
|
67
|
-
openDelay,
|
|
68
|
-
closeDelay,
|
|
69
|
-
padding,
|
|
70
|
-
radius,
|
|
71
|
-
}: HoverCardProps) {
|
|
72
|
-
const own = useDefaults('HoverCard');
|
|
73
|
-
const config = useConfig();
|
|
74
|
-
const delay = { open: openDelay ?? config.timing.hoverOpenDelay, close: closeDelay ?? config.timing.hoverCloseDelay };
|
|
75
|
-
const [open, setOpen] = useState(false);
|
|
76
|
-
const { refs, floatingStyles, context } = useFloating({
|
|
77
|
-
open,
|
|
78
|
-
onOpenChange: setOpen,
|
|
79
|
-
placement,
|
|
80
|
-
transform: false,
|
|
81
|
-
whileElementsMounted: autoUpdate,
|
|
82
|
-
middleware: floatingMiddleware({ gap: 8 }),
|
|
83
|
-
});
|
|
84
|
-
const { getReferenceProps, getFloatingProps } = useInteractions([
|
|
85
|
-
useHover(context, { delay, handleClose: safePolygon() }),
|
|
86
|
-
useFocus(context),
|
|
87
|
-
useDismiss(context),
|
|
88
|
-
]);
|
|
89
|
-
const trigger = useTrigger(children, refs.setReference, getReferenceProps);
|
|
90
|
-
|
|
91
|
-
return (
|
|
92
|
-
<>
|
|
93
|
-
{trigger}
|
|
94
|
-
{open && (
|
|
95
|
-
<FloatingPortal>
|
|
96
|
-
<div
|
|
97
|
-
ref={refs.setFloating}
|
|
98
|
-
style={floatingStyles}
|
|
99
|
-
className={cx('yarcl-floating yarcl-panel yarcl-hover-card', paddingClass(padding ?? own.padding), radiusClass(radius ?? own.radius))}
|
|
100
|
-
{...getFloatingProps()}
|
|
101
|
-
>
|
|
102
|
-
{content}
|
|
103
|
-
</div>
|
|
104
|
-
</FloatingPortal>
|
|
105
|
-
)}
|
|
106
|
-
</>
|
|
107
|
-
);
|
|
108
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import type { ComponentProps } from 'react';
|
|
2
|
-
import { colorClass, cx, radiusClass, sizeClass, variantClass } from '../classes';
|
|
3
|
-
import type { TokenProps, VariantProps } from '../types';
|
|
4
|
-
import { useButtonGroup } from './ButtonGroup';
|
|
5
|
-
import { Spinner } from './Spinner';
|
|
6
|
-
import { useDefaults } from '../runtime';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/** Props for {@link IconButton}. `aria-label` is required because the button has no visible text. */
|
|
10
|
-
export interface IconButtonProps extends Omit<ComponentProps<'button'>, 'color'>, TokenProps, VariantProps {
|
|
11
|
-
/** Shows a {@link Spinner}, disables the button and sets `aria-busy`. */
|
|
12
|
-
loading?: boolean;
|
|
13
|
-
/** Accessible name, announced by screen readers in place of visible text. */
|
|
14
|
-
'aria-label': string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* A square button containing only an icon.
|
|
19
|
-
* Width equals the control height, so it lines up with {@link Button} and {@link Input} of the same size.
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* ```tsx
|
|
23
|
-
* <IconButton aria-label="Search" variant="ghost"><SearchIcon /></IconButton>
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
export function IconButton({
|
|
27
|
-
size,
|
|
28
|
-
radius,
|
|
29
|
-
color,
|
|
30
|
-
variant,
|
|
31
|
-
loading,
|
|
32
|
-
disabled,
|
|
33
|
-
className,
|
|
34
|
-
type = 'button',
|
|
35
|
-
children,
|
|
36
|
-
...props
|
|
37
|
-
}: IconButtonProps) {
|
|
38
|
-
const own = useDefaults('IconButton');
|
|
39
|
-
const group = useButtonGroup();
|
|
40
|
-
return (
|
|
41
|
-
<button
|
|
42
|
-
type={type}
|
|
43
|
-
className={cx(
|
|
44
|
-
'yarcl-button yarcl-icon-button',
|
|
45
|
-
sizeClass(size ?? group?.size ?? own.size),
|
|
46
|
-
radiusClass(radius ?? group?.radius ?? own.radius, size ?? group?.size ?? own.size),
|
|
47
|
-
colorClass(color ?? group?.color ?? own.color),
|
|
48
|
-
variantClass(variant ?? group?.variant ?? own.variant),
|
|
49
|
-
className,
|
|
50
|
-
)}
|
|
51
|
-
disabled={disabled || loading}
|
|
52
|
-
aria-busy={loading || undefined}
|
|
53
|
-
{...props}
|
|
54
|
-
>
|
|
55
|
-
{loading && <Spinner label="" aria-hidden="true" />}
|
|
56
|
-
{!loading && children}
|
|
57
|
-
</button>
|
|
58
|
-
);
|
|
59
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { cx, gapClass } from '../classes';
|
|
2
|
-
import type { LayoutProps } from './Stack';
|
|
3
|
-
import { useDefaults } from '../runtime';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
/** Props for {@link Inline}. */
|
|
7
|
-
export interface InlineProps extends LayoutProps {
|
|
8
|
-
/**
|
|
9
|
-
* Wraps children onto new lines when they don't fit.
|
|
10
|
-
* @default true
|
|
11
|
-
*/
|
|
12
|
-
wrap?: boolean;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Lays out children horizontally with a gap from the spacing scale. Centers children vertically by default.
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```tsx
|
|
20
|
-
* <Inline gap="tight" justify="end">
|
|
21
|
-
* <Button variant="outline">Cancel</Button>
|
|
22
|
-
* <Button>Save</Button>
|
|
23
|
-
* </Inline>
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
export function Inline({ as = 'div', gap, align = 'center', justify, wrap = true, className, ...props }: InlineProps) {
|
|
27
|
-
const own = useDefaults('Inline');
|
|
28
|
-
const Tag = as as 'div';
|
|
29
|
-
return (
|
|
30
|
-
<Tag
|
|
31
|
-
className={cx(
|
|
32
|
-
'yarcl-inline',
|
|
33
|
-
gapClass(gap ?? own.gap),
|
|
34
|
-
`yarcl-align-${align}`,
|
|
35
|
-
justify && `yarcl-justify-${justify}`,
|
|
36
|
-
!wrap && 'yarcl-inline-nowrap',
|
|
37
|
-
className,
|
|
38
|
-
)}
|
|
39
|
-
{...props}
|
|
40
|
-
/>
|
|
41
|
-
);
|
|
42
|
-
}
|
package/src/components/Input.tsx
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { ComponentProps } from 'react';
|
|
2
|
-
import { colorClass, cx, radiusClass, sizeClass } from '../classes';
|
|
3
|
-
import { useFieldProps } from '../field-context';
|
|
4
|
-
import type { TokenProps } from '../types';
|
|
5
|
-
import { useDefaults } from '../runtime';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Props for {@link Input}. Accepts all native `<input>` attributes except
|
|
10
|
-
* `color` and `size`, which are replaced by design tokens.
|
|
11
|
-
*/
|
|
12
|
-
export interface InputProps extends Omit<ComponentProps<'input'>, 'color' | 'size'>, TokenProps {}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* A text input styled from the consumer's design tokens.
|
|
16
|
-
* Shares the size scale with {@link Button}, so both have the same height at the same size.
|
|
17
|
-
* `color` sets the focus border and ring. Inside a {@link Field}, it is labelled and described automatically.
|
|
18
|
-
*
|
|
19
|
-
* @example
|
|
20
|
-
* ```tsx
|
|
21
|
-
* <Input size="lg" placeholder="Email" />
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
24
|
-
export function Input(props: InputProps) {
|
|
25
|
-
const own = useDefaults('Input');
|
|
26
|
-
const { size, radius, color, className, ...rest } = useFieldProps(props);
|
|
27
|
-
return <input className={cx('yarcl-input', sizeClass(size ?? own.size), radiusClass(radius ?? own.radius, size ?? own.size), colorClass(color ?? own.color), className)} {...rest} />;
|
|
28
|
-
}
|
package/src/components/Label.tsx
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import type { ComponentProps } from 'react';
|
|
2
|
-
import { colorClass, cx, typeClass } from '../classes';
|
|
3
|
-
import type { Color, TextStyle } from '../types';
|
|
4
|
-
import { useConfig, useDefaults } from '../runtime';
|
|
5
|
-
|
|
6
|
-
/** Props for {@link Label}. */
|
|
7
|
-
export interface LabelProps extends Omit<ComponentProps<'label'>, 'color'> {
|
|
8
|
-
/**
|
|
9
|
-
* Text style, from the `typography.styles` config.
|
|
10
|
-
* @default config.defaults.labelStyle
|
|
11
|
-
*/
|
|
12
|
-
textStyle?: TextStyle;
|
|
13
|
-
/** Semantic color, from the `colors` config. Uses the default text color when omitted. */
|
|
14
|
-
color?: Color;
|
|
15
|
-
/**
|
|
16
|
-
* Shows a required marker in `defaults.errorColor`. The marker is hidden from screen readers,
|
|
17
|
-
* so also set `required` (or `aria-required`) on the control.
|
|
18
|
-
*/
|
|
19
|
-
required?: boolean;
|
|
20
|
-
/** Uses the muted color, to match a disabled control. */
|
|
21
|
-
disabled?: boolean;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* A standalone form label, for layouts {@link Field} doesn't cover: a label beside its control,
|
|
26
|
-
* one label for several controls, or a custom control. Connect it with `htmlFor`, or give it an
|
|
27
|
-
* `id` and point the control's `aria-labelledby` at it.
|
|
28
|
-
*
|
|
29
|
-
* @example
|
|
30
|
-
* ```tsx
|
|
31
|
-
* <Label htmlFor="email" required>Email</Label>
|
|
32
|
-
* <Input id="email" type="email" required />
|
|
33
|
-
* ```
|
|
34
|
-
*/
|
|
35
|
-
export function Label({ textStyle, color, required, disabled, className, children, ...props }: LabelProps) {
|
|
36
|
-
const config = useConfig();
|
|
37
|
-
const own = useDefaults('Label');
|
|
38
|
-
const resolvedColor = color ?? own.color;
|
|
39
|
-
return (
|
|
40
|
-
<label
|
|
41
|
-
className={cx(
|
|
42
|
-
'yarcl-label',
|
|
43
|
-
typeClass(textStyle ?? own.textStyle ?? config.defaults.labelStyle),
|
|
44
|
-
resolvedColor && cx('yarcl-label-colored', colorClass(resolvedColor)),
|
|
45
|
-
disabled && 'yarcl-label-disabled',
|
|
46
|
-
className,
|
|
47
|
-
)}
|
|
48
|
-
{...props}
|
|
49
|
-
>
|
|
50
|
-
{children}
|
|
51
|
-
{required && (
|
|
52
|
-
<span className="yarcl-label-required" aria-hidden="true">
|
|
53
|
-
{' *'}
|
|
54
|
-
</span>
|
|
55
|
-
)}
|
|
56
|
-
</label>
|
|
57
|
-
);
|
|
58
|
-
}
|
package/src/components/Link.tsx
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { ComponentProps } from 'react';
|
|
2
|
-
import { colorClass, cx } from '../classes';
|
|
3
|
-
import type { Color } from '../types';
|
|
4
|
-
import { useDefaults } from '../runtime';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
/** Props for {@link Link}. Accepts all native `<a>` attributes except `color`. */
|
|
8
|
-
export interface LinkProps extends Omit<ComponentProps<'a'>, 'color'> {
|
|
9
|
-
/**
|
|
10
|
-
* Link color, from the `colors` config.
|
|
11
|
-
* @default config.defaults.color
|
|
12
|
-
*/
|
|
13
|
-
color?: Color;
|
|
14
|
-
/**
|
|
15
|
-
* When to underline. Keep `'always'` for links inside running text, so they don't rely on color alone.
|
|
16
|
-
* @default 'always'
|
|
17
|
-
*/
|
|
18
|
-
underline?: 'always' | 'hover' | 'none';
|
|
19
|
-
/** Opens in a new tab with `rel="noopener noreferrer"`. */
|
|
20
|
-
external?: boolean;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* A text link that inherits the surrounding text style.
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* ```tsx
|
|
28
|
-
* <Link href="/docs">Read the docs</Link>
|
|
29
|
-
* <Link href="https://example.com" external>Example</Link>
|
|
30
|
-
* ```
|
|
31
|
-
*/
|
|
32
|
-
export function Link({ color, underline = 'always', external, className, ...props }: LinkProps) {
|
|
33
|
-
const own = useDefaults('Link');
|
|
34
|
-
return (
|
|
35
|
-
<a
|
|
36
|
-
className={cx('yarcl-link', `yarcl-link-underline-${underline}`, colorClass(color ?? own.color), className)}
|
|
37
|
-
{...(external && { target: '_blank', rel: 'noopener noreferrer' })}
|
|
38
|
-
{...props}
|
|
39
|
-
/>
|
|
40
|
-
);
|
|
41
|
-
}
|
package/src/components/Menu.tsx
DELETED
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
autoUpdate,
|
|
3
|
-
FloatingFocusManager,
|
|
4
|
-
FloatingList,
|
|
5
|
-
FloatingPortal,
|
|
6
|
-
useClick,
|
|
7
|
-
useDismiss,
|
|
8
|
-
useFloating,
|
|
9
|
-
useInteractions,
|
|
10
|
-
useListItem,
|
|
11
|
-
useListNavigation,
|
|
12
|
-
useRole,
|
|
13
|
-
useTypeahead,
|
|
14
|
-
type Placement,
|
|
15
|
-
} from '@floating-ui/react';
|
|
16
|
-
import {
|
|
17
|
-
createContext,
|
|
18
|
-
useContext,
|
|
19
|
-
useRef,
|
|
20
|
-
useState,
|
|
21
|
-
type ComponentProps,
|
|
22
|
-
type ReactElement,
|
|
23
|
-
type ReactNode,
|
|
24
|
-
} from 'react';
|
|
25
|
-
import { colorClass, cx, sizeClass } from '../classes';
|
|
26
|
-
import { floatingMiddleware, useTrigger } from '../floating';
|
|
27
|
-
import { useControllable } from '../hooks';
|
|
28
|
-
import type { Color, Size } from '../types';
|
|
29
|
-
import { useDefaults } from '../runtime';
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
type MenuContextValue = ReturnType<typeof useMenuState>;
|
|
33
|
-
|
|
34
|
-
const MenuContext = createContext<MenuContextValue | null>(null);
|
|
35
|
-
|
|
36
|
-
function useMenuContext(component: string) {
|
|
37
|
-
const context = useContext(MenuContext);
|
|
38
|
-
if (!context) throw new Error(`yarcl: <${component}> must be inside <Menu>`);
|
|
39
|
-
return context;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function useMenuState({ open: openProp, defaultOpen = false, onOpenChange, placement = 'bottom-start', size }: MenuProps) {
|
|
43
|
-
const [open, setOpen] = useControllable(openProp, defaultOpen, onOpenChange);
|
|
44
|
-
const [activeIndex, setActiveIndex] = useState<number | null>(null);
|
|
45
|
-
const elementsRef = useRef<(HTMLElement | null)[]>([]);
|
|
46
|
-
const labelsRef = useRef<(string | null)[]>([]);
|
|
47
|
-
|
|
48
|
-
const floating = useFloating({
|
|
49
|
-
open,
|
|
50
|
-
onOpenChange: setOpen,
|
|
51
|
-
placement,
|
|
52
|
-
transform: false,
|
|
53
|
-
whileElementsMounted: autoUpdate,
|
|
54
|
-
middleware: floatingMiddleware(),
|
|
55
|
-
});
|
|
56
|
-
const interactions = useInteractions([
|
|
57
|
-
useClick(floating.context),
|
|
58
|
-
useDismiss(floating.context),
|
|
59
|
-
useRole(floating.context, { role: 'menu' }),
|
|
60
|
-
useListNavigation(floating.context, {
|
|
61
|
-
listRef: elementsRef,
|
|
62
|
-
activeIndex,
|
|
63
|
-
onNavigate: setActiveIndex,
|
|
64
|
-
loop: true,
|
|
65
|
-
}),
|
|
66
|
-
useTypeahead(floating.context, {
|
|
67
|
-
listRef: labelsRef,
|
|
68
|
-
activeIndex,
|
|
69
|
-
onMatch: open ? setActiveIndex : undefined,
|
|
70
|
-
}),
|
|
71
|
-
]);
|
|
72
|
-
|
|
73
|
-
return { open, setOpen, activeIndex, setActiveIndex, elementsRef, labelsRef, size, ...floating, ...interactions };
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/** Props for {@link Menu}. */
|
|
77
|
-
export interface MenuProps {
|
|
78
|
-
/** `Menu.Trigger` and `Menu.Content`. */
|
|
79
|
-
children?: ReactNode;
|
|
80
|
-
/** Controlled open state. */
|
|
81
|
-
open?: boolean;
|
|
82
|
-
/**
|
|
83
|
-
* Initial open state when uncontrolled.
|
|
84
|
-
* @default false
|
|
85
|
-
*/
|
|
86
|
-
defaultOpen?: boolean;
|
|
87
|
-
/** Called when the menu opens or closes. */
|
|
88
|
-
onOpenChange?: (open: boolean) => void;
|
|
89
|
-
/**
|
|
90
|
-
* Preferred side. Flips when there isn't room.
|
|
91
|
-
* @default 'bottom-start'
|
|
92
|
-
*/
|
|
93
|
-
placement?: Placement;
|
|
94
|
-
/**
|
|
95
|
-
* Item size, from the `sizes` config.
|
|
96
|
-
* @default config.defaults.size
|
|
97
|
-
*/
|
|
98
|
-
size?: Size;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function MenuRoot(props: MenuProps) {
|
|
102
|
-
const state = useMenuState(props);
|
|
103
|
-
return <MenuContext.Provider value={state}>{props.children}</MenuContext.Provider>;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/** Props for `Menu.Trigger`. */
|
|
107
|
-
export interface MenuTriggerProps {
|
|
108
|
-
/** A single element, usually a {@link Button}. */
|
|
109
|
-
children: ReactElement;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function MenuTrigger({ children }: MenuTriggerProps) {
|
|
113
|
-
const { refs, getReferenceProps } = useMenuContext('Menu.Trigger');
|
|
114
|
-
return useTrigger(children, refs.setReference, getReferenceProps);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/** Props for `Menu.Content`. */
|
|
118
|
-
export interface MenuContentProps extends ComponentProps<'div'> {}
|
|
119
|
-
|
|
120
|
-
function MenuContent({ className, style, children, ...props }: MenuContentProps) {
|
|
121
|
-
const own = useDefaults('Menu');
|
|
122
|
-
const { open, size, refs, floatingStyles, context, getFloatingProps, elementsRef, labelsRef } =
|
|
123
|
-
useMenuContext('Menu.Content');
|
|
124
|
-
if (!open) return null;
|
|
125
|
-
return (
|
|
126
|
-
<FloatingPortal>
|
|
127
|
-
<FloatingFocusManager context={context} modal={false} initialFocus={0}>
|
|
128
|
-
<div
|
|
129
|
-
ref={refs.setFloating}
|
|
130
|
-
style={{ ...floatingStyles, ...style }}
|
|
131
|
-
className={cx('yarcl-floating yarcl-panel yarcl-listbox', sizeClass(size ?? own.size), colorClass(), className)}
|
|
132
|
-
{...getFloatingProps(props)}
|
|
133
|
-
>
|
|
134
|
-
<FloatingList elementsRef={elementsRef} labelsRef={labelsRef}>
|
|
135
|
-
{children}
|
|
136
|
-
</FloatingList>
|
|
137
|
-
</div>
|
|
138
|
-
</FloatingFocusManager>
|
|
139
|
-
</FloatingPortal>
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/** Props for `Menu.Item`. */
|
|
144
|
-
export interface MenuItemProps extends Omit<ComponentProps<'button'>, 'color' | 'onSelect'> {
|
|
145
|
-
/** Called when the item is chosen by click, Enter or Space. The menu closes afterwards. */
|
|
146
|
-
onSelect?: () => void;
|
|
147
|
-
/** Semantic color for the item, e.g. a destructive action. From the `colors` config. */
|
|
148
|
-
color?: Color;
|
|
149
|
-
/** Text used for type-to-select. Defaults to `children` when it is a string. */
|
|
150
|
-
textValue?: string;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function MenuItem({ onSelect, color, textValue, disabled, className, children, ...props }: MenuItemProps) {
|
|
154
|
-
const { activeIndex, setOpen, getItemProps } = useMenuContext('Menu.Item');
|
|
155
|
-
const { ref, index } = useListItem({
|
|
156
|
-
label: disabled ? null : (textValue ?? (typeof children === 'string' ? children : null)),
|
|
157
|
-
});
|
|
158
|
-
const active = activeIndex === index;
|
|
159
|
-
return (
|
|
160
|
-
<button
|
|
161
|
-
ref={ref}
|
|
162
|
-
type="button"
|
|
163
|
-
role="menuitem"
|
|
164
|
-
tabIndex={active ? 0 : -1}
|
|
165
|
-
disabled={disabled}
|
|
166
|
-
data-active={active || undefined}
|
|
167
|
-
className={cx('yarcl-option', color && cx('yarcl-option-colored', colorClass(color)), className)}
|
|
168
|
-
{...getItemProps({
|
|
169
|
-
...props,
|
|
170
|
-
onClick() {
|
|
171
|
-
onSelect?.();
|
|
172
|
-
setOpen(false);
|
|
173
|
-
},
|
|
174
|
-
})}
|
|
175
|
-
>
|
|
176
|
-
{children}
|
|
177
|
-
</button>
|
|
178
|
-
);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/** A line between groups of `Menu.Item`s. */
|
|
182
|
-
function MenuSeparator() {
|
|
183
|
-
return <div role="separator" className="yarcl-listbox-separator" />;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* A list of actions opened from a trigger. Arrow keys move between items,
|
|
188
|
-
* typing jumps to a matching item, Esc closes.
|
|
189
|
-
*
|
|
190
|
-
* @example
|
|
191
|
-
* ```tsx
|
|
192
|
-
* <Menu>
|
|
193
|
-
* <Menu.Trigger><Button variant="outline">Actions</Button></Menu.Trigger>
|
|
194
|
-
* <Menu.Content>
|
|
195
|
-
* <Menu.Item onSelect={rename}>Rename</Menu.Item>
|
|
196
|
-
* <Menu.Separator />
|
|
197
|
-
* <Menu.Item color="danger" onSelect={remove}>Delete</Menu.Item>
|
|
198
|
-
* </Menu.Content>
|
|
199
|
-
* </Menu>
|
|
200
|
-
* ```
|
|
201
|
-
*/
|
|
202
|
-
export const Menu = Object.assign(MenuRoot, {
|
|
203
|
-
Trigger: MenuTrigger,
|
|
204
|
-
Content: MenuContent,
|
|
205
|
-
Item: MenuItem,
|
|
206
|
-
Separator: MenuSeparator,
|
|
207
|
-
});
|