-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.tsx
104 lines (91 loc) · 2.89 KB
/
index.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
'use client';
import React, { ComponentProps, forwardRef } from 'react';
import classnames from 'classnames';
import { oneOf } from 'prop-types';
import { twMerge } from 'tailwind-merge';
import { useTheme } from '@/uikit/context/theme';
import { ButtonStyleProps } from '@/uikit/theme';
import type {
ButtonVariant,
ButtonSize,
ButtonColor,
ButtonFullWidth,
ButtonClassName,
ButtonChildren,
} from '@/uikit/types/components/button';
import {
ButtonPropTypesVariant,
ButtonPropTypesSize,
ButtonPropTypesColor,
ButtonPropTypesFullWidth,
ButtonPropTypesClassName,
ButtonPropTypesChildren,
} from '@/uikit/types/components/button';
import findMatch from '@/uikit/utils/findMatch';
import objectsToString from '@/uikit/utils/objectsToString';
export interface ButtonProps extends ComponentProps<'button'> {
size?: ButtonSize;
color?: ButtonColor;
rounded?: boolean;
variant?: ButtonVariant;
children: ButtonChildren;
fullWidth?: ButtonFullWidth;
className?: ButtonClassName;
}
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ variant, size, color, fullWidth, className, children, rounded, ...rest }, ref) => {
// 1. init
const { button } = useTheme();
const { valid, defaultProps, styles } = button;
const { base, variants, sizes } = styles;
// 2. set default props
size = size ?? defaultProps.size;
color = color ?? defaultProps.color;
rounded = rounded ?? defaultProps.rounded;
variant = variant ?? defaultProps.variant;
fullWidth = fullWidth ?? defaultProps.fullWidth;
className = className ?? defaultProps.className;
// 4. set styles
const buttonBase = objectsToString(base.initial);
const buttonVariant = objectsToString(
variants[findMatch(valid.variants, variant, 'filled') as keyof ButtonStyleProps['variants']][
findMatch(valid.colors, color, 'white')
],
);
const buttonSize = objectsToString(
sizes[findMatch(valid.sizes, size, 'md') as keyof ButtonStyleProps['sizes']],
);
const classes = twMerge(
classnames(buttonBase, buttonSize, buttonVariant, {
[objectsToString(base.rounded)]: rounded,
[objectsToString(base.fullWidth)]: fullWidth,
}),
className,
);
// 5. return
return (
<button
{...rest}
ref={ref}
className={classes}
type={rest.type || 'button'}
onMouseDown={(e) => {
const onMouseDown = rest?.onMouseDown;
return typeof onMouseDown === 'function' && onMouseDown(e);
}}
>
{children}
</button>
);
},
);
Button.propTypes = {
size: oneOf(ButtonPropTypesSize),
children: ButtonPropTypesChildren,
color: oneOf(ButtonPropTypesColor),
fullWidth: ButtonPropTypesFullWidth,
className: ButtonPropTypesClassName,
variant: oneOf(ButtonPropTypesVariant),
};
Button.displayName = 'WebaverseTailwind.Button';
export default Button;