neogestify-ui-components 1.2.18 → 1.2.20
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/README.md +349 -342
- package/dist/components/alerts/index.js +1 -1
- package/dist/components/alerts/index.js.map +1 -1
- package/dist/components/alerts/index.mjs +1 -1
- package/dist/components/alerts/index.mjs.map +1 -1
- package/dist/components/html/index.js +2 -2
- package/dist/components/html/index.js.map +1 -1
- package/dist/components/html/index.mjs +2 -2
- package/dist/components/html/index.mjs.map +1 -1
- package/dist/components/icons/index.js.map +1 -1
- package/dist/components/icons/index.mjs.map +1 -1
- package/dist/context/theme/index.js +1 -1
- package/dist/context/theme/index.js.map +1 -1
- package/dist/context/theme/index.mjs +1 -1
- package/dist/context/theme/index.mjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/components/alerts/InfoAlert.tsx +25 -25
- package/src/components/alerts/alerta.ts +93 -93
- package/src/components/alerts/index.ts +1 -1
- package/src/components/html/Button.tsx +71 -71
- package/src/components/html/Form.tsx +39 -39
- package/src/components/html/Input.tsx +136 -136
- package/src/components/html/Loading.tsx +104 -104
- package/src/components/html/Modal.tsx +79 -79
- package/src/components/html/Select.tsx +81 -81
- package/src/components/html/Table.tsx +61 -61
- package/src/components/html/TextArea.tsx +70 -70
- package/src/components/html/index.ts +7 -7
- package/src/components/icons/icons.tsx +550 -550
- package/src/components/icons/index.ts +1 -1
- package/src/context/theme/ThemeContext.tsx +37 -37
- package/src/context/theme/ThemeToggle.tsx +23 -23
- package/src/context/theme/index.ts +3 -3
- package/src/context/theme/theme.types.ts +11 -11
- package/src/context/theme/useTheme.ts +10 -10
- package/src/index.ts +5 -5
- package/src/types/types.ts +3 -3
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
import { type SelectHTMLAttributes, type FC, type ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
interface Option {
|
|
4
|
-
value: string | number;
|
|
5
|
-
label: string;
|
|
6
|
-
disabled?: boolean;
|
|
7
|
-
selected?: boolean;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, 'size'> {
|
|
11
|
-
options: Option[];
|
|
12
|
-
placeholder?: string;
|
|
13
|
-
variant?: 'default' | 'small';
|
|
14
|
-
error?: boolean;
|
|
15
|
-
helperText?: string;
|
|
16
|
-
label?: string | ReactNode;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export const Select: FC<SelectProps> = ({
|
|
20
|
-
options,
|
|
21
|
-
placeholder,
|
|
22
|
-
variant = 'default',
|
|
23
|
-
error = false,
|
|
24
|
-
helperText,
|
|
25
|
-
label,
|
|
26
|
-
className = '',
|
|
27
|
-
id,
|
|
28
|
-
...props
|
|
29
|
-
}) => {
|
|
30
|
-
const selectId = id || `select-${Math.random().toString(36).substring(2, 9)}`;
|
|
31
|
-
|
|
32
|
-
const getVariantClasses = () => {
|
|
33
|
-
const baseClasses = 'appearance-none relative block w-full px-3 py-2 border placeholder-gray-500 dark:placeholder-gray-400 text-gray-900 dark:text-white bg-white dark:bg-gray-800 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:border-indigo-500 focus:z-10 sm:text-sm disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200';
|
|
34
|
-
|
|
35
|
-
if (variant === 'small') {
|
|
36
|
-
return `${baseClasses.replace('px-3 py-2', 'px-2.5 py-1.5 text-sm')} border-gray-300 dark:border-gray-600`;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return `${baseClasses} border-gray-300 dark:border-gray-600 ${error ? 'border-red-300 dark:border-red-600 focus:ring-red-500 dark:focus:ring-red-400 focus:border-red-500' : ''}`;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
const getOptionClasses = (option: Option) => {
|
|
43
|
-
return `bg-white dark:bg-gray-800 text-gray-900 dark:text-white py-2 ${option.disabled ? 'opacity-50 cursor-not-allowed' : ''}`;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
const combinedClassName = `${getVariantClasses()} ${className}`.trim();
|
|
47
|
-
|
|
48
|
-
return (
|
|
49
|
-
<div className="space-y-1 w-full">
|
|
50
|
-
{label && typeof label === 'string' ? (
|
|
51
|
-
<label htmlFor={selectId} className="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
|
52
|
-
{label}
|
|
53
|
-
</label>
|
|
54
|
-
) : (
|
|
55
|
-
label
|
|
56
|
-
)}
|
|
57
|
-
<select id={selectId} className={combinedClassName} {...props}>
|
|
58
|
-
{placeholder && placeholder.trim() && (
|
|
59
|
-
<option value="" disabled className="bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400 py-2">
|
|
60
|
-
{placeholder}
|
|
61
|
-
</option>
|
|
62
|
-
)}
|
|
63
|
-
{options.map((option) => (
|
|
64
|
-
<option
|
|
65
|
-
key={option.value}
|
|
66
|
-
value={option.value}
|
|
67
|
-
disabled={option.disabled}
|
|
68
|
-
selected={option.selected}
|
|
69
|
-
className={getOptionClasses(option)}
|
|
70
|
-
>
|
|
71
|
-
{option.label}
|
|
72
|
-
</option>
|
|
73
|
-
))}
|
|
74
|
-
</select>
|
|
75
|
-
{helperText && (
|
|
76
|
-
<p className={`text-sm ${error ? 'text-red-600 dark:text-red-400' : 'text-gray-500 dark:text-gray-400'}`}>
|
|
77
|
-
{helperText}
|
|
78
|
-
</p>
|
|
79
|
-
)}
|
|
80
|
-
</div>
|
|
81
|
-
);
|
|
1
|
+
import { type SelectHTMLAttributes, type FC, type ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
interface Option {
|
|
4
|
+
value: string | number;
|
|
5
|
+
label: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
selected?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, 'size'> {
|
|
11
|
+
options: Option[];
|
|
12
|
+
placeholder?: string;
|
|
13
|
+
variant?: 'default' | 'small';
|
|
14
|
+
error?: boolean;
|
|
15
|
+
helperText?: string;
|
|
16
|
+
label?: string | ReactNode;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const Select: FC<SelectProps> = ({
|
|
20
|
+
options,
|
|
21
|
+
placeholder,
|
|
22
|
+
variant = 'default',
|
|
23
|
+
error = false,
|
|
24
|
+
helperText,
|
|
25
|
+
label,
|
|
26
|
+
className = '',
|
|
27
|
+
id,
|
|
28
|
+
...props
|
|
29
|
+
}) => {
|
|
30
|
+
const selectId = id || `select-${Math.random().toString(36).substring(2, 9)}`;
|
|
31
|
+
|
|
32
|
+
const getVariantClasses = () => {
|
|
33
|
+
const baseClasses = 'appearance-none relative block w-full px-3 py-2 border placeholder-gray-500 dark:placeholder-gray-400 text-gray-900 dark:text-white bg-white dark:bg-gray-800 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:border-indigo-500 focus:z-10 sm:text-sm disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200';
|
|
34
|
+
|
|
35
|
+
if (variant === 'small') {
|
|
36
|
+
return `${baseClasses.replace('px-3 py-2', 'px-2.5 py-1.5 text-sm')} border-gray-300 dark:border-gray-600`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return `${baseClasses} border-gray-300 dark:border-gray-600 ${error ? 'border-red-300 dark:border-red-600 focus:ring-red-500 dark:focus:ring-red-400 focus:border-red-500' : ''}`;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const getOptionClasses = (option: Option) => {
|
|
43
|
+
return `bg-white dark:bg-gray-800 text-gray-900 dark:text-white py-2 ${option.disabled ? 'opacity-50 cursor-not-allowed' : ''}`;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const combinedClassName = `${getVariantClasses()} ${className}`.trim();
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<div className="space-y-1 w-full">
|
|
50
|
+
{label && typeof label === 'string' ? (
|
|
51
|
+
<label htmlFor={selectId} className="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
|
52
|
+
{label}
|
|
53
|
+
</label>
|
|
54
|
+
) : (
|
|
55
|
+
label
|
|
56
|
+
)}
|
|
57
|
+
<select id={selectId} className={combinedClassName} {...props}>
|
|
58
|
+
{placeholder && placeholder.trim() && (
|
|
59
|
+
<option value="" disabled selected className="bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400 py-2">
|
|
60
|
+
{placeholder}
|
|
61
|
+
</option>
|
|
62
|
+
)}
|
|
63
|
+
{options.map((option) => (
|
|
64
|
+
<option
|
|
65
|
+
key={option.value}
|
|
66
|
+
value={option.value}
|
|
67
|
+
disabled={option.disabled}
|
|
68
|
+
selected={option.selected}
|
|
69
|
+
className={getOptionClasses(option)}
|
|
70
|
+
>
|
|
71
|
+
{option.label}
|
|
72
|
+
</option>
|
|
73
|
+
))}
|
|
74
|
+
</select>
|
|
75
|
+
{helperText && (
|
|
76
|
+
<p className={`text-sm ${error ? 'text-red-600 dark:text-red-400' : 'text-gray-500 dark:text-gray-400'}`}>
|
|
77
|
+
{helperText}
|
|
78
|
+
</p>
|
|
79
|
+
)}
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
82
|
};
|
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
import { type ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
interface TableProps {
|
|
4
|
-
headers: ReactNode[];
|
|
5
|
-
rows: ReactNode[][];
|
|
6
|
-
variant?: 'default' | 'custom';
|
|
7
|
-
className?: string;
|
|
8
|
-
thClassName?: string;
|
|
9
|
-
tdClassName?: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function Table({
|
|
13
|
-
headers,
|
|
14
|
-
rows,
|
|
15
|
-
variant = 'default',
|
|
16
|
-
className = '',
|
|
17
|
-
thClassName = '',
|
|
18
|
-
tdClassName = ''
|
|
19
|
-
}: TableProps) {
|
|
20
|
-
const baseTableClass = variant === 'default'
|
|
21
|
-
? 'w-full table-auto border-collapse border border-gray-300 dark:border-gray-600 min-w-full'
|
|
22
|
-
: '';
|
|
23
|
-
|
|
24
|
-
const baseThClass = variant === 'default'
|
|
25
|
-
? 'border border-gray-300 dark:border-gray-600 px-4 py-2 text-left text-gray-900 dark:text-white'
|
|
26
|
-
: '';
|
|
27
|
-
|
|
28
|
-
const baseTdClass = variant === 'default'
|
|
29
|
-
? 'border border-gray-300 dark:border-gray-600 px-4 py-2 text-gray-900 dark:text-white'
|
|
30
|
-
: '';
|
|
31
|
-
|
|
32
|
-
const tableClass = `${baseTableClass} ${className}`.trim();
|
|
33
|
-
const thClass = `${baseThClass} ${thClassName}`.trim();
|
|
34
|
-
const tdClass = `${baseTdClass} ${tdClassName}`.trim();
|
|
35
|
-
|
|
36
|
-
return (
|
|
37
|
-
<div className="overflow-x-auto w-full">
|
|
38
|
-
<table className={tableClass}>
|
|
39
|
-
<thead>
|
|
40
|
-
<tr className={variant === 'default' ? 'bg-gray-100 dark:bg-gray-700' : ''}>
|
|
41
|
-
{headers.map((header, index) => (
|
|
42
|
-
<th key={index} className={thClass}>
|
|
43
|
-
{header}
|
|
44
|
-
</th>
|
|
45
|
-
))}
|
|
46
|
-
</tr>
|
|
47
|
-
</thead>
|
|
48
|
-
<tbody>
|
|
49
|
-
{rows.map((row, rowIndex) => (
|
|
50
|
-
<tr key={rowIndex} className={variant === 'default' ? 'hover:bg-gray-50 dark:hover:bg-gray-600' : ''}>
|
|
51
|
-
{row.map((cell, cellIndex) => (
|
|
52
|
-
<td key={cellIndex} className={tdClass}>
|
|
53
|
-
{cell}
|
|
54
|
-
</td>
|
|
55
|
-
))}
|
|
56
|
-
</tr>
|
|
57
|
-
))}
|
|
58
|
-
</tbody>
|
|
59
|
-
</table>
|
|
60
|
-
</div>
|
|
61
|
-
);
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
interface TableProps {
|
|
4
|
+
headers: ReactNode[];
|
|
5
|
+
rows: ReactNode[][];
|
|
6
|
+
variant?: 'default' | 'custom';
|
|
7
|
+
className?: string;
|
|
8
|
+
thClassName?: string;
|
|
9
|
+
tdClassName?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function Table({
|
|
13
|
+
headers,
|
|
14
|
+
rows,
|
|
15
|
+
variant = 'default',
|
|
16
|
+
className = '',
|
|
17
|
+
thClassName = '',
|
|
18
|
+
tdClassName = ''
|
|
19
|
+
}: TableProps) {
|
|
20
|
+
const baseTableClass = variant === 'default'
|
|
21
|
+
? 'w-full table-auto border-collapse border border-gray-300 dark:border-gray-600 min-w-full'
|
|
22
|
+
: '';
|
|
23
|
+
|
|
24
|
+
const baseThClass = variant === 'default'
|
|
25
|
+
? 'border border-gray-300 dark:border-gray-600 px-4 py-2 text-left text-gray-900 dark:text-white'
|
|
26
|
+
: '';
|
|
27
|
+
|
|
28
|
+
const baseTdClass = variant === 'default'
|
|
29
|
+
? 'border border-gray-300 dark:border-gray-600 px-4 py-2 text-gray-900 dark:text-white'
|
|
30
|
+
: '';
|
|
31
|
+
|
|
32
|
+
const tableClass = `${baseTableClass} ${className}`.trim();
|
|
33
|
+
const thClass = `${baseThClass} ${thClassName}`.trim();
|
|
34
|
+
const tdClass = `${baseTdClass} ${tdClassName}`.trim();
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<div className="overflow-x-auto w-full">
|
|
38
|
+
<table className={tableClass}>
|
|
39
|
+
<thead>
|
|
40
|
+
<tr className={variant === 'default' ? 'bg-gray-100 dark:bg-gray-700' : ''}>
|
|
41
|
+
{headers.map((header, index) => (
|
|
42
|
+
<th key={index} className={thClass}>
|
|
43
|
+
{header}
|
|
44
|
+
</th>
|
|
45
|
+
))}
|
|
46
|
+
</tr>
|
|
47
|
+
</thead>
|
|
48
|
+
<tbody>
|
|
49
|
+
{rows.map((row, rowIndex) => (
|
|
50
|
+
<tr key={rowIndex} className={variant === 'default' ? 'hover:bg-gray-50 dark:hover:bg-gray-600' : ''}>
|
|
51
|
+
{row.map((cell, cellIndex) => (
|
|
52
|
+
<td key={cellIndex} className={tdClass}>
|
|
53
|
+
{cell}
|
|
54
|
+
</td>
|
|
55
|
+
))}
|
|
56
|
+
</tr>
|
|
57
|
+
))}
|
|
58
|
+
</tbody>
|
|
59
|
+
</table>
|
|
60
|
+
</div>
|
|
61
|
+
);
|
|
62
62
|
}
|
|
@@ -1,71 +1,71 @@
|
|
|
1
|
-
import { type TextareaHTMLAttributes, type FC, type ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
interface TextAreaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
4
|
-
label?: string | ReactNode;
|
|
5
|
-
error?: string;
|
|
6
|
-
helperText?: string;
|
|
7
|
-
variant?: 'default' | 'outline' | 'filled' | 'minimal';
|
|
8
|
-
size?: 'small' | 'medium' | 'large';
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const TextArea: FC<TextAreaProps> = ({
|
|
12
|
-
label,
|
|
13
|
-
error,
|
|
14
|
-
helperText,
|
|
15
|
-
variant = 'default',
|
|
16
|
-
size = 'medium',
|
|
17
|
-
className = '',
|
|
18
|
-
id,
|
|
19
|
-
...props
|
|
20
|
-
}) => {
|
|
21
|
-
const textAreaId = id || `textarea-${Math.random().toString(36).substring(2, 9)}`;
|
|
22
|
-
|
|
23
|
-
const sizeClasses = {
|
|
24
|
-
small: 'px-2 py-1 text-xs',
|
|
25
|
-
medium: 'px-3 py-2 text-sm',
|
|
26
|
-
large: 'px-4 py-3 text-base'
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const variantClasses = {
|
|
30
|
-
default: 'border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800',
|
|
31
|
-
outline: 'border-2 border-indigo-300 dark:border-indigo-600 bg-transparent',
|
|
32
|
-
filled: 'border-gray-300 dark:border-gray-600 bg-gray-100 dark:bg-gray-700',
|
|
33
|
-
minimal: 'border-0 bg-transparent focus:ring-0 focus:border-0'
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const baseClasses = 'appearance-none relative block w-full placeholder-gray-500 dark:placeholder-gray-400 text-gray-900 dark:text-white rounded-md border focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:border-indigo-500 focus:z-10 disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200 resize-y';
|
|
37
|
-
|
|
38
|
-
const errorClasses = error ? 'border-red-300 dark:border-red-600 focus:ring-red-500 dark:focus:ring-red-400 focus:border-red-500' : '';
|
|
39
|
-
|
|
40
|
-
const classes = `${baseClasses} ${sizeClasses[size]} ${variantClasses[variant]} ${errorClasses} ${className}`;
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
<div className="space-y-1 w-full">
|
|
44
|
-
{label && typeof label === 'string' ? (
|
|
45
|
-
<label
|
|
46
|
-
htmlFor={textAreaId}
|
|
47
|
-
className="block text-sm font-medium text-gray-700 dark:text-gray-300"
|
|
48
|
-
>
|
|
49
|
-
{label}
|
|
50
|
-
</label>
|
|
51
|
-
) : (
|
|
52
|
-
label
|
|
53
|
-
)}
|
|
54
|
-
<textarea
|
|
55
|
-
id={textAreaId}
|
|
56
|
-
className={classes}
|
|
57
|
-
{...props}
|
|
58
|
-
/>
|
|
59
|
-
{error && (
|
|
60
|
-
<p className="text-sm text-red-600 dark:text-red-400" role="alert">
|
|
61
|
-
{error}
|
|
62
|
-
</p>
|
|
63
|
-
)}
|
|
64
|
-
{helperText && !error && (
|
|
65
|
-
<p className="text-sm text-gray-500 dark:text-gray-400">
|
|
66
|
-
{helperText}
|
|
67
|
-
</p>
|
|
68
|
-
)}
|
|
69
|
-
</div>
|
|
70
|
-
);
|
|
1
|
+
import { type TextareaHTMLAttributes, type FC, type ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
interface TextAreaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
4
|
+
label?: string | ReactNode;
|
|
5
|
+
error?: string;
|
|
6
|
+
helperText?: string;
|
|
7
|
+
variant?: 'default' | 'outline' | 'filled' | 'minimal';
|
|
8
|
+
size?: 'small' | 'medium' | 'large';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const TextArea: FC<TextAreaProps> = ({
|
|
12
|
+
label,
|
|
13
|
+
error,
|
|
14
|
+
helperText,
|
|
15
|
+
variant = 'default',
|
|
16
|
+
size = 'medium',
|
|
17
|
+
className = '',
|
|
18
|
+
id,
|
|
19
|
+
...props
|
|
20
|
+
}) => {
|
|
21
|
+
const textAreaId = id || `textarea-${Math.random().toString(36).substring(2, 9)}`;
|
|
22
|
+
|
|
23
|
+
const sizeClasses = {
|
|
24
|
+
small: 'px-2 py-1 text-xs',
|
|
25
|
+
medium: 'px-3 py-2 text-sm',
|
|
26
|
+
large: 'px-4 py-3 text-base'
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const variantClasses = {
|
|
30
|
+
default: 'border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800',
|
|
31
|
+
outline: 'border-2 border-indigo-300 dark:border-indigo-600 bg-transparent',
|
|
32
|
+
filled: 'border-gray-300 dark:border-gray-600 bg-gray-100 dark:bg-gray-700',
|
|
33
|
+
minimal: 'border-0 bg-transparent focus:ring-0 focus:border-0'
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const baseClasses = 'appearance-none relative block w-full placeholder-gray-500 dark:placeholder-gray-400 text-gray-900 dark:text-white rounded-md border focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:border-indigo-500 focus:z-10 disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200 resize-y';
|
|
37
|
+
|
|
38
|
+
const errorClasses = error ? 'border-red-300 dark:border-red-600 focus:ring-red-500 dark:focus:ring-red-400 focus:border-red-500' : '';
|
|
39
|
+
|
|
40
|
+
const classes = `${baseClasses} ${sizeClasses[size]} ${variantClasses[variant]} ${errorClasses} ${className}`;
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<div className="space-y-1 w-full">
|
|
44
|
+
{label && typeof label === 'string' ? (
|
|
45
|
+
<label
|
|
46
|
+
htmlFor={textAreaId}
|
|
47
|
+
className="block text-sm font-medium text-gray-700 dark:text-gray-300"
|
|
48
|
+
>
|
|
49
|
+
{label}
|
|
50
|
+
</label>
|
|
51
|
+
) : (
|
|
52
|
+
label
|
|
53
|
+
)}
|
|
54
|
+
<textarea
|
|
55
|
+
id={textAreaId}
|
|
56
|
+
className={classes}
|
|
57
|
+
{...props}
|
|
58
|
+
/>
|
|
59
|
+
{error && (
|
|
60
|
+
<p className="text-sm text-red-600 dark:text-red-400" role="alert">
|
|
61
|
+
{error}
|
|
62
|
+
</p>
|
|
63
|
+
)}
|
|
64
|
+
{helperText && !error && (
|
|
65
|
+
<p className="text-sm text-gray-500 dark:text-gray-400">
|
|
66
|
+
{helperText}
|
|
67
|
+
</p>
|
|
68
|
+
)}
|
|
69
|
+
</div>
|
|
70
|
+
);
|
|
71
71
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { Button } from './Button';
|
|
2
|
-
export { Input } from './Input';
|
|
3
|
-
export { TextArea } from './TextArea';
|
|
4
|
-
export { Form } from './Form';
|
|
5
|
-
export { Select } from './Select';
|
|
6
|
-
export { Table } from './Table';
|
|
7
|
-
export { Modal, type ModalRef } from './Modal';
|
|
1
|
+
export { Button } from './Button';
|
|
2
|
+
export { Input } from './Input';
|
|
3
|
+
export { TextArea } from './TextArea';
|
|
4
|
+
export { Form } from './Form';
|
|
5
|
+
export { Select } from './Select';
|
|
6
|
+
export { Table } from './Table';
|
|
7
|
+
export { Modal, type ModalRef } from './Modal';
|
|
8
8
|
export { Loading } from './Loading';
|