@kalink-ui/seedly 0.8.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/package.json +26 -18
  3. package/src/components/box/box.css.ts +6 -15
  4. package/src/components/box/box.tsx +2 -2
  5. package/src/components/box/index.ts +1 -1
  6. package/src/components/button/button.css.ts +45 -48
  7. package/src/components/button/button.tsx +11 -8
  8. package/src/components/button/index.ts +1 -1
  9. package/src/components/button-icon/button-icon.css.ts +90 -0
  10. package/src/components/button-icon/button-icon.tsx +23 -0
  11. package/src/components/button-icon/index.ts +1 -0
  12. package/src/components/card/card.css.ts +42 -0
  13. package/src/components/card/card.tsx +76 -0
  14. package/src/components/card/index.ts +1 -0
  15. package/src/components/center/center.css.ts +1 -1
  16. package/src/components/center/center.tsx +2 -2
  17. package/src/components/center/index.ts +1 -1
  18. package/src/components/cluster/cluster.css.ts +18 -1
  19. package/src/components/cluster/cluster.tsx +2 -2
  20. package/src/components/cluster/index.ts +1 -1
  21. package/src/components/cover/cover.css.ts +1 -1
  22. package/src/components/divider/divider.css.ts +11 -0
  23. package/src/components/divider/divider.tsx +11 -0
  24. package/src/components/divider/index.ts +1 -0
  25. package/src/components/form-field/form-field-context.ts +18 -0
  26. package/src/components/form-field/form-field-control.tsx +34 -0
  27. package/src/components/form-field/form-field-description.tsx +16 -0
  28. package/src/components/form-field/form-field-error.tsx +22 -0
  29. package/src/components/form-field/form-field-item-context.ts +6 -0
  30. package/src/components/form-field/form-field-item.tsx +28 -0
  31. package/src/components/form-field/form-field-label.tsx +27 -0
  32. package/src/components/form-field/form-field-message.tsx +33 -0
  33. package/src/components/form-field/form-field.css.ts +97 -0
  34. package/src/components/form-field/form-field.tsx +56 -0
  35. package/src/components/form-field/index.ts +9 -0
  36. package/src/components/frame/frame.css.ts +8 -8
  37. package/src/components/frame/frame.tsx +2 -6
  38. package/src/components/frame/index.ts +1 -1
  39. package/src/components/grid/grid.css.ts +1 -1
  40. package/src/components/heading/heading.css.ts +49 -2
  41. package/src/components/heading/heading.tsx +123 -69
  42. package/src/components/heading/index.ts +2 -1
  43. package/src/components/index.ts +27 -14
  44. package/src/components/input/index.ts +2 -0
  45. package/src/components/input/input-wrapper.tsx +58 -0
  46. package/src/components/input/input.css.ts +250 -0
  47. package/src/components/input/input.tsx +56 -0
  48. package/src/components/label/index.ts +1 -0
  49. package/src/components/label/label.css.ts +37 -0
  50. package/src/components/label/label.tsx +23 -0
  51. package/src/components/loader/index.ts +1 -0
  52. package/src/components/loader/loader.css.ts +109 -0
  53. package/src/components/loader/moon-loader.tsx +43 -0
  54. package/src/components/loader-overlay/index.ts +1 -0
  55. package/src/components/loader-overlay/loader-overlay.css.ts +35 -0
  56. package/src/components/loader-overlay/loader-overlay.tsx +28 -0
  57. package/src/components/menu/index.ts +2 -0
  58. package/src/components/menu/menu-item.css.ts +79 -0
  59. package/src/components/menu/menu-separator.css.ts +53 -0
  60. package/src/components/popover/index.ts +3 -0
  61. package/src/components/popover/popover-content.css.ts +107 -0
  62. package/src/components/popover/popover-content.tsx +78 -0
  63. package/src/components/popover/popover.tsx +6 -0
  64. package/src/components/scroll-area/index.ts +1 -0
  65. package/src/components/scroll-area/scroll-area.css.ts +72 -0
  66. package/src/components/scroll-area/scroll-area.tsx +39 -0
  67. package/src/components/scroll-area/scroll-bar.tsx +37 -0
  68. package/src/components/seed/index.ts +1 -1
  69. package/src/components/seed/seed.tsx +39 -2
  70. package/src/components/select/index.ts +5 -0
  71. package/src/components/select/select-content.css.ts +22 -0
  72. package/src/components/select/select-content.tsx +51 -0
  73. package/src/components/select/select-item.css.ts +24 -0
  74. package/src/components/select/select-item.tsx +24 -0
  75. package/src/components/select/select-root.tsx +14 -0
  76. package/src/components/select/select-trigger.css.ts +75 -0
  77. package/src/components/select/select-trigger.tsx +47 -0
  78. package/src/components/select/select.tsx +85 -0
  79. package/src/components/sheet/index.ts +5 -0
  80. package/src/components/sheet/sheet-content.css.ts +143 -0
  81. package/src/components/sheet/sheet-content.tsx +43 -0
  82. package/src/components/sheet/sheet-description.tsx +21 -0
  83. package/src/components/sheet/sheet-footer.tsx +15 -0
  84. package/src/components/sheet/sheet-header.css.ts +35 -0
  85. package/src/components/sheet/sheet-header.tsx +32 -0
  86. package/src/components/sheet/sheet-overlay.css.ts +43 -0
  87. package/src/components/sheet/sheet-overlay.tsx +14 -0
  88. package/src/components/sheet/sheet-title.tsx +31 -0
  89. package/src/components/sheet/sheet.tsx +8 -0
  90. package/src/components/stack/index.ts +1 -1
  91. package/src/components/stack/stack.tsx +2 -2
  92. package/src/components/text/index.ts +6 -0
  93. package/src/components/text/text.css.ts +173 -7
  94. package/src/components/text/text.tsx +19 -27
  95. package/src/components/text-field/index.ts +1 -0
  96. package/src/components/text-field/text-field.css.ts +3 -0
  97. package/src/components/text-field/text-field.tsx +64 -0
  98. package/src/components/textarea/index.ts +1 -0
  99. package/src/components/textarea/textarea-input.tsx +20 -0
  100. package/src/components/textarea/textarea.css.ts +10 -0
  101. package/src/components/textarea/textarea.tsx +69 -0
  102. package/src/styles/define-responsive-properties.ts +242 -0
  103. package/src/styles/extract-sprinkles-props.ts +29 -35
  104. package/src/styles/index.ts +9 -0
  105. package/src/styles/reset.css.ts +1 -0
  106. package/src/styles/system-contract.css.ts +0 -2
  107. package/src/styles/typography.css.ts +10 -5
  108. package/src/styles/visually-hidden.css.ts +21 -0
  109. package/build-storybook.log +0 -67
@@ -0,0 +1,21 @@
1
+ import { Description } from '@radix-ui/react-dialog';
2
+ import { ComponentPropsWithRef, ElementType } from 'react';
3
+
4
+ import { Text, TextProps } from '../text';
5
+
6
+ type SheetDescriptionPros<TUse extends ElementType> = ComponentPropsWithRef<
7
+ typeof Description
8
+ > &
9
+ TextProps<TUse>;
10
+
11
+ export function SheetDescription<TUse extends ElementType>({
12
+ ref,
13
+ children,
14
+ ...props
15
+ }: SheetDescriptionPros<TUse>) {
16
+ return (
17
+ <Description ref={ref} asChild {...props}>
18
+ <Text>{children}</Text>
19
+ </Description>
20
+ );
21
+ }
@@ -0,0 +1,15 @@
1
+ import { ElementType } from 'react';
2
+
3
+ import { Box, BoxProps } from '../box';
4
+
5
+ export function SheetFooter<TUse extends ElementType>(props: BoxProps<TUse>) {
6
+ return (
7
+ <Box
8
+ display="flex"
9
+ flexDirection={{ sm: 'column-reverse', md: 'row' }}
10
+ justifyContent={{ sm: 'flex-start', md: 'flex-end' }}
11
+ gap="sm"
12
+ {...props}
13
+ />
14
+ );
15
+ }
@@ -0,0 +1,35 @@
1
+ import { style } from '@vanilla-extract/css';
2
+ import { recipe } from '@vanilla-extract/recipes';
3
+
4
+ import { sys } from '../../styles';
5
+
6
+ export const sheetHeader = recipe({
7
+ base: {
8
+ display: 'flex',
9
+ alignItems: 'flex-start',
10
+ justifyContent: 'space-between',
11
+ flexWrap: 'nowrap',
12
+ gap: sys.spacing[4],
13
+ },
14
+
15
+ variants: {
16
+ side: {
17
+ top: {
18
+ flexDirection: 'row',
19
+ },
20
+ right: {
21
+ flexDirection: 'row-reverse',
22
+ },
23
+ bottom: {
24
+ flexDirection: 'row',
25
+ },
26
+ left: {
27
+ flexDirection: 'row',
28
+ },
29
+ },
30
+ },
31
+ });
32
+
33
+ export const sheetHeaderCloseBtn = style({
34
+ flexShrink: 0,
35
+ });
@@ -0,0 +1,32 @@
1
+ import { ElementType, ReactNode } from 'react';
2
+
3
+ import { Stack, StackProps } from '../stack';
4
+
5
+ import { SheetClose } from './sheet';
6
+ import { SheetContentVariants } from './sheet-content.css';
7
+ import { sheetHeader, sheetHeaderCloseBtn } from './sheet-header.css';
8
+
9
+ type SheetHeaderProps<TUse extends ElementType> = StackProps<TUse> & {
10
+ side: SheetContentVariants['side'];
11
+ closeBtn: ReactNode;
12
+ };
13
+
14
+ export function SheetHeader<TUse extends ElementType>({
15
+ ref,
16
+ spacing = 2,
17
+ children,
18
+ side,
19
+ closeBtn,
20
+ ...props
21
+ }: SheetHeaderProps<TUse>) {
22
+ return (
23
+ <div ref={ref} className={sheetHeader({ side })}>
24
+ <Stack spacing={spacing} {...props}>
25
+ {children}
26
+ </Stack>
27
+ <SheetClose asChild className={sheetHeaderCloseBtn}>
28
+ {closeBtn}
29
+ </SheetClose>
30
+ </div>
31
+ );
32
+ }
@@ -0,0 +1,43 @@
1
+ import { keyframes, style } from '@vanilla-extract/css';
2
+
3
+ import { sys } from '../../styles';
4
+
5
+ const enterAnimation = keyframes({
6
+ '0%': {
7
+ opacity: 0,
8
+ },
9
+ '100%': {
10
+ opacity: 1,
11
+ },
12
+ });
13
+
14
+ const exitAnimation = keyframes({
15
+ '0%': {
16
+ opacity: 1,
17
+ },
18
+ '100%': {
19
+ opacity: 0,
20
+ },
21
+ });
22
+
23
+ export const sheetOverlay = style({
24
+ zIndex: 50,
25
+
26
+ position: 'fixed',
27
+ inset: 0,
28
+
29
+ backgroundColor: `color(from ${sys.color.background} srgb r g b / 0.5)`,
30
+
31
+ animationDuration: sys.motion.duration.medium[2],
32
+ animationTimingFunction: sys.motion.easing.standard,
33
+ backdropFilter: 'blur(4px)',
34
+
35
+ selectors: {
36
+ '&[data-state="open"]': {
37
+ animationName: enterAnimation,
38
+ },
39
+ '&[data-state="closed"]': {
40
+ animationName: exitAnimation,
41
+ },
42
+ },
43
+ });
@@ -0,0 +1,14 @@
1
+ 'use client';
2
+
3
+ import { Overlay } from '@radix-ui/react-dialog';
4
+ import { clsx } from 'clsx';
5
+ import { ComponentPropsWithoutRef } from 'react';
6
+
7
+ import { sheetOverlay } from './sheet-overlay.css';
8
+
9
+ export function SheetOverlay({
10
+ className,
11
+ ...props
12
+ }: ComponentPropsWithoutRef<typeof Overlay>) {
13
+ return <Overlay className={clsx(sheetOverlay, className)} {...props} />;
14
+ }
@@ -0,0 +1,31 @@
1
+ 'use client';
2
+
3
+ import { Title } from '@radix-ui/react-dialog';
4
+ import { ComponentPropsWithRef } from 'react';
5
+
6
+ import { Heading, HeadingProps, HeadingTypes } from '../heading';
7
+
8
+ type SheetTitleProps<TUse extends HeadingTypes> = ComponentPropsWithRef<
9
+ typeof Title
10
+ > &
11
+ HeadingProps<TUse>;
12
+
13
+ export function SheetTitle<TUse extends HeadingTypes>(
14
+ props: SheetTitleProps<TUse>,
15
+ ) {
16
+ const { use = 'h2', className, children, variant, size, ...rest } = props;
17
+
18
+ return (
19
+ <Title asChild>
20
+ <Heading
21
+ use={use as HeadingProps<TUse>['use']}
22
+ variant={variant}
23
+ size={size}
24
+ className={className}
25
+ {...rest}
26
+ >
27
+ {children}
28
+ </Heading>
29
+ </Title>
30
+ );
31
+ }
@@ -0,0 +1,8 @@
1
+ 'use client';
2
+
3
+ import { Root, Trigger, Close, Portal } from '@radix-ui/react-dialog';
4
+
5
+ export const Sheet = Root;
6
+ export const SheetTrigger = Trigger;
7
+ export const SheetClose = Close;
8
+ export const SheetPortal = Portal;
@@ -1,2 +1,2 @@
1
- export { Stack } from './stack';
1
+ export { Stack, type StackProps } from './stack';
2
2
  export { stackRecipe, type StackVariants } from './stack.css';
@@ -4,8 +4,8 @@ import { ElementType } from 'react';
4
4
 
5
5
  import { stackRecipe, StackVariants } from './stack.css';
6
6
 
7
- type StackProps<TUse extends ElementType> = PolymorphicComponentProps<TUse> &
8
- StackVariants;
7
+ export type StackProps<TUse extends ElementType> =
8
+ PolymorphicComponentProps<TUse> & StackVariants;
9
9
 
10
10
  /**
11
11
  * A custom element for injecting white space (margin) between flow
@@ -1 +1,7 @@
1
1
  export { Text, type TextProps } from './text';
2
+ export {
3
+ textRecipe,
4
+ textAlign,
5
+ lineClampNumber,
6
+ type TextVariants,
7
+ } from './text.css';
@@ -1,25 +1,191 @@
1
- import { style } from '@vanilla-extract/css';
1
+ import { createVar, style } from '@vanilla-extract/css';
2
2
  import { recipe, type RecipeVariants } from '@vanilla-extract/recipes';
3
3
 
4
+ import { components } from '../../styles/layers.css';
5
+
6
+ export const lineClampNumber = createVar();
7
+ export const textAlign = createVar();
8
+
9
+ const lineClamp = style({
10
+ '@layer': {
11
+ [components]: {
12
+ display: '-webkit-box',
13
+ WebkitLineClamp: lineClampNumber,
14
+ WebkitBoxOrient: 'vertical',
15
+ overflow: 'hidden',
16
+ },
17
+ },
18
+ });
19
+
4
20
  export const textRecipe = recipe({
21
+ base: {
22
+ '@layer': {
23
+ [components]: {
24
+ textAlign,
25
+
26
+ vars: {
27
+ [textAlign]: 'inherit',
28
+ },
29
+ },
30
+ },
31
+ },
5
32
  variants: {
33
+ /**
34
+ * Controls the wrapping of the text.
35
+ */
36
+ wrap: {
37
+ true: {
38
+ '@layer': {
39
+ [components]: {
40
+ textWrap: 'wrap',
41
+ },
42
+ },
43
+ },
44
+ false: {
45
+ '@layer': {
46
+ [components]: {
47
+ textWrap: 'nowrap',
48
+ },
49
+ },
50
+ },
51
+ balance: {
52
+ '@layer': {
53
+ [components]: {
54
+ textWrap: 'balance',
55
+ },
56
+ },
57
+ },
58
+ pretty: {
59
+ '@layer': {
60
+ [components]: {
61
+ textWrap: 'pretty',
62
+ },
63
+ },
64
+ },
65
+ },
66
+
6
67
  /**
7
68
  * If true, use an ellipsis when the text overflows the element.
8
69
  */
9
- ellipsis: {
70
+ truncate: {
10
71
  true: {
11
- display: 'inline-block',
12
- maxWidth: '100%',
13
- overflow: 'hidden',
72
+ '@layer': {
73
+ [components]: {
74
+ display: 'inline-block',
75
+ maxWidth: '100%',
76
+ overflow: 'hidden',
77
+
78
+ textOverflow: 'ellipsis',
79
+ },
80
+ },
81
+ },
82
+ },
83
+
84
+ /**
85
+ * If provided, the text will be truncated and displayed with a maximum of
86
+ * the provided number of lines.
87
+ */
88
+ lineClamp: {
89
+ 2: [
90
+ lineClamp,
91
+ {
92
+ '@layer': {
93
+ [components]: {
94
+ vars: {
95
+ [lineClampNumber]: '2',
96
+ },
97
+ },
98
+ },
99
+ },
100
+ ],
101
+ 3: [
102
+ lineClamp,
103
+ {
104
+ '@layer': {
105
+ [components]: {
106
+ vars: {
107
+ [lineClampNumber]: '3',
108
+ },
109
+ },
110
+ },
111
+ },
112
+ ],
113
+ 4: [
114
+ lineClamp,
115
+ {
116
+ '@layer': {
117
+ [components]: {
118
+ vars: {
119
+ [lineClampNumber]: '4',
120
+ },
121
+ },
122
+ },
123
+ },
124
+ ],
125
+ 5: [
126
+ lineClamp,
127
+ {
128
+ '@layer': {
129
+ [components]: {
130
+ vars: {
131
+ [lineClampNumber]: '5',
132
+ },
133
+ },
134
+ },
135
+ },
136
+ ],
137
+ },
14
138
 
15
- textOverflow: 'ellipsis',
139
+ /**
140
+ * Controls the alignment of the text.
141
+ */
142
+ align: {
143
+ start: {
144
+ '@layer': {
145
+ [components]: {
146
+ vars: {
147
+ [textAlign]: 'start',
148
+ },
149
+ },
150
+ },
151
+ },
152
+ center: {
153
+ '@layer': {
154
+ [components]: {
155
+ vars: {
156
+ [textAlign]: 'center',
157
+ },
158
+ },
159
+ },
160
+ },
161
+ end: {
162
+ '@layer': {
163
+ [components]: {
164
+ vars: {
165
+ [textAlign]: 'end',
166
+ },
167
+ },
168
+ },
169
+ },
170
+ justify: {
171
+ '@layer': {
172
+ [components]: {
173
+ vars: {
174
+ [textAlign]: 'justify',
175
+ },
176
+ },
177
+ },
16
178
  },
17
179
  },
18
180
  },
19
181
  });
20
182
 
21
183
  export const textEllipsisWrapper = style({
22
- whiteSpace: 'nowrap',
184
+ '@layer': {
185
+ [components]: {
186
+ whiteSpace: 'nowrap',
187
+ },
188
+ },
23
189
  });
24
190
 
25
191
  export type TextVariants = NonNullable<RecipeVariants<typeof textRecipe>>;
@@ -1,8 +1,4 @@
1
- import {
2
- DistributiveOmit,
3
- PolymorphicComponentProps,
4
- getProp,
5
- } from '@kalink-ui/dibbly';
1
+ import { PolymorphicComponentProps, getProp } from '@kalink-ui/dibbly';
6
2
  import { clsx } from 'clsx';
7
3
  import { ElementType } from 'react';
8
4
 
@@ -10,48 +6,44 @@ import { TypographySize, TypographyVariant, typography } from '../../styles';
10
6
 
11
7
  import { TextVariants, textRecipe, textEllipsisWrapper } from './text.css';
12
8
 
13
- export type TextProps<TUse extends React.ElementType> = DistributiveOmit<
14
- PolymorphicComponentProps<TUse>,
15
- 'children'
16
- > &
17
- TextVariants & {
18
- /**
19
- * The size of the typography used to render the text.
20
- */
21
- size?: TypographySize;
9
+ export type TextProps<TUse extends React.ElementType> =
10
+ PolymorphicComponentProps<TUse> &
11
+ TextVariants & {
12
+ /**
13
+ * The size of the typography used to render the text.
14
+ */
15
+ size?: TypographySize;
22
16
 
23
- /**
24
- * The typography variant used to render the text.
25
- */
26
- variant?: Extract<TypographyVariant, 'body' | 'caption' | 'label'>;
27
-
28
- /**
29
- * The text to render.
30
- */
31
- children: string;
32
- };
17
+ /**
18
+ * The typography variant used to render the text.
19
+ */
20
+ variant?: TypographyVariant;
21
+ };
33
22
 
34
23
  export function Text<TUse extends ElementType>(props: TextProps<TUse>) {
35
24
  const {
36
25
  children,
37
26
  className,
38
- ellipsis,
27
+ truncate,
28
+ lineClamp,
39
29
  size = 'medium',
40
30
  use: Comp = 'span',
41
31
  variant = 'body',
32
+ wrap,
33
+ align,
42
34
  ...rest
43
35
  } = props;
44
36
 
45
37
  return (
46
38
  <Comp
47
39
  className={clsx(
48
- textRecipe({ ellipsis }),
49
40
  getProp(typography, `${variant}.${size}`),
41
+ textRecipe({ truncate, lineClamp, align, wrap }),
50
42
  className,
51
43
  )}
52
44
  {...rest}
53
45
  >
54
- {ellipsis ? (
46
+ {truncate ? (
55
47
  <span className={textEllipsisWrapper}>{children}</span>
56
48
  ) : (
57
49
  children
@@ -0,0 +1 @@
1
+ export { TextField } from './text-field';
@@ -0,0 +1,3 @@
1
+ import { style } from '@vanilla-extract/css';
2
+
3
+ export const textFieldStyle = style({});
@@ -0,0 +1,64 @@
1
+ 'use client';
2
+
3
+ import {
4
+ FormField,
5
+ FormFieldControl,
6
+ FormFieldDescription,
7
+ FormFieldError,
8
+ FormFieldItem,
9
+ FormFieldLabel,
10
+ } from '../form-field';
11
+ import { Input, InputProps } from '../input';
12
+
13
+ export type TextFieldProps = InputProps & {
14
+ name: string;
15
+ label: string;
16
+ description?: string;
17
+ wrapperClassName?: string;
18
+ hideLabel?: boolean;
19
+ errors?: string | null;
20
+ hideErrorMessage?: boolean;
21
+ };
22
+
23
+ export function TextField({
24
+ description,
25
+ disabled,
26
+ label,
27
+ name,
28
+ hideLabel = false,
29
+ errors,
30
+ required,
31
+ hideErrorMessage = false,
32
+ size = 'md',
33
+ ...rest
34
+ }: TextFieldProps) {
35
+ return (
36
+ <FormField
37
+ name={name}
38
+ label={label}
39
+ errors={errors}
40
+ hideErrorMessage={hideErrorMessage}
41
+ disabled={disabled}
42
+ hideLabel={hideLabel}
43
+ >
44
+ <FormFieldItem>
45
+ <FormFieldLabel required={required} disabled={disabled} size={size}>
46
+ {label}
47
+ </FormFieldLabel>
48
+
49
+ <FormFieldControl>
50
+ <Input
51
+ name={name}
52
+ disabled={disabled}
53
+ required={required}
54
+ size={size}
55
+ {...rest}
56
+ />
57
+ </FormFieldControl>
58
+
59
+ <FormFieldDescription>{description}</FormFieldDescription>
60
+ <FormFieldError />
61
+ </FormFieldItem>
62
+ </FormField>
63
+ );
64
+ }
@@ -0,0 +1 @@
1
+ export { Textarea } from './textarea';
@@ -0,0 +1,20 @@
1
+ import { clsx } from 'clsx';
2
+ import { TextareaHTMLAttributes } from 'react';
3
+
4
+ import { useFormFieldContext } from '../form-field/form-field-context';
5
+ import { textarea } from '../textarea/textarea.css';
6
+
7
+ export function TextareaInput({
8
+ className,
9
+ ...props
10
+ }: TextareaHTMLAttributes<HTMLTextAreaElement>) {
11
+ const { errors } = useFormFieldContext();
12
+
13
+ return (
14
+ <textarea
15
+ className={clsx(textarea, className)}
16
+ aria-invalid={errors ? 'true' : undefined}
17
+ {...props}
18
+ />
19
+ );
20
+ }
@@ -0,0 +1,10 @@
1
+ import { style } from '@vanilla-extract/css';
2
+
3
+ import { inputAppearance } from '../input';
4
+
5
+ export const textarea = style([
6
+ inputAppearance(),
7
+ {
8
+ lineHeight: 'auto',
9
+ },
10
+ ]);
@@ -0,0 +1,69 @@
1
+ 'use client';
2
+
3
+ import { TextareaHTMLAttributes } from 'react';
4
+
5
+ import {
6
+ FormField,
7
+ FormFieldControl,
8
+ FormFieldDescription,
9
+ FormFieldError,
10
+ FormFieldItem,
11
+ FormFieldLabel,
12
+ } from '../form-field';
13
+ import { InputProps } from '../input';
14
+
15
+ import { TextareaInput } from './textarea-input';
16
+
17
+ export type TextareaProps = TextareaHTMLAttributes<HTMLTextAreaElement> &
18
+ InputProps & {
19
+ name: string;
20
+ label: string;
21
+ description?: string;
22
+ hideLabel?: boolean;
23
+ errors: string;
24
+ hideErrorMessage?: boolean;
25
+ };
26
+
27
+ export function Textarea({
28
+ className,
29
+ description,
30
+ disabled,
31
+ label,
32
+ name,
33
+ hideLabel = false,
34
+ errors,
35
+ required,
36
+ hideErrorMessage = false,
37
+ size = 'md',
38
+ ...rest
39
+ }: TextareaProps) {
40
+ return (
41
+ <FormField
42
+ name={name}
43
+ label={label}
44
+ errors={errors}
45
+ hideErrorMessage={hideErrorMessage}
46
+ disabled={disabled}
47
+ hideLabel={hideLabel}
48
+ >
49
+ <FormFieldItem>
50
+ <FormFieldLabel disabled={disabled} required={required} size={size}>
51
+ {label}
52
+ </FormFieldLabel>
53
+
54
+ <FormFieldControl>
55
+ <TextareaInput
56
+ name={name}
57
+ className={className}
58
+ disabled={disabled}
59
+ aria-label={hideLabel ? label : undefined}
60
+ {...rest}
61
+ />
62
+ </FormFieldControl>
63
+
64
+ <FormFieldDescription>{description}</FormFieldDescription>
65
+ <FormFieldError />
66
+ </FormFieldItem>
67
+ </FormField>
68
+ );
69
+ }