@neoptocom/neopto-ui 1.6.10 → 1.6.14
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/dist/index.cjs +17 -6
- package/dist/index.d.cts +11 -5
- package/dist/index.d.ts +11 -5
- package/dist/index.js +17 -6
- package/package.json +1 -1
- package/src/components/Button.docs.mdx +1 -1
- package/src/components/Button.stories.tsx +6 -1
- package/src/components/Button.tsx +2 -1
- package/src/components/DateInput.tsx +1 -1
- package/src/components/Input.tsx +38 -7
- package/src/components/Search.tsx +4 -1
- package/src/stories/Input.stories.tsx +24 -0
- package/src/stories/Search.stories.tsx +2 -1
package/dist/index.cjs
CHANGED
|
@@ -303,6 +303,7 @@ var Input = React11__namespace.forwardRef(
|
|
|
303
303
|
className,
|
|
304
304
|
disabled,
|
|
305
305
|
variant = "default",
|
|
306
|
+
size = "md",
|
|
306
307
|
label,
|
|
307
308
|
fieldsetProps,
|
|
308
309
|
legendProps,
|
|
@@ -314,11 +315,15 @@ var Input = React11__namespace.forwardRef(
|
|
|
314
315
|
const shouldUseInlineStyles = isInlineVariant || Boolean(label);
|
|
315
316
|
const isError = error && !disabled;
|
|
316
317
|
const hasIcon = Boolean(icon);
|
|
318
|
+
const inputSizeClass = shouldUseInlineStyles ? size === "sm" ? "h-4" : size === "lg" ? "h-10" : "h-9" : size === "sm" ? "h-6 rounded-full" : size === "lg" ? "h-14 rounded-full" : "h-12 rounded-full";
|
|
319
|
+
const inputPaddingClass = shouldUseInlineStyles ? hasIcon ? "pr-8" : "" : size === "sm" ? hasIcon ? "px-3 pr-9" : "px-3" : hasIcon ? "px-4 pr-10" : "px-4";
|
|
320
|
+
const inputTextSizeClass = size === "sm" ? "text-xs placeholder:text-xs" : "text-sm placeholder:text-sm";
|
|
317
321
|
const inputClasses = [
|
|
318
322
|
"w-full bg-transparent outline-none transition-colors",
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
323
|
+
inputSizeClass,
|
|
324
|
+
inputPaddingClass,
|
|
325
|
+
inputTextSizeClass,
|
|
326
|
+
"font-['Poppins'] placeholder:text-[var(--muted-fg)]"
|
|
322
327
|
];
|
|
323
328
|
if (!shouldUseInlineStyles) {
|
|
324
329
|
inputClasses.push("border");
|
|
@@ -354,16 +359,20 @@ var Input = React11__namespace.forwardRef(
|
|
|
354
359
|
}
|
|
355
360
|
const { className: fieldsetClassNameProp = "", ...restFieldsetProps } = fieldsetProps ?? {};
|
|
356
361
|
const { className: legendClassNameProp = "", ...restLegendProps } = legendProps ?? {};
|
|
362
|
+
const fieldsetHeightClass = size === "sm" ? "h-8" : size === "lg" ? "h-16" : "h-14";
|
|
357
363
|
const fieldsetClassName = [
|
|
358
|
-
"w-full min-w-0 rounded-full border bg-[var(--surface)] transition-colors
|
|
364
|
+
"w-full min-w-0 rounded-full border bg-[var(--surface)] transition-colors",
|
|
365
|
+
fieldsetHeightClass,
|
|
359
366
|
isError ? "border-[var(--destructive)]" : "border-[var(--border)]",
|
|
360
367
|
isError ? "focus-within:border-[var(--destructive)]" : "focus-within:border-[var(--color-brand)]",
|
|
361
368
|
disabled ? "opacity-60 cursor-not-allowed" : "",
|
|
362
369
|
fieldsetClassNameProp
|
|
363
370
|
].filter(Boolean).join(" ");
|
|
364
371
|
const legendColorClass = disabled ? "text-[var(--muted-fg)]" : isError ? "text-[var(--destructive)]" : "text-[var(--muted-fg)]";
|
|
372
|
+
const legendSizeClass = size === "sm" ? "text-xs" : "text-sm";
|
|
365
373
|
const legendClassNameCombined = [
|
|
366
|
-
"ml-4 px-1
|
|
374
|
+
"ml-4 px-1 leading-none relative font-normal select-none",
|
|
375
|
+
legendSizeClass,
|
|
367
376
|
legendColorClass,
|
|
368
377
|
legendClassNameProp
|
|
369
378
|
].filter(Boolean).join(" ");
|
|
@@ -967,6 +976,7 @@ function Search({
|
|
|
967
976
|
searchDelay = 300,
|
|
968
977
|
disabled = false,
|
|
969
978
|
maxHeight = 152,
|
|
979
|
+
placeholder = "Pesquisar",
|
|
970
980
|
id,
|
|
971
981
|
children,
|
|
972
982
|
...props
|
|
@@ -1126,7 +1136,7 @@ function Search({
|
|
|
1126
1136
|
"leading-tight text-[var(--fg)] placeholder:text-[var(--muted-fg)]",
|
|
1127
1137
|
"px-2"
|
|
1128
1138
|
].join(" "),
|
|
1129
|
-
placeholder
|
|
1139
|
+
placeholder,
|
|
1130
1140
|
onClick: () => !disabled && setOpen(true)
|
|
1131
1141
|
}
|
|
1132
1142
|
),
|
|
@@ -1156,6 +1166,7 @@ function getButtonClasses(variant = "primary", size = "md", fullWidth, className
|
|
|
1156
1166
|
inline: "text-cyan-500 bg-transparent active:bg-cyan-100 disabled:text-neutral-400"
|
|
1157
1167
|
};
|
|
1158
1168
|
const sizes = {
|
|
1169
|
+
xs: "h-6 px-2",
|
|
1159
1170
|
sm: "h-9 px-3",
|
|
1160
1171
|
md: "h-12 px-[18px]",
|
|
1161
1172
|
lg: "h-14 px-6"
|
package/dist/index.d.cts
CHANGED
|
@@ -62,6 +62,8 @@ declare function Card({ children, className, style, showDecorations, variant, el
|
|
|
62
62
|
type InputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> & {
|
|
63
63
|
/** Input visual variant */
|
|
64
64
|
variant?: "default" | "inline";
|
|
65
|
+
/** Input size */
|
|
66
|
+
size?: "sm" | "md" | "lg";
|
|
65
67
|
/** Optional floating label (renders a fieldset wrapper when provided) */
|
|
66
68
|
label?: string;
|
|
67
69
|
/** Additional props for the surrounding fieldset when label is set */
|
|
@@ -76,6 +78,8 @@ type InputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> & {
|
|
|
76
78
|
declare const Input: React.ForwardRefExoticComponent<Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> & {
|
|
77
79
|
/** Input visual variant */
|
|
78
80
|
variant?: "default" | "inline";
|
|
81
|
+
/** Input size */
|
|
82
|
+
size?: "sm" | "md" | "lg";
|
|
79
83
|
/** Optional floating label (renders a fieldset wrapper when provided) */
|
|
80
84
|
label?: string;
|
|
81
85
|
/** Additional props for the surrounding fieldset when label is set */
|
|
@@ -219,18 +223,20 @@ interface SearchProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onSele
|
|
|
219
223
|
disabled?: boolean;
|
|
220
224
|
/** Maximum height of the options dropdown */
|
|
221
225
|
maxHeight?: number;
|
|
226
|
+
/** Placeholder shown when the input is empty and nothing is selected */
|
|
227
|
+
placeholder?: string;
|
|
222
228
|
/** Optional id base (for accessibility hooks) */
|
|
223
229
|
id?: string;
|
|
224
230
|
/** Optional filter children to render when filters are expanded */
|
|
225
231
|
children?: React.ReactNode;
|
|
226
232
|
}
|
|
227
|
-
declare function Search({ className, options, onSearch, selectedOption, onSelect, searchDelay, disabled, maxHeight, id, children, ...props }: SearchProps): react_jsx_runtime.JSX.Element;
|
|
233
|
+
declare function Search({ className, options, onSearch, selectedOption, onSelect, searchDelay, disabled, maxHeight, placeholder, id, children, ...props }: SearchProps): react_jsx_runtime.JSX.Element;
|
|
228
234
|
|
|
229
235
|
type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
230
236
|
/** Button visual variant */
|
|
231
237
|
variant?: "primary" | "secondary" | "ghost" | "inline";
|
|
232
238
|
/** Button size */
|
|
233
|
-
size?: "sm" | "md" | "lg";
|
|
239
|
+
size?: "xs" | "sm" | "md" | "lg";
|
|
234
240
|
/** Make button full width */
|
|
235
241
|
fullWidth?: boolean;
|
|
236
242
|
/** Icon component to display instead of text */
|
|
@@ -240,7 +246,7 @@ declare const Button: React.ForwardRefExoticComponent<React.ButtonHTMLAttributes
|
|
|
240
246
|
/** Button visual variant */
|
|
241
247
|
variant?: "primary" | "secondary" | "ghost" | "inline";
|
|
242
248
|
/** Button size */
|
|
243
|
-
size?: "sm" | "md" | "lg";
|
|
249
|
+
size?: "xs" | "sm" | "md" | "lg";
|
|
244
250
|
/** Make button full width */
|
|
245
251
|
fullWidth?: boolean;
|
|
246
252
|
/** Icon component to display instead of text */
|
|
@@ -394,7 +400,7 @@ interface BreadcrumbProps {
|
|
|
394
400
|
*/
|
|
395
401
|
declare const Breadcrumb: React__default.FC<BreadcrumbProps>;
|
|
396
402
|
|
|
397
|
-
type DateInputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "value" | "onChange" | "type"> & {
|
|
403
|
+
type DateInputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "value" | "onChange" | "type" | "size"> & {
|
|
398
404
|
/** Label text displayed above the input */
|
|
399
405
|
label?: string;
|
|
400
406
|
/** Current date value */
|
|
@@ -414,7 +420,7 @@ type DateInputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "value"
|
|
|
414
420
|
/** Background image URL for dark mode */
|
|
415
421
|
darkBackgroundImage?: string;
|
|
416
422
|
};
|
|
417
|
-
declare const DateInput: React.ForwardRefExoticComponent<Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "type" | "value"> & {
|
|
423
|
+
declare const DateInput: React.ForwardRefExoticComponent<Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "size" | "type" | "value"> & {
|
|
418
424
|
/** Label text displayed above the input */
|
|
419
425
|
label?: string;
|
|
420
426
|
/** Current date value */
|
package/dist/index.d.ts
CHANGED
|
@@ -62,6 +62,8 @@ declare function Card({ children, className, style, showDecorations, variant, el
|
|
|
62
62
|
type InputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> & {
|
|
63
63
|
/** Input visual variant */
|
|
64
64
|
variant?: "default" | "inline";
|
|
65
|
+
/** Input size */
|
|
66
|
+
size?: "sm" | "md" | "lg";
|
|
65
67
|
/** Optional floating label (renders a fieldset wrapper when provided) */
|
|
66
68
|
label?: string;
|
|
67
69
|
/** Additional props for the surrounding fieldset when label is set */
|
|
@@ -76,6 +78,8 @@ type InputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> & {
|
|
|
76
78
|
declare const Input: React.ForwardRefExoticComponent<Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> & {
|
|
77
79
|
/** Input visual variant */
|
|
78
80
|
variant?: "default" | "inline";
|
|
81
|
+
/** Input size */
|
|
82
|
+
size?: "sm" | "md" | "lg";
|
|
79
83
|
/** Optional floating label (renders a fieldset wrapper when provided) */
|
|
80
84
|
label?: string;
|
|
81
85
|
/** Additional props for the surrounding fieldset when label is set */
|
|
@@ -219,18 +223,20 @@ interface SearchProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onSele
|
|
|
219
223
|
disabled?: boolean;
|
|
220
224
|
/** Maximum height of the options dropdown */
|
|
221
225
|
maxHeight?: number;
|
|
226
|
+
/** Placeholder shown when the input is empty and nothing is selected */
|
|
227
|
+
placeholder?: string;
|
|
222
228
|
/** Optional id base (for accessibility hooks) */
|
|
223
229
|
id?: string;
|
|
224
230
|
/** Optional filter children to render when filters are expanded */
|
|
225
231
|
children?: React.ReactNode;
|
|
226
232
|
}
|
|
227
|
-
declare function Search({ className, options, onSearch, selectedOption, onSelect, searchDelay, disabled, maxHeight, id, children, ...props }: SearchProps): react_jsx_runtime.JSX.Element;
|
|
233
|
+
declare function Search({ className, options, onSearch, selectedOption, onSelect, searchDelay, disabled, maxHeight, placeholder, id, children, ...props }: SearchProps): react_jsx_runtime.JSX.Element;
|
|
228
234
|
|
|
229
235
|
type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
230
236
|
/** Button visual variant */
|
|
231
237
|
variant?: "primary" | "secondary" | "ghost" | "inline";
|
|
232
238
|
/** Button size */
|
|
233
|
-
size?: "sm" | "md" | "lg";
|
|
239
|
+
size?: "xs" | "sm" | "md" | "lg";
|
|
234
240
|
/** Make button full width */
|
|
235
241
|
fullWidth?: boolean;
|
|
236
242
|
/** Icon component to display instead of text */
|
|
@@ -240,7 +246,7 @@ declare const Button: React.ForwardRefExoticComponent<React.ButtonHTMLAttributes
|
|
|
240
246
|
/** Button visual variant */
|
|
241
247
|
variant?: "primary" | "secondary" | "ghost" | "inline";
|
|
242
248
|
/** Button size */
|
|
243
|
-
size?: "sm" | "md" | "lg";
|
|
249
|
+
size?: "xs" | "sm" | "md" | "lg";
|
|
244
250
|
/** Make button full width */
|
|
245
251
|
fullWidth?: boolean;
|
|
246
252
|
/** Icon component to display instead of text */
|
|
@@ -394,7 +400,7 @@ interface BreadcrumbProps {
|
|
|
394
400
|
*/
|
|
395
401
|
declare const Breadcrumb: React__default.FC<BreadcrumbProps>;
|
|
396
402
|
|
|
397
|
-
type DateInputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "value" | "onChange" | "type"> & {
|
|
403
|
+
type DateInputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "value" | "onChange" | "type" | "size"> & {
|
|
398
404
|
/** Label text displayed above the input */
|
|
399
405
|
label?: string;
|
|
400
406
|
/** Current date value */
|
|
@@ -414,7 +420,7 @@ type DateInputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "value"
|
|
|
414
420
|
/** Background image URL for dark mode */
|
|
415
421
|
darkBackgroundImage?: string;
|
|
416
422
|
};
|
|
417
|
-
declare const DateInput: React.ForwardRefExoticComponent<Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "type" | "value"> & {
|
|
423
|
+
declare const DateInput: React.ForwardRefExoticComponent<Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "size" | "type" | "value"> & {
|
|
418
424
|
/** Label text displayed above the input */
|
|
419
425
|
label?: string;
|
|
420
426
|
/** Current date value */
|
package/dist/index.js
CHANGED
|
@@ -282,6 +282,7 @@ var Input = React11.forwardRef(
|
|
|
282
282
|
className,
|
|
283
283
|
disabled,
|
|
284
284
|
variant = "default",
|
|
285
|
+
size = "md",
|
|
285
286
|
label,
|
|
286
287
|
fieldsetProps,
|
|
287
288
|
legendProps,
|
|
@@ -293,11 +294,15 @@ var Input = React11.forwardRef(
|
|
|
293
294
|
const shouldUseInlineStyles = isInlineVariant || Boolean(label);
|
|
294
295
|
const isError = error && !disabled;
|
|
295
296
|
const hasIcon = Boolean(icon);
|
|
297
|
+
const inputSizeClass = shouldUseInlineStyles ? size === "sm" ? "h-4" : size === "lg" ? "h-10" : "h-9" : size === "sm" ? "h-6 rounded-full" : size === "lg" ? "h-14 rounded-full" : "h-12 rounded-full";
|
|
298
|
+
const inputPaddingClass = shouldUseInlineStyles ? hasIcon ? "pr-8" : "" : size === "sm" ? hasIcon ? "px-3 pr-9" : "px-3" : hasIcon ? "px-4 pr-10" : "px-4";
|
|
299
|
+
const inputTextSizeClass = size === "sm" ? "text-xs placeholder:text-xs" : "text-sm placeholder:text-sm";
|
|
296
300
|
const inputClasses = [
|
|
297
301
|
"w-full bg-transparent outline-none transition-colors",
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
302
|
+
inputSizeClass,
|
|
303
|
+
inputPaddingClass,
|
|
304
|
+
inputTextSizeClass,
|
|
305
|
+
"font-['Poppins'] placeholder:text-[var(--muted-fg)]"
|
|
301
306
|
];
|
|
302
307
|
if (!shouldUseInlineStyles) {
|
|
303
308
|
inputClasses.push("border");
|
|
@@ -333,16 +338,20 @@ var Input = React11.forwardRef(
|
|
|
333
338
|
}
|
|
334
339
|
const { className: fieldsetClassNameProp = "", ...restFieldsetProps } = fieldsetProps ?? {};
|
|
335
340
|
const { className: legendClassNameProp = "", ...restLegendProps } = legendProps ?? {};
|
|
341
|
+
const fieldsetHeightClass = size === "sm" ? "h-8" : size === "lg" ? "h-16" : "h-14";
|
|
336
342
|
const fieldsetClassName = [
|
|
337
|
-
"w-full min-w-0 rounded-full border bg-[var(--surface)] transition-colors
|
|
343
|
+
"w-full min-w-0 rounded-full border bg-[var(--surface)] transition-colors",
|
|
344
|
+
fieldsetHeightClass,
|
|
338
345
|
isError ? "border-[var(--destructive)]" : "border-[var(--border)]",
|
|
339
346
|
isError ? "focus-within:border-[var(--destructive)]" : "focus-within:border-[var(--color-brand)]",
|
|
340
347
|
disabled ? "opacity-60 cursor-not-allowed" : "",
|
|
341
348
|
fieldsetClassNameProp
|
|
342
349
|
].filter(Boolean).join(" ");
|
|
343
350
|
const legendColorClass = disabled ? "text-[var(--muted-fg)]" : isError ? "text-[var(--destructive)]" : "text-[var(--muted-fg)]";
|
|
351
|
+
const legendSizeClass = size === "sm" ? "text-xs" : "text-sm";
|
|
344
352
|
const legendClassNameCombined = [
|
|
345
|
-
"ml-4 px-1
|
|
353
|
+
"ml-4 px-1 leading-none relative font-normal select-none",
|
|
354
|
+
legendSizeClass,
|
|
346
355
|
legendColorClass,
|
|
347
356
|
legendClassNameProp
|
|
348
357
|
].filter(Boolean).join(" ");
|
|
@@ -946,6 +955,7 @@ function Search({
|
|
|
946
955
|
searchDelay = 300,
|
|
947
956
|
disabled = false,
|
|
948
957
|
maxHeight = 152,
|
|
958
|
+
placeholder = "Pesquisar",
|
|
949
959
|
id,
|
|
950
960
|
children,
|
|
951
961
|
...props
|
|
@@ -1105,7 +1115,7 @@ function Search({
|
|
|
1105
1115
|
"leading-tight text-[var(--fg)] placeholder:text-[var(--muted-fg)]",
|
|
1106
1116
|
"px-2"
|
|
1107
1117
|
].join(" "),
|
|
1108
|
-
placeholder
|
|
1118
|
+
placeholder,
|
|
1109
1119
|
onClick: () => !disabled && setOpen(true)
|
|
1110
1120
|
}
|
|
1111
1121
|
),
|
|
@@ -1135,6 +1145,7 @@ function getButtonClasses(variant = "primary", size = "md", fullWidth, className
|
|
|
1135
1145
|
inline: "text-cyan-500 bg-transparent active:bg-cyan-100 disabled:text-neutral-400"
|
|
1136
1146
|
};
|
|
1137
1147
|
const sizes = {
|
|
1148
|
+
xs: "h-6 px-2",
|
|
1138
1149
|
sm: "h-9 px-3",
|
|
1139
1150
|
md: "h-12 px-[18px]",
|
|
1140
1151
|
lg: "h-14 px-6"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neoptocom/neopto-ui",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.14",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A modern React component library built with Tailwind CSS v4 and TypeScript. Features dark mode, design tokens, and comprehensive documentation. Requires Tailwind v4+.",
|
|
6
6
|
"keywords": [
|
|
@@ -6,7 +6,7 @@ import * as ButtonStories from "./Button.stories";
|
|
|
6
6
|
|
|
7
7
|
# Button
|
|
8
8
|
|
|
9
|
-
Buttons trigger primary user actions. They support three visual variants,
|
|
9
|
+
Buttons trigger primary user actions. They support three visual variants, four sizes (`xs`–`lg`), optional full
|
|
10
10
|
width layout, and icon affordances.
|
|
11
11
|
|
|
12
12
|
## Usage
|
|
@@ -20,7 +20,7 @@ const meta: Meta<typeof Button> = {
|
|
|
20
20
|
},
|
|
21
21
|
size: {
|
|
22
22
|
control: "inline-radio",
|
|
23
|
-
options: ["sm", "md", "lg"]
|
|
23
|
+
options: ["xs", "sm", "md", "lg"]
|
|
24
24
|
},
|
|
25
25
|
fullWidth: {
|
|
26
26
|
control: "boolean"
|
|
@@ -66,6 +66,11 @@ export const Variants: Story = {
|
|
|
66
66
|
export const Sizes: Story = {
|
|
67
67
|
render: () => (
|
|
68
68
|
<div className="flex flex-wrap items-center gap-4">
|
|
69
|
+
<Button size="xs">
|
|
70
|
+
<Typo variant="label-sm" bold="semibold">
|
|
71
|
+
Extra small
|
|
72
|
+
</Typo>
|
|
73
|
+
</Button>
|
|
69
74
|
<Button size="sm">
|
|
70
75
|
<Typo variant="title-sm" bold="semibold">
|
|
71
76
|
Small
|
|
@@ -4,7 +4,7 @@ export type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
|
4
4
|
/** Button visual variant */
|
|
5
5
|
variant?: "primary" | "secondary" | "ghost" | "inline";
|
|
6
6
|
/** Button size */
|
|
7
|
-
size?: "sm" | "md" | "lg";
|
|
7
|
+
size?: "xs" | "sm" | "md" | "lg";
|
|
8
8
|
/** Make button full width */
|
|
9
9
|
fullWidth?: boolean;
|
|
10
10
|
/** Icon component to display instead of text */
|
|
@@ -30,6 +30,7 @@ function getButtonClasses(
|
|
|
30
30
|
};
|
|
31
31
|
|
|
32
32
|
const sizes = {
|
|
33
|
+
xs: "h-6 px-2",
|
|
33
34
|
sm: "h-9 px-3",
|
|
34
35
|
md: "h-12 px-[18px]",
|
|
35
36
|
lg: "h-14 px-6"
|
package/src/components/Input.tsx
CHANGED
|
@@ -4,6 +4,8 @@ import Icon from "./Icon";
|
|
|
4
4
|
export type InputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> & {
|
|
5
5
|
/** Input visual variant */
|
|
6
6
|
variant?: "default" | "inline";
|
|
7
|
+
/** Input size */
|
|
8
|
+
size?: "sm" | "md" | "lg";
|
|
7
9
|
/** Optional floating label (renders a fieldset wrapper when provided) */
|
|
8
10
|
label?: string;
|
|
9
11
|
/** Additional props for the surrounding fieldset when label is set */
|
|
@@ -22,6 +24,7 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|
|
22
24
|
className,
|
|
23
25
|
disabled,
|
|
24
26
|
variant = "default",
|
|
27
|
+
size = "md",
|
|
25
28
|
label,
|
|
26
29
|
fieldsetProps,
|
|
27
30
|
legendProps,
|
|
@@ -35,14 +38,36 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|
|
35
38
|
const shouldUseInlineStyles = isInlineVariant || Boolean(label);
|
|
36
39
|
const isError = error && !disabled;
|
|
37
40
|
const hasIcon = Boolean(icon);
|
|
41
|
+
const inputSizeClass = shouldUseInlineStyles
|
|
42
|
+
? size === "sm"
|
|
43
|
+
? "h-4"
|
|
44
|
+
: size === "lg"
|
|
45
|
+
? "h-10"
|
|
46
|
+
: "h-9"
|
|
47
|
+
: size === "sm"
|
|
48
|
+
? "h-6 rounded-full"
|
|
49
|
+
: size === "lg"
|
|
50
|
+
? "h-14 rounded-full"
|
|
51
|
+
: "h-12 rounded-full";
|
|
52
|
+
const inputPaddingClass = shouldUseInlineStyles
|
|
53
|
+
? hasIcon
|
|
54
|
+
? "pr-8"
|
|
55
|
+
: ""
|
|
56
|
+
: size === "sm"
|
|
57
|
+
? hasIcon
|
|
58
|
+
? "px-3 pr-9"
|
|
59
|
+
: "px-3"
|
|
60
|
+
: hasIcon
|
|
61
|
+
? "px-4 pr-10"
|
|
62
|
+
: "px-4";
|
|
63
|
+
const inputTextSizeClass = size === "sm" ? "text-xs placeholder:text-xs" : "text-sm placeholder:text-sm";
|
|
38
64
|
|
|
39
65
|
const inputClasses: string[] = [
|
|
40
66
|
"w-full bg-transparent outline-none transition-colors",
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"font-['Poppins'] text-sm placeholder:text-[var(--muted-fg)]"
|
|
67
|
+
inputSizeClass,
|
|
68
|
+
inputPaddingClass,
|
|
69
|
+
inputTextSizeClass,
|
|
70
|
+
"font-['Poppins'] placeholder:text-[var(--muted-fg)]"
|
|
46
71
|
];
|
|
47
72
|
|
|
48
73
|
if (!shouldUseInlineStyles) {
|
|
@@ -94,8 +119,12 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|
|
94
119
|
|
|
95
120
|
const { className: legendClassNameProp = "", ...restLegendProps } = legendProps ?? {};
|
|
96
121
|
|
|
122
|
+
const fieldsetHeightClass =
|
|
123
|
+
size === "sm" ? "h-8" : size === "lg" ? "h-16" : "h-14";
|
|
124
|
+
|
|
97
125
|
const fieldsetClassName = [
|
|
98
|
-
"w-full min-w-0 rounded-full border bg-[var(--surface)] transition-colors
|
|
126
|
+
"w-full min-w-0 rounded-full border bg-[var(--surface)] transition-colors",
|
|
127
|
+
fieldsetHeightClass,
|
|
99
128
|
isError ? "border-[var(--destructive)]" : "border-[var(--border)]",
|
|
100
129
|
isError
|
|
101
130
|
? "focus-within:border-[var(--destructive)]"
|
|
@@ -111,9 +140,11 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|
|
111
140
|
: isError
|
|
112
141
|
? "text-[var(--destructive)]"
|
|
113
142
|
: "text-[var(--muted-fg)]";
|
|
143
|
+
const legendSizeClass = size === "sm" ? "text-xs" : "text-sm";
|
|
114
144
|
|
|
115
145
|
const legendClassNameCombined = [
|
|
116
|
-
"ml-4 px-1
|
|
146
|
+
"ml-4 px-1 leading-none relative font-normal select-none",
|
|
147
|
+
legendSizeClass,
|
|
117
148
|
legendColorClass,
|
|
118
149
|
legendClassNameProp
|
|
119
150
|
]
|
|
@@ -28,6 +28,8 @@ export interface SearchProps
|
|
|
28
28
|
disabled?: boolean;
|
|
29
29
|
/** Maximum height of the options dropdown */
|
|
30
30
|
maxHeight?: number;
|
|
31
|
+
/** Placeholder shown when the input is empty and nothing is selected */
|
|
32
|
+
placeholder?: string;
|
|
31
33
|
/** Optional id base (for accessibility hooks) */
|
|
32
34
|
id?: string;
|
|
33
35
|
/** Optional filter children to render when filters are expanded */
|
|
@@ -43,6 +45,7 @@ export default function Search({
|
|
|
43
45
|
searchDelay = 300,
|
|
44
46
|
disabled = false,
|
|
45
47
|
maxHeight = 152,
|
|
48
|
+
placeholder = "Pesquisar",
|
|
46
49
|
id,
|
|
47
50
|
children,
|
|
48
51
|
...props
|
|
@@ -218,7 +221,7 @@ export default function Search({
|
|
|
218
221
|
"leading-tight text-[var(--fg)] placeholder:text-[var(--muted-fg)]",
|
|
219
222
|
"px-2"
|
|
220
223
|
].join(" ")}
|
|
221
|
-
placeholder=
|
|
224
|
+
placeholder={placeholder}
|
|
222
225
|
onClick={() => !disabled && setOpen(true)}
|
|
223
226
|
/>
|
|
224
227
|
{/* Action button (clear or expand) */}
|
|
@@ -37,6 +37,30 @@ export const Types: Story = {
|
|
|
37
37
|
)
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
+
export const Sizes: Story = {
|
|
41
|
+
render: () => (
|
|
42
|
+
<div className="flex flex-col gap-6 w-96">
|
|
43
|
+
<div className="flex flex-col gap-3">
|
|
44
|
+
<Input size="sm" placeholder="Small input" />
|
|
45
|
+
<Input size="md" placeholder="Medium input" />
|
|
46
|
+
<Input size="lg" placeholder="Large input" />
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<div className="flex flex-col gap-3">
|
|
50
|
+
<Input size="sm" variant="inline" placeholder="Small inline input" />
|
|
51
|
+
<Input size="md" variant="inline" placeholder="Medium inline input" />
|
|
52
|
+
<Input size="lg" variant="inline" placeholder="Large inline input" />
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<div className="flex flex-col gap-3">
|
|
56
|
+
<Input size="sm" label="Small labeled" placeholder="Small labeled input" />
|
|
57
|
+
<Input size="md" label="Medium labeled" placeholder="Medium labeled input" />
|
|
58
|
+
<Input size="lg" label="Large labeled" placeholder="Large labeled input" />
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
)
|
|
62
|
+
};
|
|
63
|
+
|
|
40
64
|
export const Inline: Story = {
|
|
41
65
|
render: () => (
|
|
42
66
|
<div className="flex flex-col gap-4 w-96">
|