@justin_evo/evo-ui 1.1.0 → 1.2.1
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 +3 -3
- package/dist/TopNav/TopNav.d.ts +19 -0
- package/dist/declarations.d.ts +6 -6
- package/dist/evo-ui.css +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +3301 -3197
- package/package.json +52 -52
- package/src/Alert/Alert.tsx +49 -49
- package/src/AutoComplete/AutoComplete.tsx +810 -810
- package/src/Badge/Badge.tsx +53 -53
- package/src/Breadcrumb/Breadcrumb.tsx +53 -53
- package/src/Button/Button.tsx +125 -125
- package/src/Card/Card.tsx +257 -257
- package/src/Checkbox/Checkbox.tsx +59 -59
- package/src/CommandPalette/CommandPalette.tsx +185 -185
- package/src/Container/Container.tsx +31 -31
- package/src/Divider/Divider.tsx +31 -31
- package/src/Form/Form.tsx +185 -185
- package/src/Grid/Grid.tsx +66 -66
- package/src/ImageCropper/ImageCropper.tsx +911 -911
- package/src/Input/Input.tsx +74 -74
- package/src/Modal/Modal.tsx +77 -77
- package/src/Nav/Nav.tsx +708 -708
- package/src/Notification/Notification.tsx +1503 -1503
- package/src/Pagination/Pagination.tsx +76 -76
- package/src/Radio/Radio.tsx +69 -69
- package/src/RichTextArea/RichTextArea.tsx +886 -869
- package/src/Select/Select.tsx +515 -515
- package/src/Skeleton/Skeleton.tsx +70 -70
- package/src/Stack/Stack.tsx +52 -52
- package/src/Table/Table.tsx +335 -335
- package/src/Tabs/Tabs.tsx +90 -90
- package/src/Theme/ThemeProvider.tsx +253 -253
- package/src/Theme/ThemeToggle.tsx +79 -79
- package/src/Toggle/Toggle.tsx +48 -48
- package/src/Tooltip/Tooltip.tsx +38 -38
- package/src/TopNav/TopNav.tsx +1163 -994
- package/src/TreeSelect/TreeSelect.tsx +825 -825
- package/src/css/alert.module.scss +93 -93
- package/src/css/autocomplete.module.scss +416 -416
- package/src/css/badge.module.scss +82 -82
- package/src/css/base/_color.scss +159 -159
- package/src/css/base/_theme.scss +237 -237
- package/src/css/base/_variables.scss +161 -161
- package/src/css/breadcrumb.module.scss +50 -50
- package/src/css/button.module.scss +385 -385
- package/src/css/card.module.scss +217 -217
- package/src/css/checkbox.module.scss +123 -120
- package/src/css/commandpalette.module.scss +211 -211
- package/src/css/container.module.scss +18 -18
- package/src/css/divider.module.scss +41 -41
- package/src/css/form.module.scss +245 -245
- package/src/css/imagecropper.module.scss +397 -397
- package/src/css/input.module.scss +89 -89
- package/src/css/modal.module.scss +105 -105
- package/src/css/nav.module.scss +494 -494
- package/src/css/notification.module.scss +691 -691
- package/src/css/pagination.module.scss +63 -63
- package/src/css/radio.module.scss +89 -89
- package/src/css/richtextarea.module.scss +307 -307
- package/src/css/select.module.scss +525 -525
- package/src/css/skeleton.module.scss +30 -30
- package/src/css/table.module.scss +386 -386
- package/src/css/tabs.module.scss +63 -63
- package/src/css/theme-toggle.module.scss +83 -83
- package/src/css/toggle.module.scss +54 -54
- package/src/css/tooltip.module.scss +97 -97
- package/src/css/topnav.module.scss +568 -396
- package/src/css/treeselect.module.scss +558 -558
- package/src/css/utilities/_borders.scss +111 -111
- package/src/css/utilities/_colors.scss +66 -66
- package/src/css/utilities/_effects.scss +216 -216
- package/src/css/utilities/_layout.scss +181 -181
- package/src/css/utilities/_position.scss +75 -75
- package/src/css/utilities/_sizing.scss +138 -138
- package/src/css/utilities/_spacing.scss +99 -99
- package/src/css/utilities/_typography.scss +121 -121
- package/src/css/utilities/index.scss +24 -24
- package/src/declarations.d.ts +6 -6
- package/src/index.ts +60 -60
package/src/Input/Input.tsx
CHANGED
|
@@ -1,74 +1,74 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import styles from '../css/input.module.scss';
|
|
3
|
-
|
|
4
|
-
interface EvoInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {
|
|
5
|
-
label?: string;
|
|
6
|
-
helperText?: string;
|
|
7
|
-
error?: string;
|
|
8
|
-
size?: 'sm' | 'md' | 'lg';
|
|
9
|
-
leadingAdornment?: React.ReactNode;
|
|
10
|
-
trailingAdornment?: React.ReactNode;
|
|
11
|
-
fullWidth?: boolean;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const EvoInput = ({
|
|
15
|
-
label,
|
|
16
|
-
helperText,
|
|
17
|
-
error,
|
|
18
|
-
size = 'md',
|
|
19
|
-
leadingAdornment,
|
|
20
|
-
trailingAdornment,
|
|
21
|
-
fullWidth = false,
|
|
22
|
-
className = '',
|
|
23
|
-
id,
|
|
24
|
-
...rest
|
|
25
|
-
}: EvoInputProps) => {
|
|
26
|
-
const inputId = id ?? label?.toLowerCase().replace(/\s+/g, '-');
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<div className={[styles.field, fullWidth ? styles.fullWidth : '', className].filter(Boolean).join(' ')}>
|
|
30
|
-
{label && (
|
|
31
|
-
<label htmlFor={inputId} className={styles.label}>
|
|
32
|
-
{label}
|
|
33
|
-
</label>
|
|
34
|
-
)}
|
|
35
|
-
|
|
36
|
-
<div
|
|
37
|
-
className={[
|
|
38
|
-
styles.inputWrapper,
|
|
39
|
-
styles[size],
|
|
40
|
-
error ? styles.hasError : '',
|
|
41
|
-
]
|
|
42
|
-
.filter(Boolean)
|
|
43
|
-
.join(' ')}
|
|
44
|
-
>
|
|
45
|
-
{leadingAdornment && <span className={styles.adornment}>{leadingAdornment}</span>}
|
|
46
|
-
<input
|
|
47
|
-
id={inputId}
|
|
48
|
-
className={styles.input}
|
|
49
|
-
aria-invalid={!!error}
|
|
50
|
-
aria-describedby={
|
|
51
|
-
error ? `${inputId}-error` : helperText ? `${inputId}-helper` : undefined
|
|
52
|
-
}
|
|
53
|
-
{...rest}
|
|
54
|
-
/>
|
|
55
|
-
{trailingAdornment && (
|
|
56
|
-
<span className={`${styles.adornment} ${styles.trailingAdornment}`}>
|
|
57
|
-
{trailingAdornment}
|
|
58
|
-
</span>
|
|
59
|
-
)}
|
|
60
|
-
</div>
|
|
61
|
-
|
|
62
|
-
{error && (
|
|
63
|
-
<p id={`${inputId}-error`} className={styles.errorText}>
|
|
64
|
-
{error}
|
|
65
|
-
</p>
|
|
66
|
-
)}
|
|
67
|
-
{!error && helperText && (
|
|
68
|
-
<p id={`${inputId}-helper`} className={styles.helperText}>
|
|
69
|
-
{helperText}
|
|
70
|
-
</p>
|
|
71
|
-
)}
|
|
72
|
-
</div>
|
|
73
|
-
);
|
|
74
|
-
};
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styles from '../css/input.module.scss';
|
|
3
|
+
|
|
4
|
+
interface EvoInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {
|
|
5
|
+
label?: string;
|
|
6
|
+
helperText?: string;
|
|
7
|
+
error?: string;
|
|
8
|
+
size?: 'sm' | 'md' | 'lg';
|
|
9
|
+
leadingAdornment?: React.ReactNode;
|
|
10
|
+
trailingAdornment?: React.ReactNode;
|
|
11
|
+
fullWidth?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const EvoInput = ({
|
|
15
|
+
label,
|
|
16
|
+
helperText,
|
|
17
|
+
error,
|
|
18
|
+
size = 'md',
|
|
19
|
+
leadingAdornment,
|
|
20
|
+
trailingAdornment,
|
|
21
|
+
fullWidth = false,
|
|
22
|
+
className = '',
|
|
23
|
+
id,
|
|
24
|
+
...rest
|
|
25
|
+
}: EvoInputProps) => {
|
|
26
|
+
const inputId = id ?? label?.toLowerCase().replace(/\s+/g, '-');
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<div className={[styles.field, fullWidth ? styles.fullWidth : '', className].filter(Boolean).join(' ')}>
|
|
30
|
+
{label && (
|
|
31
|
+
<label htmlFor={inputId} className={styles.label}>
|
|
32
|
+
{label}
|
|
33
|
+
</label>
|
|
34
|
+
)}
|
|
35
|
+
|
|
36
|
+
<div
|
|
37
|
+
className={[
|
|
38
|
+
styles.inputWrapper,
|
|
39
|
+
styles[size],
|
|
40
|
+
error ? styles.hasError : '',
|
|
41
|
+
]
|
|
42
|
+
.filter(Boolean)
|
|
43
|
+
.join(' ')}
|
|
44
|
+
>
|
|
45
|
+
{leadingAdornment && <span className={styles.adornment}>{leadingAdornment}</span>}
|
|
46
|
+
<input
|
|
47
|
+
id={inputId}
|
|
48
|
+
className={styles.input}
|
|
49
|
+
aria-invalid={!!error}
|
|
50
|
+
aria-describedby={
|
|
51
|
+
error ? `${inputId}-error` : helperText ? `${inputId}-helper` : undefined
|
|
52
|
+
}
|
|
53
|
+
{...rest}
|
|
54
|
+
/>
|
|
55
|
+
{trailingAdornment && (
|
|
56
|
+
<span className={`${styles.adornment} ${styles.trailingAdornment}`}>
|
|
57
|
+
{trailingAdornment}
|
|
58
|
+
</span>
|
|
59
|
+
)}
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
{error && (
|
|
63
|
+
<p id={`${inputId}-error`} className={styles.errorText}>
|
|
64
|
+
{error}
|
|
65
|
+
</p>
|
|
66
|
+
)}
|
|
67
|
+
{!error && helperText && (
|
|
68
|
+
<p id={`${inputId}-helper`} className={styles.helperText}>
|
|
69
|
+
{helperText}
|
|
70
|
+
</p>
|
|
71
|
+
)}
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
};
|
package/src/Modal/Modal.tsx
CHANGED
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
import React, { useEffect } from 'react';
|
|
2
|
-
import ReactDOM from 'react-dom';
|
|
3
|
-
import styles from '../css/modal.module.scss';
|
|
4
|
-
|
|
5
|
-
type ModalSize = 'sm' | 'md' | 'lg' | 'fullscreen';
|
|
6
|
-
|
|
7
|
-
interface EvoModalProps {
|
|
8
|
-
open: boolean;
|
|
9
|
-
onClose: () => void;
|
|
10
|
-
children: React.ReactNode;
|
|
11
|
-
size?: ModalSize;
|
|
12
|
-
className?: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface EvoModalHeaderProps {
|
|
16
|
-
children: React.ReactNode;
|
|
17
|
-
onClose?: () => void;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
interface EvoModalBodyProps { children: React.ReactNode; }
|
|
21
|
-
interface EvoModalFooterProps { children: React.ReactNode; }
|
|
22
|
-
|
|
23
|
-
const EvoModalHeader = ({ children, onClose }: EvoModalHeaderProps) => (
|
|
24
|
-
<div className={styles.header}>
|
|
25
|
-
<div className={styles.headerContent}>{children}</div>
|
|
26
|
-
{onClose && (
|
|
27
|
-
<button className={styles.closeBtn} onClick={onClose} aria-label="Close modal">
|
|
28
|
-
✕
|
|
29
|
-
</button>
|
|
30
|
-
)}
|
|
31
|
-
</div>
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
const EvoModalBody = ({ children }: EvoModalBodyProps) => (
|
|
35
|
-
<div className={styles.body}>{children}</div>
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
const EvoModalFooter = ({ children }: EvoModalFooterProps) => (
|
|
39
|
-
<div className={styles.footer}>{children}</div>
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
export const EvoModal = ({ open, onClose, children, size = 'md', className = '' }: EvoModalProps) => {
|
|
43
|
-
useEffect(() => {
|
|
44
|
-
if (!open) return;
|
|
45
|
-
document.body.style.overflow = 'hidden';
|
|
46
|
-
return () => { document.body.style.overflow = ''; };
|
|
47
|
-
}, [open]);
|
|
48
|
-
|
|
49
|
-
useEffect(() => {
|
|
50
|
-
if (!open) return;
|
|
51
|
-
const handler = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); };
|
|
52
|
-
document.addEventListener('keydown', handler);
|
|
53
|
-
return () => document.removeEventListener('keydown', handler);
|
|
54
|
-
}, [open, onClose]);
|
|
55
|
-
|
|
56
|
-
if (!open) return null;
|
|
57
|
-
|
|
58
|
-
return ReactDOM.createPortal(
|
|
59
|
-
<div
|
|
60
|
-
className={styles.overlay}
|
|
61
|
-
onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}
|
|
62
|
-
>
|
|
63
|
-
<div
|
|
64
|
-
className={[styles.dialog, styles[size], className].filter(Boolean).join(' ')}
|
|
65
|
-
role="dialog"
|
|
66
|
-
aria-modal="true"
|
|
67
|
-
>
|
|
68
|
-
{children}
|
|
69
|
-
</div>
|
|
70
|
-
</div>,
|
|
71
|
-
document.body
|
|
72
|
-
);
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
EvoModal.Header = EvoModalHeader;
|
|
76
|
-
EvoModal.Body = EvoModalBody;
|
|
77
|
-
EvoModal.Footer = EvoModalFooter;
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import ReactDOM from 'react-dom';
|
|
3
|
+
import styles from '../css/modal.module.scss';
|
|
4
|
+
|
|
5
|
+
type ModalSize = 'sm' | 'md' | 'lg' | 'fullscreen';
|
|
6
|
+
|
|
7
|
+
interface EvoModalProps {
|
|
8
|
+
open: boolean;
|
|
9
|
+
onClose: () => void;
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
size?: ModalSize;
|
|
12
|
+
className?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface EvoModalHeaderProps {
|
|
16
|
+
children: React.ReactNode;
|
|
17
|
+
onClose?: () => void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface EvoModalBodyProps { children: React.ReactNode; }
|
|
21
|
+
interface EvoModalFooterProps { children: React.ReactNode; }
|
|
22
|
+
|
|
23
|
+
const EvoModalHeader = ({ children, onClose }: EvoModalHeaderProps) => (
|
|
24
|
+
<div className={styles.header}>
|
|
25
|
+
<div className={styles.headerContent}>{children}</div>
|
|
26
|
+
{onClose && (
|
|
27
|
+
<button className={styles.closeBtn} onClick={onClose} aria-label="Close modal">
|
|
28
|
+
✕
|
|
29
|
+
</button>
|
|
30
|
+
)}
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const EvoModalBody = ({ children }: EvoModalBodyProps) => (
|
|
35
|
+
<div className={styles.body}>{children}</div>
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const EvoModalFooter = ({ children }: EvoModalFooterProps) => (
|
|
39
|
+
<div className={styles.footer}>{children}</div>
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
export const EvoModal = ({ open, onClose, children, size = 'md', className = '' }: EvoModalProps) => {
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
if (!open) return;
|
|
45
|
+
document.body.style.overflow = 'hidden';
|
|
46
|
+
return () => { document.body.style.overflow = ''; };
|
|
47
|
+
}, [open]);
|
|
48
|
+
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
if (!open) return;
|
|
51
|
+
const handler = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); };
|
|
52
|
+
document.addEventListener('keydown', handler);
|
|
53
|
+
return () => document.removeEventListener('keydown', handler);
|
|
54
|
+
}, [open, onClose]);
|
|
55
|
+
|
|
56
|
+
if (!open) return null;
|
|
57
|
+
|
|
58
|
+
return ReactDOM.createPortal(
|
|
59
|
+
<div
|
|
60
|
+
className={styles.overlay}
|
|
61
|
+
onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}
|
|
62
|
+
>
|
|
63
|
+
<div
|
|
64
|
+
className={[styles.dialog, styles[size], className].filter(Boolean).join(' ')}
|
|
65
|
+
role="dialog"
|
|
66
|
+
aria-modal="true"
|
|
67
|
+
>
|
|
68
|
+
{children}
|
|
69
|
+
</div>
|
|
70
|
+
</div>,
|
|
71
|
+
document.body
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
EvoModal.Header = EvoModalHeader;
|
|
76
|
+
EvoModal.Body = EvoModalBody;
|
|
77
|
+
EvoModal.Footer = EvoModalFooter;
|