@kalink-ui/seedly 0.9.0 → 0.11.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 (108) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/package.json +14 -6
  3. package/src/components/box/box.css.ts +2 -2
  4. package/src/components/button/button.css.ts +52 -50
  5. package/src/components/button/button.tsx +15 -12
  6. package/src/components/button/index.ts +1 -1
  7. package/src/components/button-icon/button-icon.css.ts +90 -0
  8. package/src/components/button-icon/button-icon.tsx +23 -0
  9. package/src/components/button-icon/index.ts +1 -0
  10. package/src/components/card/card.tsx +7 -4
  11. package/src/components/card/index.ts +1 -1
  12. package/src/components/center/center.tsx +2 -2
  13. package/src/components/center/index.ts +1 -1
  14. package/src/components/cluster/cluster.css.ts +17 -0
  15. package/src/components/command/command-empty.tsx +14 -0
  16. package/src/components/command/command-group.css.ts +34 -0
  17. package/src/components/command/command-group.tsx +19 -0
  18. package/src/components/command/command-input.css.ts +31 -0
  19. package/src/components/command/command-input.tsx +44 -0
  20. package/src/components/command/command-item.css.ts +27 -0
  21. package/src/components/command/command-item.tsx +35 -0
  22. package/src/components/command/command-list.css.ts +14 -0
  23. package/src/components/command/command-list.tsx +19 -0
  24. package/src/components/command/command-separator.tsx +29 -0
  25. package/src/components/command/command.tsx +24 -0
  26. package/src/components/command/index.ts +7 -0
  27. package/src/components/cover/index.ts +1 -1
  28. package/src/components/divider/divider.css.ts +11 -0
  29. package/src/components/divider/divider.tsx +11 -0
  30. package/src/components/divider/index.ts +1 -0
  31. package/src/components/form-field/form-field-context.ts +18 -0
  32. package/src/components/form-field/form-field-control.tsx +34 -0
  33. package/src/components/form-field/form-field-description.tsx +16 -0
  34. package/src/components/form-field/form-field-error.tsx +22 -0
  35. package/src/components/form-field/form-field-item-context.ts +6 -0
  36. package/src/components/form-field/form-field-item.tsx +28 -0
  37. package/src/components/form-field/form-field-label.tsx +27 -0
  38. package/src/components/form-field/form-field-message.tsx +33 -0
  39. package/src/components/form-field/form-field.css.ts +97 -0
  40. package/src/components/form-field/form-field.tsx +56 -0
  41. package/src/components/form-field/index.ts +9 -0
  42. package/src/components/frame/frame.css.ts +8 -8
  43. package/src/components/frame/frame.tsx +2 -6
  44. package/src/components/frame/index.ts +1 -1
  45. package/src/components/heading/heading.tsx +43 -8
  46. package/src/components/index.ts +29 -15
  47. package/src/components/input/index.ts +2 -0
  48. package/src/components/input/input-wrapper.tsx +58 -0
  49. package/src/components/input/input.css.ts +250 -0
  50. package/src/components/input/input.tsx +56 -0
  51. package/src/components/label/index.ts +1 -0
  52. package/src/components/label/label.css.ts +37 -0
  53. package/src/components/label/label.tsx +23 -0
  54. package/src/components/loader/index.ts +1 -0
  55. package/src/components/loader/loader.css.ts +109 -0
  56. package/src/components/loader/moon-loader.tsx +43 -0
  57. package/src/components/loader-overlay/index.ts +1 -0
  58. package/src/components/loader-overlay/loader-overlay.css.ts +35 -0
  59. package/src/components/loader-overlay/loader-overlay.tsx +28 -0
  60. package/src/components/menu/index.ts +2 -0
  61. package/src/components/menu/menu-item.css.ts +79 -0
  62. package/src/components/menu/menu-separator.css.ts +53 -0
  63. package/src/components/popover/index.ts +3 -0
  64. package/src/components/popover/popover-content.css.ts +107 -0
  65. package/src/components/popover/popover-content.tsx +82 -0
  66. package/src/components/popover/popover.tsx +6 -0
  67. package/src/components/scroll-area/index.ts +1 -0
  68. package/src/components/scroll-area/scroll-area.css.ts +72 -0
  69. package/src/components/scroll-area/scroll-area.tsx +39 -0
  70. package/src/components/scroll-area/scroll-bar.tsx +37 -0
  71. package/src/components/seed/seed.tsx +4 -4
  72. package/src/components/select/index.ts +5 -0
  73. package/src/components/select/select-content.css.ts +22 -0
  74. package/src/components/select/select-content.tsx +51 -0
  75. package/src/components/select/select-item.css.ts +24 -0
  76. package/src/components/select/select-item.tsx +24 -0
  77. package/src/components/select/select-root.tsx +14 -0
  78. package/src/components/select/select-trigger.css.ts +75 -0
  79. package/src/components/select/select-trigger.tsx +47 -0
  80. package/src/components/select/select.tsx +85 -0
  81. package/src/components/sheet/index.ts +5 -0
  82. package/src/components/sheet/sheet-content.css.ts +143 -0
  83. package/src/components/sheet/sheet-content.tsx +43 -0
  84. package/src/components/sheet/sheet-description.tsx +21 -0
  85. package/src/components/sheet/sheet-footer.tsx +15 -0
  86. package/src/components/sheet/sheet-header.css.ts +35 -0
  87. package/src/components/sheet/sheet-header.tsx +32 -0
  88. package/src/components/sheet/sheet-overlay.css.ts +43 -0
  89. package/src/components/sheet/sheet-overlay.tsx +14 -0
  90. package/src/components/sheet/sheet-title.tsx +31 -0
  91. package/src/components/sheet/sheet.tsx +8 -0
  92. package/src/components/stack/index.ts +1 -1
  93. package/src/components/stack/stack.css.ts +5 -1
  94. package/src/components/stack/stack.tsx +2 -2
  95. package/src/components/text/index.ts +6 -0
  96. package/src/components/text/text.css.ts +31 -4
  97. package/src/components/text-field/index.ts +1 -0
  98. package/src/components/text-field/text-field.css.ts +3 -0
  99. package/src/components/text-field/text-field.tsx +64 -0
  100. package/src/components/textarea/index.ts +1 -0
  101. package/src/components/textarea/textarea-input.tsx +20 -0
  102. package/src/components/textarea/textarea.css.ts +10 -0
  103. package/src/components/textarea/textarea.tsx +69 -0
  104. package/src/styles/define-responsive-properties.ts +242 -0
  105. package/src/styles/extract-sprinkles-props.ts +29 -35
  106. package/src/styles/index.ts +9 -0
  107. package/src/styles/reset.css.ts +1 -0
  108. package/src/styles/visually-hidden.css.ts +21 -0
@@ -3,7 +3,7 @@ import { recipe, type RecipeVariants } from '@vanilla-extract/recipes';
3
3
 
4
4
  import { components } from '../../styles/layers.css';
5
5
 
6
- const ratioVar = createVar();
6
+ export const frameRatioVar = createVar();
7
7
 
8
8
  const baseFrame = style({
9
9
  '@layer': {
@@ -14,7 +14,7 @@ const baseFrame = style({
14
14
 
15
15
  overflow: 'hidden',
16
16
 
17
- aspectRatio: ratioVar,
17
+ aspectRatio: frameRatioVar,
18
18
  },
19
19
  },
20
20
  });
@@ -31,7 +31,7 @@ export const frameRecipe = recipe({
31
31
  '@layer': {
32
32
  [components]: {
33
33
  vars: {
34
- [ratioVar]: '1 / 1',
34
+ [frameRatioVar]: '1 / 1',
35
35
  },
36
36
  },
37
37
  },
@@ -40,7 +40,7 @@ export const frameRecipe = recipe({
40
40
  '@layer': {
41
41
  [components]: {
42
42
  vars: {
43
- [ratioVar]: '3 / 2',
43
+ [frameRatioVar]: '3 / 2',
44
44
  },
45
45
  },
46
46
  },
@@ -49,7 +49,7 @@ export const frameRecipe = recipe({
49
49
  '@layer': {
50
50
  [components]: {
51
51
  vars: {
52
- [ratioVar]: '2 / 3',
52
+ [frameRatioVar]: '2 / 3',
53
53
  },
54
54
  },
55
55
  },
@@ -58,7 +58,7 @@ export const frameRecipe = recipe({
58
58
  '@layer': {
59
59
  [components]: {
60
60
  vars: {
61
- [ratioVar]: '4 / 3',
61
+ [frameRatioVar]: '4 / 3',
62
62
  },
63
63
  },
64
64
  },
@@ -67,7 +67,7 @@ export const frameRecipe = recipe({
67
67
  '@layer': {
68
68
  [components]: {
69
69
  vars: {
70
- [ratioVar]: '16 / 9',
70
+ [frameRatioVar]: '16 / 9',
71
71
  },
72
72
  },
73
73
  },
@@ -76,7 +76,7 @@ export const frameRecipe = recipe({
76
76
  '@layer': {
77
77
  [components]: {
78
78
  vars: {
79
- [ratioVar]: '9 / 16',
79
+ [frameRatioVar]: '9 / 16',
80
80
  },
81
81
  },
82
82
  },
@@ -12,12 +12,8 @@ type FrameProps<TUse extends ElementType> = PolymorphicComponentProps<TUse> &
12
12
  *
13
13
  * https://every-layout.dev/layouts/frame
14
14
  */
15
- export function Frame<TUse extends ElementType>({
16
- ratio,
17
- className,
18
- ...props
19
- }: FrameProps<TUse>) {
20
- const { use: Comp = 'div', ...rest } = props;
15
+ export function Frame<TUse extends ElementType>(props: FrameProps<TUse>) {
16
+ const { use: Comp = 'div', className, ratio, ...rest } = props;
21
17
 
22
18
  return <Comp className={clsx(frameRecipe({ ratio }), className)} {...rest} />;
23
19
  }
@@ -1,2 +1,2 @@
1
1
  export { Frame } from './frame';
2
- export { frameRecipe, type FrameVariants } from './frame.css';
2
+ export { frameRecipe, frameRatioVar, type FrameVariants } from './frame.css';
@@ -1,5 +1,5 @@
1
1
  import { clsx } from 'clsx';
2
- import { ElementType, ReactElement } from 'react';
2
+ import { ElementType, ReactElement, ReactNode } from 'react';
3
3
 
4
4
  import { Spacing, TypographySize, TypographyVariant } from '../../styles';
5
5
  import { ConditionalWrapper } from '../conditional-wrapper';
@@ -11,8 +11,12 @@ export type HeadingTypes = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
11
11
 
12
12
  export type HeadingProps<TUse extends ElementType = 'h2'> = Omit<
13
13
  TextProps<TUse>,
14
- 'variant' | 'children'
14
+ 'variant' | 'children' | 'align'
15
15
  > & {
16
+ align?: Extract<
17
+ Pick<TextProps<TUse>, 'align'>['align'],
18
+ 'start' | 'center' | 'end'
19
+ >;
16
20
  /**
17
21
  * The typography used to render the text.
18
22
  */
@@ -36,7 +40,12 @@ export type HeadingProps<TUse extends ElementType = 'h2'> = Omit<
36
40
  /**
37
41
  * The text to render.
38
42
  */
39
- children: string;
43
+ children: ReactNode;
44
+
45
+ /**
46
+ * The class to pass to the root element.
47
+ */
48
+ rootClassName?: string;
40
49
  };
41
50
 
42
51
  const headingMapping: Record<
@@ -60,17 +69,21 @@ export function Heading<TUse extends HeadingTypes>({
60
69
  spacing,
61
70
  pretitle,
62
71
  subtitle,
72
+ rootClassName,
73
+ ref,
63
74
  ...rest
64
75
  }: HeadingProps<TUse>) {
65
76
  return (
66
77
  <ConditionalWrapper
78
+ ref={ref}
67
79
  use={'hgroup'}
68
80
  condition={!!pretitle || !!subtitle}
69
- className={clsx(headingRoot({ align, spacing }))}
81
+ className={clsx(headingRoot({ align, spacing }), rootClassName)}
70
82
  >
71
83
  {pretitle}
72
84
 
73
85
  <Text
86
+ {...(!pretitle && !subtitle && { ref })}
74
87
  use={use}
75
88
  align={align}
76
89
  variant={variant ?? headingMapping[use].variant}
@@ -85,18 +98,40 @@ export function Heading<TUse extends HeadingTypes>({
85
98
  );
86
99
  }
87
100
 
101
+ type HeadingPretitleProps = Omit<TextProps<'p'>, 'children'> & {
102
+ children?: string | null;
103
+ };
104
+
88
105
  Heading.Pretitle = function HeadingPretitle({
89
106
  variant = 'title',
90
107
  size = 'medium',
108
+ children,
91
109
  ...rest
92
- }: TextProps<'p'>) {
93
- return <Text use="p" variant={variant} size={size} {...rest} />;
110
+ }: HeadingPretitleProps) {
111
+ return (
112
+ children && (
113
+ <Text use="p" variant={variant} size={size} {...rest}>
114
+ {children}
115
+ </Text>
116
+ )
117
+ );
118
+ };
119
+
120
+ type HeadingSubtitleProps = Omit<TextProps<'p'>, 'children'> & {
121
+ children?: string | null;
94
122
  };
95
123
 
96
124
  Heading.Subtitle = function HeadingSubtitle({
97
125
  variant = 'title',
98
126
  size = 'medium',
127
+ children,
99
128
  ...rest
100
- }: TextProps<'p'>) {
101
- return <Text use="p" variant={variant} size={size} {...rest} />;
129
+ }: HeadingSubtitleProps) {
130
+ return (
131
+ children && (
132
+ <Text use="p" variant={variant} size={size} {...rest}>
133
+ {children}
134
+ </Text>
135
+ )
136
+ );
102
137
  };
@@ -1,15 +1,29 @@
1
- export { Box } from './box';
2
- export { Button } from './button';
3
- export { Card } from './card';
4
- export { Center } from './center';
5
- export { Cluster } from './cluster';
6
- export { ConditionalWrapper } from './conditional-wrapper';
7
- export { Cover } from './cover';
8
- export { Frame } from './frame';
9
- export { Grid } from './grid';
10
- export { Heading } from './heading';
11
- export { plantSeed, withSeed } from './seed';
12
- export { Sidebar } from './sidebar';
13
- export { Stack } from './stack';
14
- export { Switcher } from './switcher';
15
- export { Text } from './text';
1
+ export * from './box';
2
+ export * from './button';
3
+ export * from './button-icon';
4
+ export * from './card';
5
+ export * from './center';
6
+ export * from './cluster';
7
+ export * from './command';
8
+ export * from './conditional-wrapper';
9
+ export * from './cover';
10
+ export * from './divider';
11
+ export * from './form-field';
12
+ export * from './frame';
13
+ export * from './grid';
14
+ export * from './heading';
15
+ export * from './input';
16
+ export * from './label';
17
+ export * from './loader';
18
+ export * from './loader-overlay';
19
+ export * from './popover';
20
+ export * from './scroll-area';
21
+ export * from './seed';
22
+ export * from './select';
23
+ export * from './sheet';
24
+ export * from './sidebar';
25
+ export * from './stack';
26
+ export * from './switcher';
27
+ export * from './text';
28
+ export * from './text-field';
29
+ export * from './textarea';
@@ -0,0 +1,2 @@
1
+ export { Input, type InputProps } from './input';
2
+ export { inputAppearance, type InputAppearanceVariants } from './input.css';
@@ -0,0 +1,58 @@
1
+ import { clsx } from 'clsx';
2
+ import {
3
+ ComponentPropsWithRef,
4
+ ForwardedRef,
5
+ MouseEventHandler,
6
+ ReactNode,
7
+ RefObject,
8
+ useCallback,
9
+ } from 'react';
10
+
11
+ import {
12
+ inputAppearance,
13
+ InputAppearanceVariants,
14
+ inputWrapper,
15
+ } from './input.css';
16
+
17
+ export type InputWrapperProps = ComponentPropsWithRef<'div'> & {
18
+ children: ReactNode;
19
+ className?: string;
20
+ inputRef: RefObject<HTMLInputElement | null>;
21
+ disabled?: boolean;
22
+ } & InputAppearanceVariants;
23
+
24
+ export function InputWrapper({
25
+ children,
26
+ className,
27
+ inputRef,
28
+ disabled,
29
+ variant = 'outlined',
30
+ size = 'md',
31
+ ref,
32
+ }: InputWrapperProps) {
33
+ const handleInputFocus = useCallback<MouseEventHandler<HTMLElement>>(
34
+ (e) => {
35
+ if (disabled || !inputRef?.current || e.target === inputRef.current) {
36
+ return;
37
+ }
38
+
39
+ inputRef.current.click();
40
+ inputRef.current.focus();
41
+ },
42
+ [inputRef, disabled],
43
+ );
44
+
45
+ return (
46
+ <div
47
+ ref={ref as ForwardedRef<HTMLDivElement>}
48
+ className={clsx(
49
+ inputAppearance({ variant, size }),
50
+ inputWrapper,
51
+ className,
52
+ )}
53
+ onClick={handleInputFocus}
54
+ >
55
+ {children}
56
+ </div>
57
+ );
58
+ }
@@ -0,0 +1,250 @@
1
+ import { style, globalStyle, createGlobalTheme } from '@vanilla-extract/css';
2
+ import { recipe, RecipeVariants } from '@vanilla-extract/recipes';
3
+
4
+ import { sys, transition, typography } from '../../styles';
5
+ import { components } from '../../styles/layers.css';
6
+
7
+ export const inputVars = createGlobalTheme(':root', {
8
+ '@layer': components,
9
+
10
+ color: {
11
+ foreground: 'inherit',
12
+ background: sys.color.background,
13
+ outline: sys.color.foreground,
14
+ error: 'red',
15
+ },
16
+
17
+ spacing: {
18
+ block: sys.spacing[2],
19
+ inline: sys.spacing[4],
20
+ },
21
+
22
+ shape: {
23
+ corner: sys.shape.corner.none,
24
+ },
25
+ });
26
+
27
+ export const inputAppearance = recipe({
28
+ base: [
29
+ {
30
+ '@layer': {
31
+ [components]: {
32
+ boxSizing: 'border-box',
33
+ position: 'relative',
34
+
35
+ color: inputVars.color.foreground,
36
+
37
+ backgroundColor: 'transparent',
38
+ borderRadius: inputVars.shape.corner,
39
+
40
+ cursor: 'inherit',
41
+
42
+ transition: transition(
43
+ ['background-color', 'border-color', 'box-shadow'],
44
+ {
45
+ duration: 'short.2',
46
+ },
47
+ ),
48
+
49
+ selectors: {
50
+ '&:disabled, &:has(:disabled)': {
51
+ backgroundColor: `color-mix(in srgb, ${inputVars.color.foreground} calc(${sys.state.muted.dark} * 100%), transparent)`,
52
+
53
+ vars: {
54
+ [inputVars.color.foreground]:
55
+ `color(from ${sys.color.foreground} srgb r g b / 0.38)`,
56
+ },
57
+ },
58
+
59
+ '&:focus, &:focus-within, &:focus-visible': {
60
+ boxShadow: `0 0 0 1px ${inputVars.color.outline} inset`,
61
+ outline: 'none',
62
+ },
63
+
64
+ '&[aria-invalid], &:has([aria-invalid])': {
65
+ vars: {
66
+ [inputVars.color.foreground]: 'red',
67
+ },
68
+ },
69
+ },
70
+
71
+ vars: {
72
+ [inputVars.color.foreground]: sys.color.foreground,
73
+ [inputVars.color.background]: sys.color.background,
74
+ [inputVars.color.outline]: inputVars.color.foreground,
75
+ [inputVars.spacing.block]: sys.spacing[2],
76
+ [inputVars.spacing.inline]: sys.spacing[4],
77
+ },
78
+ },
79
+ },
80
+ },
81
+ ],
82
+
83
+ variants: {
84
+ variant: {
85
+ outlined: {
86
+ '@layer': {
87
+ [components]: {
88
+ paddingInline: inputVars.spacing.inline,
89
+ paddingBlock: inputVars.spacing.block,
90
+
91
+ borderColor: inputVars.color.outline,
92
+ borderStyle: 'solid',
93
+ borderWidth: 1,
94
+ },
95
+ },
96
+ },
97
+
98
+ plain: {
99
+ '@layer': {
100
+ [components]: {
101
+ paddingInline: inputVars.spacing.inline,
102
+ paddingBlock: inputVars.spacing.block,
103
+
104
+ backgroundColor: inputVars.color.background,
105
+ borderRadius: inputVars.shape.corner,
106
+
107
+ vars: {
108
+ [inputVars.color.background]:
109
+ `color-mix(in srgb, ${inputVars.color.foreground} calc(${sys.state.muted.dark} * 100%), transparent)`,
110
+ },
111
+ },
112
+ },
113
+ },
114
+
115
+ bare: {},
116
+ },
117
+
118
+ size: {
119
+ sm: [
120
+ typography.body.small,
121
+ {
122
+ '@layer': {
123
+ [components]: {
124
+ /**
125
+ * Force the font size to 16px to avoid zooming on mobile
126
+ */
127
+ fontSize: `max(16px, ${sys.typography.body.small.size})`,
128
+
129
+ vars: {
130
+ [inputVars.spacing.block]: sys.spacing[1],
131
+ [inputVars.spacing.inline]: sys.spacing[1],
132
+ },
133
+ },
134
+ },
135
+ },
136
+ ],
137
+
138
+ md: [
139
+ typography.body.medium,
140
+ {
141
+ '@layer': {
142
+ [components]: {
143
+ /**
144
+ * Force the font size to 16px to avoid zooming on mobile
145
+ */
146
+ fontSize: `max(16px, ${sys.typography.body.medium.size})`,
147
+
148
+ vars: {
149
+ [inputVars.spacing.block]: sys.spacing[2],
150
+ [inputVars.spacing.inline]: sys.spacing[2],
151
+ },
152
+ },
153
+ },
154
+ },
155
+ ],
156
+
157
+ lg: [
158
+ typography.body.large,
159
+ {
160
+ '@layer': {
161
+ [components]: {
162
+ /**
163
+ * Force the font size to 16px to avoid zooming on mobile
164
+ */
165
+ fontSize: `max(16px, ${sys.typography.body.large.size})`,
166
+
167
+ vars: {
168
+ [inputVars.spacing.block]: sys.spacing[3],
169
+ [inputVars.spacing.inline]: sys.spacing[3],
170
+ },
171
+ },
172
+ },
173
+ },
174
+ ],
175
+ },
176
+ },
177
+
178
+ defaultVariants: {
179
+ variant: 'outlined',
180
+ size: 'md',
181
+ },
182
+ });
183
+
184
+ export const inputWrapper = style({
185
+ '@layer': {
186
+ [components]: {
187
+ display: 'flex',
188
+ alignItems: 'center',
189
+ justifyContent: 'space-between',
190
+ gap: inputVars.spacing.inline,
191
+
192
+ width: '100%',
193
+
194
+ position: 'relative',
195
+
196
+ cursor: 'text',
197
+
198
+ selectors: {
199
+ '&:disabled, &:has(:disabled)': {
200
+ cursor: 'inherit',
201
+ },
202
+ },
203
+ },
204
+ },
205
+ });
206
+
207
+ export const input = style({
208
+ '@layer': {
209
+ [components]: {
210
+ appearance: 'none',
211
+
212
+ flexGrow: 1,
213
+ flexBasis: 1,
214
+
215
+ paddingTop: 0,
216
+ paddingBottom: 0,
217
+
218
+ color: 'inherit',
219
+
220
+ border: 'none',
221
+ backgroundColor: 'transparent',
222
+ cursor: 'inherit',
223
+ },
224
+ },
225
+ });
226
+
227
+ export const inputAddornment = style({
228
+ '@layer': {
229
+ [components]: {
230
+ flexShrink: 0,
231
+
232
+ color: 'inherit',
233
+ },
234
+ },
235
+ });
236
+
237
+ globalStyle(
238
+ `${inputAppearance.classNames.base} input:is(:focus, :focus-visible)`,
239
+ {
240
+ '@layer': {
241
+ [components]: {
242
+ outline: 'none',
243
+ },
244
+ },
245
+ },
246
+ );
247
+
248
+ export type InputAppearanceVariants = NonNullable<
249
+ RecipeVariants<typeof inputAppearance>
250
+ >;
@@ -0,0 +1,56 @@
1
+ 'use client';
2
+
3
+ import { mergeRefs } from '@kalink-ui/dibbly';
4
+ import { clsx } from 'clsx';
5
+ import { ComponentPropsWithRef, ReactNode, RefObject, useRef } from 'react';
6
+
7
+ import { useFormFieldContext } from '../form-field/form-field-context';
8
+
9
+ import { InputWrapper } from './input-wrapper';
10
+ import { InputAppearanceVariants, input, inputAddornment } from './input.css';
11
+
12
+ export type InputProps = Omit<ComponentPropsWithRef<'input'>, 'size'> & {
13
+ startAdornment?: ReactNode;
14
+ endAdornment?: ReactNode;
15
+ inputRef?: RefObject<HTMLInputElement>;
16
+ } & InputAppearanceVariants;
17
+
18
+ export function Input({
19
+ className,
20
+ type = 'text',
21
+ startAdornment,
22
+ endAdornment,
23
+ disabled,
24
+ inputRef,
25
+ children,
26
+ variant,
27
+ size,
28
+ ref,
29
+ ...props
30
+ }: InputProps) {
31
+ const innerRef = useRef<HTMLInputElement>(null);
32
+ const { errors } = useFormFieldContext();
33
+
34
+ return (
35
+ <InputWrapper
36
+ ref={ref}
37
+ inputRef={innerRef}
38
+ disabled={disabled}
39
+ variant={variant}
40
+ size={size}
41
+ >
42
+ {startAdornment && (
43
+ <div className={inputAddornment}>{startAdornment}</div>
44
+ )}
45
+ <input
46
+ ref={mergeRefs([inputRef, innerRef])}
47
+ type={type}
48
+ className={clsx(input, className)}
49
+ disabled={disabled}
50
+ aria-invalid={errors ? 'true' : undefined}
51
+ {...props}
52
+ />
53
+ {endAdornment && <div className={inputAddornment}>{endAdornment}</div>}
54
+ </InputWrapper>
55
+ );
56
+ }
@@ -0,0 +1 @@
1
+ export { Label, type LabelProps } from './label';
@@ -0,0 +1,37 @@
1
+ import { recipe, RecipeVariants } from '@vanilla-extract/recipes';
2
+
3
+ import { typography } from '../../styles';
4
+ import { components } from '../../styles/layers.css';
5
+
6
+ export const label = recipe({
7
+ base: {
8
+ '@layer': {
9
+ [components]: {
10
+ cursor: 'default',
11
+ },
12
+ },
13
+ },
14
+
15
+ variants: {
16
+ disabled: {
17
+ true: {
18
+ '@layer': {
19
+ [components]: {
20
+ cursor: 'not-allowed',
21
+ },
22
+ },
23
+ },
24
+ },
25
+ error: {
26
+ true: {},
27
+ },
28
+
29
+ size: {
30
+ sm: [typography.label.small],
31
+ md: [typography.label.medium],
32
+ lg: [typography.label.large],
33
+ },
34
+ },
35
+ });
36
+
37
+ export type LabelVariants = NonNullable<RecipeVariants<typeof label>>;
@@ -0,0 +1,23 @@
1
+ import { clsx } from 'clsx';
2
+ import { ComponentPropsWithRef } from 'react';
3
+
4
+ import { label, LabelVariants } from './label.css';
5
+
6
+ export type LabelProps = ComponentPropsWithRef<'label'> & {
7
+ required?: boolean;
8
+ } & LabelVariants;
9
+
10
+ export function Label({
11
+ className,
12
+ disabled,
13
+ error,
14
+ size = 'md',
15
+ ...props
16
+ }: LabelProps) {
17
+ return (
18
+ <label
19
+ className={clsx(label({ disabled, error, size }), className)}
20
+ {...props}
21
+ />
22
+ );
23
+ }
@@ -0,0 +1 @@
1
+ export { MoonLoader } from './moon-loader';