@clicktap/ui 0.14.12 → 0.14.13
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/components/Accordion/Accordion.tsx +82 -0
- package/components/Accordion/index.ts +3 -0
- package/components/Avatar/Avatar.stories.tsx +99 -0
- package/components/Avatar/Avatar.tsx +120 -0
- package/components/Avatar/Avatar.types.ts +3 -0
- package/components/Avatar/AvatarGroup/AvatarGroup.tsx +32 -0
- package/components/Avatar/AvatarGroup/AvatarGroup.types.ts +8 -0
- package/components/Avatar/index.ts +4 -0
- package/components/Badge/Badge.stories.tsx +72 -0
- package/components/Badge/Badge.tsx +169 -0
- package/components/Badge/Badge.types.ts +3 -0
- package/components/Badge/index.ts +2 -0
- package/components/Breadcrumbs/BreadcrumbEllipsis.tsx +47 -0
- package/components/Breadcrumbs/BreadcrumbEllipsis.types.ts +5 -0
- package/components/Breadcrumbs/BreadcrumbItem.tsx +23 -0
- package/components/Breadcrumbs/BreadcrumbItem.types.ts +3 -0
- package/components/Breadcrumbs/BreadcrumbLink.tsx +30 -0
- package/components/Breadcrumbs/BreadcrumbLink.types.ts +3 -0
- package/components/Breadcrumbs/BreadcrumbSeparator.tsx +41 -0
- package/components/Breadcrumbs/BreadcrumbSeparator.types.ts +9 -0
- package/components/Breadcrumbs/Breadcrumbs.tsx +28 -0
- package/components/Breadcrumbs/Breadcrumbs.types.ts +6 -0
- package/components/Breadcrumbs/index.ts +10 -0
- package/components/Button/Button.tsx +72 -0
- package/components/Button/Button.types.ts +7 -0
- package/components/Button/index.ts +2 -0
- package/components/Card/Card.tsx +15 -0
- package/components/Card/Card.types.ts +3 -0
- package/components/Card/index.ts +2 -0
- package/components/Checkbox/Checkbox.tsx +122 -0
- package/components/Checkbox/Checkbox.types.ts +15 -0
- package/components/Checkbox/index.ts +2 -0
- package/components/Collapsible/Collapsible.tsx +34 -0
- package/components/Collapsible/Collapsible.types.ts +5 -0
- package/components/Collapsible/CollapsibleTrigger.tsx +57 -0
- package/components/Collapsible/CollapsibleTrigger.types.ts +14 -0
- package/components/Collapsible/index.ts +10 -0
- package/components/Container/Container.tsx +26 -0
- package/components/Container/Container.types.ts +3 -0
- package/components/Container/index.ts +2 -0
- package/components/ContextMenu/ContextMenu.tsx +74 -0
- package/components/ContextMenu/ContextMenu.types.ts +17 -0
- package/components/ContextMenu/index.ts +2 -0
- package/components/CreditCardExpirationInput/CreditCardExpirationInput.tsx +115 -0
- package/components/CreditCardExpirationInput/CreditCardExpirationInput.types.ts +10 -0
- package/components/CreditCardExpirationInput/index.ts +2 -0
- package/components/CreditCardInput/CreditCardInput.tsx +147 -0
- package/components/CreditCardInput/CreditCardInput.types.ts +12 -0
- package/components/CreditCardInput/index.ts +2 -0
- package/components/DateInput/DateInput.tsx +81 -0
- package/components/DateInput/DateInput.types.ts +15 -0
- package/components/DateInput/index.ts +2 -0
- package/components/DateTimeFormat/DateTimeFormat.tsx +16 -0
- package/components/DateTimeFormat/DateTimeFormat.types.ts +7 -0
- package/components/DateTimeFormat/index.ts +2 -0
- package/components/Dialog/Dialog.tsx +65 -0
- package/components/Dialog/Dialog.types.ts +9 -0
- package/components/Dialog/index.ts +2 -0
- package/components/DialogTrigger/DialogTrigger.tsx +45 -0
- package/components/DialogTrigger/DialogTrigger.types.ts +6 -0
- package/components/DialogTrigger/index.ts +5 -0
- package/components/Divider/Divider.stories.tsx +37 -0
- package/components/Divider/Divider.tsx +34 -0
- package/components/Divider/Divider.types.ts +5 -0
- package/components/Divider/index.ts +2 -0
- package/components/DobInput/DobInput.tsx +120 -0
- package/components/DobInput/index.ts +2 -0
- package/components/Drawer/Drawer.tsx +126 -0
- package/components/Drawer/Drawer.types.ts +11 -0
- package/components/Drawer/index.ts +2 -0
- package/components/Icon/Account.tsx +50 -0
- package/components/Icon/Cart.tsx +43 -0
- package/components/Icon/Checkmark.tsx +34 -0
- package/components/Icon/Cross.tsx +36 -0
- package/components/Icon/DownArrow.tsx +23 -0
- package/components/Icon/Hamburger.tsx +23 -0
- package/components/Icon/Icon.types.ts +8 -0
- package/components/Icon/LinkArrow.tsx +32 -0
- package/components/Icon/Minus.tsx +20 -0
- package/components/Icon/Plus.tsx +20 -0
- package/components/Icon/Search.tsx +36 -0
- package/components/Icon/Trash.tsx +27 -0
- package/components/Icon/Verified.tsx +20 -0
- package/components/Icon/index.ts +14 -0
- package/components/Image/Image.tsx +32 -0
- package/components/Image/index.ts +2 -0
- package/components/Input/Input.tsx +109 -0
- package/components/Input/Input.types.ts +17 -0
- package/components/Input/index.ts +2 -0
- package/components/Link/Link.stories.tsx +96 -0
- package/components/Link/Link.tsx +34 -0
- package/components/Link/Link.types.ts +3 -0
- package/components/Link/index.ts +2 -0
- package/components/Loader/CircularEasing.tsx +66 -0
- package/components/Loader/CircularEasing.types.ts +8 -0
- package/components/Loader/Pulse.tsx +45 -0
- package/components/Loader/Pulse.types.ts +5 -0
- package/components/Loader/index.ts +4 -0
- package/components/Menu/ContextMenu.tsx +83 -0
- package/components/Menu/Menu.tsx +143 -0
- package/components/Menu/Menu.types.ts +44 -0
- package/components/Menu/index.ts +4 -0
- package/components/Meter/Meter.stories.tsx +111 -0
- package/components/Meter/Meter.tsx +68 -0
- package/components/Meter/Meter.types.ts +10 -0
- package/components/Meter/index.ts +2 -0
- package/components/Modal/Modal.tsx +16 -0
- package/components/Modal/Modal.types.ts +6 -0
- package/components/Modal/index.ts +2 -0
- package/components/ModalOverlay/ModalOverlay.tsx +121 -0
- package/components/ModalOverlay/ModalOverlay.types.ts +18 -0
- package/components/ModalOverlay/index.ts +2 -0
- package/components/NumberFormat/NumberFormat.tsx +19 -0
- package/components/NumberFormat/NumberFormat.types.ts +8 -0
- package/components/NumberFormat/index.ts +2 -0
- package/components/NumberInput/NumberInput.tsx +164 -0
- package/components/NumberInput/NumberInput.types.ts +22 -0
- package/components/NumberInput/index.ts +2 -0
- package/components/NumberTicker/DigitResolver.tsx +119 -0
- package/components/NumberTicker/DigitResolver.types.ts +18 -0
- package/components/NumberTicker/NumberTicker.tsx +56 -0
- package/components/NumberTicker/NumberTicker.types.ts +96 -0
- package/components/NumberTicker/hooks/useColumnTransition.ts +36 -0
- package/components/NumberTicker/hooks/useNumberDelta.ts +19 -0
- package/components/NumberTicker/hooks/useNumberTicker.ts +36 -0
- package/components/NumberTicker/index.ts +10 -0
- package/components/Pagination/Pagination.tsx +44 -0
- package/components/Pagination/index.ts +2 -0
- package/components/PasswordCheck/PasswordCheck.tsx +59 -0
- package/components/PasswordCheck/PasswordCheck.types.ts +4 -0
- package/components/PasswordCheck/PasswordCheck.utils.ts +47 -0
- package/components/PasswordCheck/index.ts +2 -0
- package/components/PhoneInput/PhoneInput.tsx +191 -0
- package/components/PhoneInput/index.ts +2 -0
- package/components/PinInput/PinInput.tsx +314 -0
- package/components/PinInput/PinInput.types.ts +21 -0
- package/components/PinInput/index.ts +2 -0
- package/components/Progressbar/CircularProgressbar.tsx +71 -0
- package/components/Progressbar/CircularProgressbar.types.ts +10 -0
- package/components/Progressbar/LinearProgressbar.tsx +75 -0
- package/components/Progressbar/LinearProgressbar.types.ts +11 -0
- package/components/Progressbar/index.ts +4 -0
- package/components/Radio/Radio.tsx +88 -0
- package/components/Radio/Radio.types.ts +16 -0
- package/components/Radio/index.ts +2 -0
- package/components/RadioGroup/RadioGroup.tsx +49 -0
- package/components/RadioGroup/RadioGroup.types.ts +7 -0
- package/components/RadioGroup/index.ts +2 -0
- package/components/Select/Option.tsx +32 -0
- package/components/Select/Option.types.ts +3 -0
- package/components/Select/Select.tsx +253 -0
- package/components/Select/Select.types.ts +42 -0
- package/components/Select/index.ts +8 -0
- package/components/Skeleton/Skeleton.tsx +15 -0
- package/components/Skeleton/Skeleton.types.ts +3 -0
- package/components/Skeleton/index.ts +2 -0
- package/components/Slider/Slider.tsx +110 -0
- package/components/Slider/Slider.types.ts +11 -0
- package/components/Slider/index.ts +2 -0
- package/components/Switch/Switch.tsx +63 -0
- package/components/Switch/Switch.types.ts +8 -0
- package/components/Switch/index.ts +2 -0
- package/components/Table/Table.tsx +52 -0
- package/components/Table/Table.types.ts +22 -0
- package/components/Table/index.ts +2 -0
- package/components/Tabs/Tab.tsx +118 -0
- package/components/Tabs/Tab.types.ts +10 -0
- package/components/Tabs/TabList.tsx +51 -0
- package/components/Tabs/TabList.types.ts +12 -0
- package/components/Tabs/TabPanel.tsx +19 -0
- package/components/Tabs/TabPanel.types.ts +3 -0
- package/components/Tabs/Tabs.context.tsx +9 -0
- package/components/Tabs/Tabs.tsx +39 -0
- package/components/Tabs/Tabs.types.ts +3 -0
- package/components/Tabs/index.ts +9 -0
- package/components/TimeInput/TimeInput.stories.tsx +125 -0
- package/components/TimeInput/TimeInput.tsx +81 -0
- package/components/TimeInput/TimeInput.types.ts +15 -0
- package/components/TimeInput/index.ts +2 -0
- package/components/ToggleButton/ToggleButton.stories.tsx +89 -0
- package/components/ToggleButton/ToggleButton.tsx +69 -0
- package/components/ToggleButton/ToggleButton.types.ts +6 -0
- package/components/ToggleButton/index.ts +2 -0
- package/components/Tooltip/Tooltip.tsx +59 -0
- package/components/Tooltip/Tooltip.types.ts +3 -0
- package/components/Tooltip/index.ts +2 -0
- package/components/UploadImage/UploadImage.tsx +206 -0
- package/components/UploadImage/UploadImage.types.ts +15 -0
- package/components/UploadImage/index.ts +2 -0
- package/package.json +1 -1
- package/tailwind.config.js +3 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Link } from 'react-aria-components';
|
|
4
|
+
import { cn } from '../../utils/cn';
|
|
5
|
+
import type { BreadcrumbLinkProps } from './BreadcrumbLink.types';
|
|
6
|
+
|
|
7
|
+
export function BreadcrumbLink({
|
|
8
|
+
children,
|
|
9
|
+
className,
|
|
10
|
+
...props
|
|
11
|
+
}: BreadcrumbLinkProps) {
|
|
12
|
+
return (
|
|
13
|
+
<Link
|
|
14
|
+
className={cn(
|
|
15
|
+
'text-slate-600 no-underline cursor-pointer',
|
|
16
|
+
'focus-visible:outline-2 focus-visible:outline focus-visible:outline-slate-200',
|
|
17
|
+
'hover:text-slate-900 hover:underline',
|
|
18
|
+
'current:cursor-default current:text-slate-900 current:font-semibold',
|
|
19
|
+
'disabled:cursor-default disabled:text-slate-400 disabled:current:text-slate-900',
|
|
20
|
+
className
|
|
21
|
+
)}
|
|
22
|
+
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
23
|
+
{...props}
|
|
24
|
+
>
|
|
25
|
+
{children}
|
|
26
|
+
</Link>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default BreadcrumbLink;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Breadcrumb } from 'react-aria-components';
|
|
4
|
+
import { cn } from '../../utils/cn';
|
|
5
|
+
import type { BreadcrumbSeparatorProps } from './BreadcrumbSeparator.types';
|
|
6
|
+
|
|
7
|
+
export function BreadcrumbSeparator({
|
|
8
|
+
children,
|
|
9
|
+
className,
|
|
10
|
+
...props
|
|
11
|
+
}: BreadcrumbSeparatorProps) {
|
|
12
|
+
return (
|
|
13
|
+
<Breadcrumb
|
|
14
|
+
className={cn('flex items-center text-slate-600', 'my-0 mx-2', className)}
|
|
15
|
+
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
16
|
+
{...props}
|
|
17
|
+
>
|
|
18
|
+
{children ?? (
|
|
19
|
+
<svg
|
|
20
|
+
aria-hidden="true"
|
|
21
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
22
|
+
width="16"
|
|
23
|
+
height="16"
|
|
24
|
+
viewBox="0 0 16 16"
|
|
25
|
+
fill="none"
|
|
26
|
+
className="w-4 h-4"
|
|
27
|
+
>
|
|
28
|
+
<path
|
|
29
|
+
d="M6 12L10 8L6 4"
|
|
30
|
+
stroke="currentColor"
|
|
31
|
+
strokeWidth="1.5"
|
|
32
|
+
strokeLinecap="round"
|
|
33
|
+
strokeLinejoin="round"
|
|
34
|
+
/>
|
|
35
|
+
</svg>
|
|
36
|
+
)}
|
|
37
|
+
</Breadcrumb>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default BreadcrumbSeparator;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BreadcrumbProps } from 'react-aria-components';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/** @todo what is this type actually trying to do? */
|
|
5
|
+
export interface BreadcrumbSeparatorProps
|
|
6
|
+
extends Omit<BreadcrumbProps, 'children'>,
|
|
7
|
+
React.RefAttributes<HTMLLIElement> {
|
|
8
|
+
children?: ReactNode;
|
|
9
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Breadcrumbs as AriaBreadcrumbs } from 'react-aria-components';
|
|
4
|
+
import { cn } from '../../utils/cn';
|
|
5
|
+
import type { BreadcrumbsProps } from './Breadcrumbs.types';
|
|
6
|
+
|
|
7
|
+
export function Breadcrumbs({
|
|
8
|
+
children,
|
|
9
|
+
className,
|
|
10
|
+
...props
|
|
11
|
+
}: BreadcrumbsProps<object>) {
|
|
12
|
+
return (
|
|
13
|
+
<AriaBreadcrumbs
|
|
14
|
+
className={cn(
|
|
15
|
+
'flex items-center list-none text-sm',
|
|
16
|
+
'mx-0 mt-0 mr-4',
|
|
17
|
+
'px-0 pt-1.5 pb-0',
|
|
18
|
+
className
|
|
19
|
+
)}
|
|
20
|
+
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
21
|
+
{...props}
|
|
22
|
+
>
|
|
23
|
+
{children}
|
|
24
|
+
</AriaBreadcrumbs>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export default Breadcrumbs;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { BreadcrumbEllipsis } from './BreadcrumbEllipsis';
|
|
2
|
+
export { BreadcrumbItem } from './BreadcrumbItem';
|
|
3
|
+
export { BreadcrumbLink } from './BreadcrumbLink';
|
|
4
|
+
export { BreadcrumbSeparator } from './BreadcrumbSeparator';
|
|
5
|
+
export { Breadcrumbs } from './Breadcrumbs';
|
|
6
|
+
export type { BreadcrumbEllipsisProps } from './BreadcrumbEllipsis.types';
|
|
7
|
+
export type { BreadcrumbItemProps } from './BreadcrumbItem.types';
|
|
8
|
+
export type { BreadcrumbLinkProps } from './BreadcrumbLink.types';
|
|
9
|
+
export type { BreadcrumbSeparatorProps } from './BreadcrumbSeparator.types';
|
|
10
|
+
export type { BreadcrumbsProps } from './Breadcrumbs.types';
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { forwardRef } from 'react';
|
|
4
|
+
import { Button as AriaButton } from 'react-aria-components';
|
|
5
|
+
import { cn } from '../../utils/cn';
|
|
6
|
+
import type { ButtonProps } from './Button.types';
|
|
7
|
+
|
|
8
|
+
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
9
|
+
function Button(
|
|
10
|
+
{
|
|
11
|
+
className,
|
|
12
|
+
isDisabled = false,
|
|
13
|
+
isLoading = false,
|
|
14
|
+
size = 'md',
|
|
15
|
+
variant = 'solid',
|
|
16
|
+
...props
|
|
17
|
+
},
|
|
18
|
+
ref
|
|
19
|
+
) {
|
|
20
|
+
const baseClasses = [
|
|
21
|
+
'flex items-center justify-center',
|
|
22
|
+
'rounded-md border-solid border',
|
|
23
|
+
'font-semibold text-sm',
|
|
24
|
+
'py-2 px-8',
|
|
25
|
+
'transition-all duration-200 ease-in-out',
|
|
26
|
+
'focus:outline-2 focus:outline focus:outline-slate-200 pressed:scale-95',
|
|
27
|
+
// size logic:
|
|
28
|
+
size === 'sm' && 'h-8',
|
|
29
|
+
size === 'md' && 'h-10',
|
|
30
|
+
size === 'lg' && 'h-12',
|
|
31
|
+
// variant logic:
|
|
32
|
+
variant === 'ghost' && [
|
|
33
|
+
'bg-transparent hover:bg-transparent focus:bg-transparent disabled:bg-transparent',
|
|
34
|
+
'border-transparent hover:border-transparent focus:border-transparent disabled:border-transparent',
|
|
35
|
+
'text-slate-900 disabled:text-slate-400',
|
|
36
|
+
isLoading && 'disabled:text-slate-900',
|
|
37
|
+
],
|
|
38
|
+
variant === 'outline' && [
|
|
39
|
+
'bg-transparent hover:bg-transparent focus:bg-transparent disabled:bg-transparent',
|
|
40
|
+
'border-slate-300 hover:border-slate-400 focus:border-slate-400 disabled:border-slate-200',
|
|
41
|
+
'text-slate-900 disabled:text-slate-500',
|
|
42
|
+
isLoading && ['disabled:border-slate-300', 'disabled:text-slate-900'],
|
|
43
|
+
],
|
|
44
|
+
variant === 'solid' && [
|
|
45
|
+
'bg-slate-800 hover:bg-slate-900 focus:bg-slate-900 disabled:bg-slate-900',
|
|
46
|
+
'border-slate-800 hover:border-slate-900 focus:border-slate-900 disabled:border-slate-200',
|
|
47
|
+
'text-white disabled:text-slate-400',
|
|
48
|
+
isLoading && ['disabled:border-slate-900', 'disabled:text-white'],
|
|
49
|
+
],
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<AriaButton
|
|
54
|
+
ref={ref}
|
|
55
|
+
type="button"
|
|
56
|
+
isDisabled={isDisabled}
|
|
57
|
+
className={(renderProps) => {
|
|
58
|
+
const userClasses =
|
|
59
|
+
typeof className === 'function'
|
|
60
|
+
? className(renderProps)
|
|
61
|
+
: className;
|
|
62
|
+
|
|
63
|
+
return cn(baseClasses, userClasses);
|
|
64
|
+
}}
|
|
65
|
+
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
66
|
+
{...props}
|
|
67
|
+
/>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
export default Button;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { cn } from '../../utils/cn';
|
|
4
|
+
import type { CardProps } from './Card.types';
|
|
5
|
+
|
|
6
|
+
export function Card({ children, className, ...props }: CardProps) {
|
|
7
|
+
return (
|
|
8
|
+
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
9
|
+
<div className={cn('flex flex-col', className)} {...props}>
|
|
10
|
+
{children}
|
|
11
|
+
</div>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default Card;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { Checkbox as AriaCheckbox } from 'react-aria-components';
|
|
2
|
+
import type { CheckboxRenderProps } from 'react-aria-components';
|
|
3
|
+
import { cn } from '../../utils/cn';
|
|
4
|
+
import type { CheckboxProps, CheckboxSlots } from './Checkbox.types';
|
|
5
|
+
|
|
6
|
+
function ControlSlot({
|
|
7
|
+
control,
|
|
8
|
+
isHovered,
|
|
9
|
+
isFocused,
|
|
10
|
+
isDisabled,
|
|
11
|
+
isIndeterminate,
|
|
12
|
+
isInvalid,
|
|
13
|
+
isSelected,
|
|
14
|
+
isPressed,
|
|
15
|
+
classNames,
|
|
16
|
+
...rest
|
|
17
|
+
}: CheckboxRenderProps &
|
|
18
|
+
Pick<CheckboxSlots, 'control'> &
|
|
19
|
+
Pick<CheckboxProps, 'classNames'>) {
|
|
20
|
+
if (!control) {
|
|
21
|
+
return (
|
|
22
|
+
<div
|
|
23
|
+
className={cn(
|
|
24
|
+
'flex items-center justify-center',
|
|
25
|
+
'w-6 h-6',
|
|
26
|
+
'border border-solid border-slate-300 rounded',
|
|
27
|
+
'transition-all duration-200 ease-in-out',
|
|
28
|
+
'checkbox-control',
|
|
29
|
+
isHovered && ['border-slate-400'],
|
|
30
|
+
isFocused && ['border-slate-400 outline-2 outline outline-slate-200'],
|
|
31
|
+
(isDisabled || (isDisabled && isIndeterminate)) && [
|
|
32
|
+
'border-slate-200 bg-slate-100',
|
|
33
|
+
],
|
|
34
|
+
isInvalid && ['bg-slate-100 text-red-600 border-red-500'],
|
|
35
|
+
isInvalid && isHovered && ['border-red-600'],
|
|
36
|
+
isInvalid && isFocused && ['border-red-600 outline-red-200'],
|
|
37
|
+
isInvalid &&
|
|
38
|
+
isSelected &&
|
|
39
|
+
isIndeterminate && ['bg-red-500 border-red-500'],
|
|
40
|
+
isInvalid &&
|
|
41
|
+
isSelected &&
|
|
42
|
+
isIndeterminate &&
|
|
43
|
+
isPressed && ['bg-red-600 border-red-600'],
|
|
44
|
+
(isSelected || isIndeterminate) && ['border-slate-300 bg-slate-300'],
|
|
45
|
+
(isSelected || isIndeterminate) &&
|
|
46
|
+
isPressed && ['border-slate-400 bg-slate-400'],
|
|
47
|
+
classNames?.control
|
|
48
|
+
)}
|
|
49
|
+
>
|
|
50
|
+
{/* <Control className="checkbox-control"> */}
|
|
51
|
+
<svg
|
|
52
|
+
viewBox="0 0 18 18"
|
|
53
|
+
aria-hidden="true"
|
|
54
|
+
style={{
|
|
55
|
+
strokeDasharray: '22px',
|
|
56
|
+
strokeDashoffset: isSelected || isIndeterminate ? 44 : 66,
|
|
57
|
+
}}
|
|
58
|
+
className={cn(
|
|
59
|
+
'w-4 h-4 fill-none',
|
|
60
|
+
'stroke-white stroke-[3px]',
|
|
61
|
+
'transition-all duration-200 ease-in-out',
|
|
62
|
+
isDisabled && isIndeterminate && ['stroke-none fill-slate-300'],
|
|
63
|
+
isIndeterminate && ['stroke-none fill-white']
|
|
64
|
+
)}
|
|
65
|
+
>
|
|
66
|
+
{isIndeterminate ? (
|
|
67
|
+
<rect x={1} y={7.5} width={15} height={3} />
|
|
68
|
+
) : (
|
|
69
|
+
<polyline points="1 9 7 14 15 4" />
|
|
70
|
+
)}
|
|
71
|
+
</svg>
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
return typeof control === 'function'
|
|
76
|
+
? control({
|
|
77
|
+
isHovered,
|
|
78
|
+
isFocused,
|
|
79
|
+
isDisabled,
|
|
80
|
+
isIndeterminate,
|
|
81
|
+
isInvalid,
|
|
82
|
+
isSelected,
|
|
83
|
+
isPressed,
|
|
84
|
+
...rest,
|
|
85
|
+
})
|
|
86
|
+
: control;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function Checkbox({
|
|
90
|
+
children,
|
|
91
|
+
slots,
|
|
92
|
+
className,
|
|
93
|
+
classNames,
|
|
94
|
+
...props
|
|
95
|
+
}: CheckboxProps) {
|
|
96
|
+
return (
|
|
97
|
+
<AriaCheckbox
|
|
98
|
+
className={cn(
|
|
99
|
+
'flex items-center gap-2',
|
|
100
|
+
'text-xs text-slate-500 forced-color-adjust-none disabled:text-slate-400 group',
|
|
101
|
+
'invalid:text-red-500',
|
|
102
|
+
className
|
|
103
|
+
)}
|
|
104
|
+
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
105
|
+
{...props}
|
|
106
|
+
>
|
|
107
|
+
{(renderProps) => (
|
|
108
|
+
<>
|
|
109
|
+
<ControlSlot
|
|
110
|
+
control={slots?.control}
|
|
111
|
+
classNames={classNames}
|
|
112
|
+
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
113
|
+
{...renderProps}
|
|
114
|
+
/>
|
|
115
|
+
{typeof children === 'function' ? children(renderProps) : children}
|
|
116
|
+
</>
|
|
117
|
+
)}
|
|
118
|
+
</AriaCheckbox>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export default Checkbox;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CheckboxProps as UiCheckboxProps,
|
|
3
|
+
CheckboxRenderProps,
|
|
4
|
+
} from 'react-aria-components';
|
|
5
|
+
import type { ReactNode } from 'react';
|
|
6
|
+
import type { SlotsToClasses } from '../../types/SlotsToClasses';
|
|
7
|
+
|
|
8
|
+
export interface CheckboxSlots {
|
|
9
|
+
control?: ReactNode | ((values: CheckboxRenderProps) => ReactNode);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface CheckboxProps extends UiCheckboxProps {
|
|
13
|
+
slots?: CheckboxSlots;
|
|
14
|
+
classNames?: SlotsToClasses<'control'>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useContext } from 'react';
|
|
4
|
+
import { motion } from 'framer-motion';
|
|
5
|
+
import type { CollapsibleContentProps } from './Collapsible.types';
|
|
6
|
+
import { CollapsibleTriggerStateContext } from './CollapsibleTrigger';
|
|
7
|
+
import { cn } from '../../utils/cn';
|
|
8
|
+
|
|
9
|
+
export function Collapsible({ children, className }: CollapsibleContentProps) {
|
|
10
|
+
const { isOpen, id, defaultOpen } = useContext(
|
|
11
|
+
CollapsibleTriggerStateContext
|
|
12
|
+
);
|
|
13
|
+
return (
|
|
14
|
+
<motion.div
|
|
15
|
+
className={cn('w-full overflow-hidden', className)}
|
|
16
|
+
id={id}
|
|
17
|
+
variants={{
|
|
18
|
+
hidden: { height: '0px', opacity: 0 },
|
|
19
|
+
visible: { height: 'auto', opacity: 1 },
|
|
20
|
+
}}
|
|
21
|
+
initial={defaultOpen ? 'visible' : 'hidden'}
|
|
22
|
+
animate={isOpen ? 'visible' : 'hidden'}
|
|
23
|
+
transition={{
|
|
24
|
+
type: 'spring',
|
|
25
|
+
bounce: 0,
|
|
26
|
+
}}
|
|
27
|
+
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
28
|
+
>
|
|
29
|
+
{children}
|
|
30
|
+
</motion.div>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default Collapsible;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Provider } from 'react-aria-components';
|
|
4
|
+
import { useControlledState } from '@react-stately/utils';
|
|
5
|
+
import { createContext, useCallback, useId, useRef } from 'react';
|
|
6
|
+
import { PressResponder } from '@react-aria/interactions';
|
|
7
|
+
import {
|
|
8
|
+
CollapsibleTriggerProps,
|
|
9
|
+
CollapsibleTriggerState,
|
|
10
|
+
} from './CollapsibleTrigger.types';
|
|
11
|
+
import { cn } from '../../utils/cn';
|
|
12
|
+
|
|
13
|
+
/** @todo look into use hook to provide access instead of exporting directly */
|
|
14
|
+
export const CollapsibleTriggerStateContext =
|
|
15
|
+
createContext<CollapsibleTriggerState>({} as CollapsibleTriggerState);
|
|
16
|
+
|
|
17
|
+
export function CollapsibleTrigger({
|
|
18
|
+
children,
|
|
19
|
+
className,
|
|
20
|
+
...props
|
|
21
|
+
}: CollapsibleTriggerProps) {
|
|
22
|
+
const id = useId();
|
|
23
|
+
const [isOpen, onOpenChange] = useControlledState(
|
|
24
|
+
props.isOpen,
|
|
25
|
+
props.defaultOpen || false,
|
|
26
|
+
props.onOpenChange
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
30
|
+
|
|
31
|
+
const toggle = useCallback(() => {
|
|
32
|
+
onOpenChange(!isOpen);
|
|
33
|
+
}, [onOpenChange, isOpen]);
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<Provider
|
|
37
|
+
values={[
|
|
38
|
+
[
|
|
39
|
+
CollapsibleTriggerStateContext,
|
|
40
|
+
{ isOpen, id, defaultOpen: props.defaultOpen || false },
|
|
41
|
+
],
|
|
42
|
+
]}
|
|
43
|
+
>
|
|
44
|
+
<PressResponder
|
|
45
|
+
ref={buttonRef}
|
|
46
|
+
isPressed={isOpen}
|
|
47
|
+
onPress={toggle}
|
|
48
|
+
aria-expanded={isOpen}
|
|
49
|
+
aria-controls={id}
|
|
50
|
+
>
|
|
51
|
+
<div className={cn('w-full', className)}>{children}</div>
|
|
52
|
+
</PressResponder>
|
|
53
|
+
</Provider>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export default CollapsibleTrigger;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { PropsWithChildren } from 'react';
|
|
2
|
+
|
|
3
|
+
export type CollapsibleTriggerState = {
|
|
4
|
+
isOpen: boolean;
|
|
5
|
+
id: string;
|
|
6
|
+
defaultOpen: boolean;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export type CollapsibleTriggerProps = PropsWithChildren<{
|
|
10
|
+
isOpen?: boolean;
|
|
11
|
+
defaultOpen?: boolean;
|
|
12
|
+
onOpenChange?: (isOpen: boolean) => void;
|
|
13
|
+
className?: string | undefined;
|
|
14
|
+
}>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { Collapsible } from './Collapsible';
|
|
2
|
+
export {
|
|
3
|
+
CollapsibleTrigger,
|
|
4
|
+
CollapsibleTriggerStateContext,
|
|
5
|
+
} from './CollapsibleTrigger';
|
|
6
|
+
export type { CollapsibleContentProps } from './Collapsible.types';
|
|
7
|
+
export type {
|
|
8
|
+
CollapsibleTriggerProps,
|
|
9
|
+
CollapsibleTriggerState,
|
|
10
|
+
} from './CollapsibleTrigger.types';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { forwardRef } from 'react';
|
|
4
|
+
import type { ForwardedRef } from 'react';
|
|
5
|
+
import type { ContainerProps } from './Container.types';
|
|
6
|
+
import { cn } from '../../utils/cn';
|
|
7
|
+
|
|
8
|
+
export const Container = forwardRef(
|
|
9
|
+
(
|
|
10
|
+
{ children, className, ...props }: ContainerProps,
|
|
11
|
+
ref: ForwardedRef<HTMLDivElement>
|
|
12
|
+
) => {
|
|
13
|
+
return (
|
|
14
|
+
<div
|
|
15
|
+
ref={ref}
|
|
16
|
+
className={cn('container', 'mx-auto my-0', 'py-0 px-4', className)}
|
|
17
|
+
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
18
|
+
{...props}
|
|
19
|
+
>
|
|
20
|
+
{children}
|
|
21
|
+
</div>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
export default Container;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Menu, Popover } from 'react-aria-components';
|
|
4
|
+
import { forwardRef } from 'react';
|
|
5
|
+
import type { Ref } from 'react';
|
|
6
|
+
import { motion } from 'framer-motion';
|
|
7
|
+
import { cn } from '../../utils/cn';
|
|
8
|
+
import type { PopoverProps } from './ContextMenu.types';
|
|
9
|
+
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11
|
+
const ForwardedPopover = forwardRef<HTMLElement, any>(
|
|
12
|
+
({ style, ...props }, ref: Ref<HTMLElement>) => {
|
|
13
|
+
// Separate the dynamic style logic
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
|
|
15
|
+
const ariaStyle = typeof style === 'function' ? style(props) : style;
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
// Pass only static styles to framer-motion
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, react/jsx-props-no-spreading
|
|
20
|
+
<Popover {...props} ref={ref} style={ariaStyle} />
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
const MotionPopover = motion.create(ForwardedPopover);
|
|
26
|
+
|
|
27
|
+
export function ContextMenu({
|
|
28
|
+
children,
|
|
29
|
+
key,
|
|
30
|
+
onAction,
|
|
31
|
+
setAnimation,
|
|
32
|
+
animation = 'hidden',
|
|
33
|
+
className,
|
|
34
|
+
classNames,
|
|
35
|
+
...props
|
|
36
|
+
}: PopoverProps) {
|
|
37
|
+
return (
|
|
38
|
+
<MotionPopover
|
|
39
|
+
className={cn(
|
|
40
|
+
'px-0 py-1.5',
|
|
41
|
+
'shadow-[0_10px_15px_-3px_rgba(0,0,0,0.1),0_4px_6px_-4px_rgba(0,0,0,0.1)]',
|
|
42
|
+
'rounded-md',
|
|
43
|
+
'w-56',
|
|
44
|
+
'bg-white',
|
|
45
|
+
'border border-solid border-slate-300',
|
|
46
|
+
className
|
|
47
|
+
)}
|
|
48
|
+
key={key}
|
|
49
|
+
isExiting={animation === 'hidden'}
|
|
50
|
+
onAnimationComplete={(completedAnimation: string) => {
|
|
51
|
+
setAnimation((a) =>
|
|
52
|
+
completedAnimation === 'hidden' && a === 'hidden' ? 'unmounted' : a
|
|
53
|
+
);
|
|
54
|
+
}}
|
|
55
|
+
variants={{
|
|
56
|
+
hidden: { opacity: 0, y: -10 },
|
|
57
|
+
visible: { opacity: 1, y: 0 },
|
|
58
|
+
}}
|
|
59
|
+
initial="hidden"
|
|
60
|
+
animate={animation}
|
|
61
|
+
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
62
|
+
{...props}
|
|
63
|
+
>
|
|
64
|
+
<Menu
|
|
65
|
+
className={cn('outline-none', classNames?.menu)}
|
|
66
|
+
onAction={onAction}
|
|
67
|
+
>
|
|
68
|
+
{children}
|
|
69
|
+
</Menu>
|
|
70
|
+
</MotionPopover>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export default ContextMenu;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { PopoverProps as AriaPopoverProps } from 'react-aria-components';
|
|
2
|
+
import type { Dispatch, Key, SetStateAction, ReactNode } from 'react';
|
|
3
|
+
import type { MotionStyle } from 'framer-motion';
|
|
4
|
+
import type { SlotsToClasses } from '../../types/SlotsToClasses';
|
|
5
|
+
|
|
6
|
+
type ContextMenuAnimationState = 'unmounted' | 'hidden' | 'visible';
|
|
7
|
+
|
|
8
|
+
export interface PopoverProps
|
|
9
|
+
extends Omit<AriaPopoverProps, 'children' | 'style'> {
|
|
10
|
+
animation: ContextMenuAnimationState;
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
onAction?: (key: Key) => void;
|
|
13
|
+
setAnimation: Dispatch<SetStateAction<ContextMenuAnimationState>>;
|
|
14
|
+
key?: Key | null;
|
|
15
|
+
classNames?: SlotsToClasses<'menu'>;
|
|
16
|
+
style?: MotionStyle;
|
|
17
|
+
}
|