ece-docs-components 1.0.105 → 1.0.107
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/cjs/_virtual/index8.js +2 -2
- package/dist/cjs/_virtual/index9.js +2 -2
- package/dist/cjs/components/AutocompleteSelect.js +6 -1
- package/dist/cjs/components/AutocompleteSelect.js.map +1 -1
- package/dist/cjs/components/FileUploadButton.js +30 -19
- package/dist/cjs/components/FileUploadButton.js.map +1 -1
- package/dist/cjs/node_modules/domhandler/lib/index.js +1 -1
- package/dist/cjs/node_modules/domutils/lib/index.js +1 -1
- package/dist/cjs/node_modules/html-dom-parser/lib/index.js +1 -1
- package/dist/cjs/node_modules/style-to-object/cjs/index.js +1 -1
- package/dist/esm/components/AutocompleteSelect.js +6 -1
- package/dist/esm/components/AutocompleteSelect.js.map +1 -1
- package/dist/esm/components/FileUploadButton.d.ts +7 -3
- package/dist/esm/components/FileUploadButton.js +31 -20
- package/dist/esm/components/FileUploadButton.js.map +1 -1
- package/package.json +1 -1
|
@@ -15,7 +15,12 @@ function AutocompleteSelect({ id, label, error, helperText, placeholder, fullWid
|
|
|
15
15
|
return (jsxRuntime.jsxs(AutocompleteWrapper, { className: className, sx: [
|
|
16
16
|
{ ...(!fullWidth && { width: "auto" }) },
|
|
17
17
|
...(Array.isArray(sx) ? sx : [sx]),
|
|
18
|
-
], children: [label && (jsxRuntime.jsx(Input.StyledLabel, { htmlFor: selectId, shrink: false, children: label })), jsxRuntime.jsx(material.Autocomplete, { id: selectId, options: options, value: value, disabled: disabled,
|
|
18
|
+
], children: [label && (jsxRuntime.jsx(Input.StyledLabel, { htmlFor: selectId, shrink: false, children: label })), jsxRuntime.jsx(material.Autocomplete, { id: selectId, options: options, value: value, disabled: disabled, getOptionLabel: (option) => option?.label || "", isOptionEqualToValue: (option, val) => option?.value === val?.value, onChange: (_event, newValue) => onChange(newValue), popupIcon: jsxRuntime.jsx(iconsMaterial.ExpandMoreRounded, { sx: { color: `${theme.palette.dark.main}66` } }), slotProps: {
|
|
19
|
+
popper: {
|
|
20
|
+
sx: {
|
|
21
|
+
zIndex: (muiTheme) => muiTheme.zIndex.modal + 1,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
19
24
|
paper: {
|
|
20
25
|
sx: {
|
|
21
26
|
borderRadius: 2,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutocompleteSelect.js","sources":["../../../../src/components/AutocompleteSelect.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n Autocomplete as MuiAutocomplete,\n FormHelperText,\n styled,\n} from \"@mui/material\";\nimport { ExpandMoreRounded } from \"@mui/icons-material\";\nimport { useTheme } from \"../ThemeProvider\"; // Adjust pathway according to project layout\nimport { Input, StyledLabel } from \"./Input\";\n\ninterface AutocompleteOption {\n value: string;\n label: string;\n}\n\ninterface AutocompleteSelectProps {\n id?: string;\n label?: string;\n error?: string;\n helperText?: string;\n placeholder?: string;\n fullWidth?: boolean;\n disabled?: boolean;\n options: AutocompleteOption[];\n value: AutocompleteOption | null;\n onChange: (value: AutocompleteOption | null) => void;\n className?: string;\n sx?: any;\n}\n\nconst AutocompleteWrapper = styled(\"div\")({\n width: \"100%\",\n});\n\nexport function AutocompleteSelect({\n id,\n label,\n error,\n helperText,\n placeholder,\n fullWidth = false,\n disabled = false,\n options,\n value,\n onChange,\n className = \"\",\n sx,\n}: AutocompleteSelectProps): React.JSX.Element {\n const theme = useTheme();\n const selectId =\n id || `auto-select-${Math.random().toString(36).substr(2, 9)}`;\n\n return (\n <AutocompleteWrapper\n className={className}\n sx={[\n { ...(!fullWidth && { width: \"auto\" }) },\n ...(Array.isArray(sx) ? sx : [sx]),\n ]}\n >\n {label && (\n <StyledLabel htmlFor={selectId} shrink={false}>\n {label}\n </StyledLabel>\n )}\n\n <MuiAutocomplete\n id={selectId}\n options={options}\n value={value}\n disabled={disabled}\n
|
|
1
|
+
{"version":3,"file":"AutocompleteSelect.js","sources":["../../../../src/components/AutocompleteSelect.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n Autocomplete as MuiAutocomplete,\n FormHelperText,\n styled,\n} from \"@mui/material\";\nimport { ExpandMoreRounded } from \"@mui/icons-material\";\nimport { useTheme } from \"../ThemeProvider\"; // Adjust pathway according to project layout\nimport { Input, StyledLabel } from \"./Input\";\n\ninterface AutocompleteOption {\n value: string;\n label: string;\n}\n\ninterface AutocompleteSelectProps {\n id?: string;\n label?: string;\n error?: string;\n helperText?: string;\n placeholder?: string;\n fullWidth?: boolean;\n disabled?: boolean;\n options: AutocompleteOption[];\n value: AutocompleteOption | null;\n onChange: (value: AutocompleteOption | null) => void;\n className?: string;\n sx?: any;\n}\n\nconst AutocompleteWrapper = styled(\"div\")({\n width: \"100%\",\n});\n\nexport function AutocompleteSelect({\n id,\n label,\n error,\n helperText,\n placeholder,\n fullWidth = false,\n disabled = false,\n options,\n value,\n onChange,\n className = \"\",\n sx,\n}: AutocompleteSelectProps): React.JSX.Element {\n const theme = useTheme();\n const selectId =\n id || `auto-select-${Math.random().toString(36).substr(2, 9)}`;\n\n return (\n <AutocompleteWrapper\n className={className}\n sx={[\n { ...(!fullWidth && { width: \"auto\" }) },\n ...(Array.isArray(sx) ? sx : [sx]),\n ]}\n >\n {label && (\n <StyledLabel htmlFor={selectId} shrink={false}>\n {label}\n </StyledLabel>\n )}\n\n <MuiAutocomplete\n id={selectId}\n options={options}\n value={value}\n disabled={disabled}\n getOptionLabel={(option: { label: string; value: string }) =>\n option?.label || \"\"\n }\n isOptionEqualToValue={(\n option: AutocompleteOption,\n val: AutocompleteOption,\n ) => option?.value === val?.value}\n onChange={(_event, newValue) => onChange(newValue)}\n popupIcon={\n <ExpandMoreRounded sx={{ color: `${theme.palette.dark.main}66` }} />\n }\n slotProps={{\n popper: {\n sx: {\n zIndex: (muiTheme) => muiTheme.zIndex.modal + 1,\n },\n },\n paper: {\n sx: {\n borderRadius: 2,\n boxShadow:\n \"0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)\",\n maxHeight: \"min(22rem, calc(100vh - 6rem))\",\n overflow: \"hidden\",\n backgroundColor: theme.palette.light.main,\n mt: 0.5,\n },\n },\n }}\n sx={{\n \"& .MuiOutlinedInput-root\": {\n padding: \"0 9px !important\",\n height: 48,\n display: \"flex\",\n alignItems: \"center\",\n },\n \"& .MuiAutocomplete-input\": {\n padding: \"0 !important\",\n },\n \"& + .MuiAutocomplete-popper .MuiAutocomplete-option\": {\n fontSize: \"1rem\",\n color: theme.palette.dark.main,\n '&[aria-selected=\"true\"]': {\n backgroundColor: \"transparent\",\n },\n '&[aria-selected=\"true\"].Mui-focused, &:hover, &.Mui-focused': {\n backgroundColor: `${theme.palette.primary.main}1A !important`,\n },\n },\n }}\n renderInput={(params: any) => {\n // 1. Separate structural configurations from direct props\n const { InputProps, inputProps, ...restParams } = params;\n\n return (\n <Input\n {...restParams}\n // 2. Safely spread native input elements\n inputProps={inputProps}\n // 3. Bind MUI's dynamic layout objects (adornments, ref) into the slot configuration\n InputProps={{\n ...InputProps,\n }}\n error={error}\n placeholder={placeholder}\n fullWidth\n // Explicitly empty string avoids passing a raw error object down to helperText slots\n helperText=\"\"\n />\n );\n }}\n />\n\n {error && (\n <FormHelperText\n sx={{\n mt: 0.75,\n fontSize: \"0.875rem\",\n color: theme.palette.error.main,\n }}\n >\n {error}\n </FormHelperText>\n )}\n\n {helperText && !error && (\n <FormHelperText\n sx={{\n mt: 0.75,\n fontSize: \"0.875rem\",\n color: `${theme.palette.dark.main}99`,\n }}\n >\n {helperText}\n </FormHelperText>\n )}\n </AutocompleteWrapper>\n );\n}\n"],"names":["styled","useTheme","_jsxs","_jsx","StyledLabel","MuiAutocomplete","ExpandMoreRounded","Input","FormHelperText"],"mappings":"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"}
|
|
@@ -7,10 +7,10 @@ var styles = require('@mui/material/styles');
|
|
|
7
7
|
var iconsMaterial = require('@mui/icons-material');
|
|
8
8
|
var reactToastify = require('react-toastify');
|
|
9
9
|
|
|
10
|
-
const HiddenInput = styles.styled(
|
|
11
|
-
display:
|
|
10
|
+
const HiddenInput = styles.styled("input")({
|
|
11
|
+
display: "none",
|
|
12
12
|
});
|
|
13
|
-
const FileUploadButton = ({ id, label =
|
|
13
|
+
const FileUploadButton = ({ id, label = "Upload File", accept, multiple = false, onFileSelect, variant = "primary", size = "md", onError, maxSizeBytes = 25 * 1024 * 1024, sendToast = true, children, }) => {
|
|
14
14
|
const handleFileChange = (event) => {
|
|
15
15
|
const files = event.target.files;
|
|
16
16
|
if (!files || files.length === 0) {
|
|
@@ -20,32 +20,43 @@ const FileUploadButton = ({ id, label = 'Upload File', accept, multiple = false,
|
|
|
20
20
|
// If multiple, filter; if single, validate the first
|
|
21
21
|
if (multiple) {
|
|
22
22
|
const valid = [];
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
const rejected = [];
|
|
24
|
+
for (const file of Array.from(files)) {
|
|
25
|
+
if (file.size > maxSizeBytes) {
|
|
26
|
+
rejected.push(file);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
valid.push(file);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (rejected.length > 0) {
|
|
33
|
+
onError?.(rejected);
|
|
34
|
+
}
|
|
35
|
+
if (valid.length === 0) {
|
|
36
|
+
onFileSelect?.(null);
|
|
37
|
+
event.target.value = "";
|
|
38
|
+
return;
|
|
27
39
|
}
|
|
28
40
|
const dt = new DataTransfer();
|
|
29
41
|
valid.forEach((f) => dt.items.add(f));
|
|
30
42
|
onFileSelect?.(dt.files);
|
|
43
|
+
return;
|
|
31
44
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
// Example: toast.error('File exceeds 5MB');
|
|
37
|
-
reactToastify.toast.error('File exceeds 25MB');
|
|
38
|
-
onFileSelect?.(null);
|
|
39
|
-
// Clear the input so user can reselect
|
|
40
|
-
event.target.value = '';
|
|
41
|
-
return;
|
|
45
|
+
const file = files[0];
|
|
46
|
+
if (file.size > maxSizeBytes) {
|
|
47
|
+
if (sendToast) {
|
|
48
|
+
reactToastify.toast.error("File exceeds 25MB");
|
|
42
49
|
}
|
|
43
|
-
|
|
50
|
+
onError?.([file]);
|
|
51
|
+
onFileSelect?.(null);
|
|
52
|
+
event.target.value = "";
|
|
53
|
+
return;
|
|
44
54
|
}
|
|
55
|
+
onFileSelect?.(files);
|
|
45
56
|
};
|
|
46
57
|
const autoId = React.useId();
|
|
47
58
|
const inputId = id || `file-upload-${autoId}`;
|
|
48
|
-
return (jsxRuntime.jsxs("label", { htmlFor: inputId, children: [jsxRuntime.jsx(HiddenInput, { id: inputId, type: "file", accept: accept, multiple: multiple, onChange: handleFileChange }), jsxRuntime.
|
|
59
|
+
return (jsxRuntime.jsxs("label", { htmlFor: inputId, children: [jsxRuntime.jsx(HiddenInput, { id: inputId, type: "file", accept: accept, multiple: multiple, onChange: handleFileChange }), jsxRuntime.jsx(Button.Button, { component: "span", variant: variant, size: size, children: children ?? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(iconsMaterial.FileUploadRounded, {}), label] })) })] }));
|
|
49
60
|
};
|
|
50
61
|
|
|
51
62
|
exports.FileUploadButton = FileUploadButton;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileUploadButton.js","sources":["../../../../src/components/FileUploadButton.tsx"],"sourcesContent":["import React, { useId } from
|
|
1
|
+
{"version":3,"file":"FileUploadButton.js","sources":["../../../../src/components/FileUploadButton.tsx"],"sourcesContent":["import React, { useId } from \"react\";\r\nimport { Button } from \"./Button\"; // Import your existing styled button component\r\nimport { styled } from \"@mui/material/styles\";\r\nimport { FileUploadRounded } from \"@mui/icons-material\";\r\nimport { toast } from \"react-toastify\";\r\n\r\ninterface FileUploadButtonProps {\r\n id?: string;\r\n label?: string;\r\n accept?: string;\r\n multiple?: boolean;\r\n onFileSelect?: (files: FileList | null) => void;\r\n variant?:\r\n | \"primary\"\r\n | \"secondary\"\r\n | \"outline\"\r\n | \"marked-read\"\r\n | \"mark-read\"\r\n | \"danger\";\r\n size?: \"sm\" | \"md\" | \"lg\";\r\n onError?: (files: File[]) => void;\r\n maxSizeBytes?: number;\r\n sendToast?: boolean;\r\n children?: React.ReactNode;\r\n}\r\n\r\nconst HiddenInput = styled(\"input\")({\r\n display: \"none\",\r\n});\r\n\r\nexport const FileUploadButton: React.FC<FileUploadButtonProps> = ({\r\n id,\r\n label = \"Upload File\",\r\n accept,\r\n multiple = false,\r\n onFileSelect,\r\n variant = \"primary\",\r\n size = \"md\",\r\n onError,\r\n maxSizeBytes = 25 * 1024 * 1024,\r\n sendToast = true,\r\n children,\r\n}) => {\r\n const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {\r\n const files = event.target.files;\r\n\r\n if (!files || files.length === 0) {\r\n onFileSelect?.(files);\r\n return;\r\n }\r\n\r\n // If multiple, filter; if single, validate the first\r\n if (multiple) {\r\n const valid: File[] = [];\r\n const rejected: File[] = [];\r\n for (const file of Array.from(files)) {\r\n if (file.size > maxSizeBytes) {\r\n rejected.push(file);\r\n } else {\r\n valid.push(file);\r\n }\r\n }\r\n\r\n if (rejected.length > 0) {\r\n onError?.(rejected);\r\n }\r\n\r\n if (valid.length === 0) {\r\n onFileSelect?.(null);\r\n event.target.value = \"\";\r\n return;\r\n }\r\n\r\n const dt = new DataTransfer();\r\n valid.forEach((f) => dt.items.add(f));\r\n onFileSelect?.(dt.files);\r\n return;\r\n }\r\n\r\n const file = files[0];\r\n if (file.size > maxSizeBytes) {\r\n if (sendToast) {\r\n toast.error(\"File exceeds 25MB\");\r\n }\r\n onError?.([file]);\r\n onFileSelect?.(null);\r\n event.target.value = \"\";\r\n return;\r\n }\r\n onFileSelect?.(files);\r\n };\r\n const autoId = useId();\r\n const inputId = id || `file-upload-${autoId}`;\r\n return (\r\n <label htmlFor={inputId}>\r\n <HiddenInput\r\n id={inputId}\r\n type=\"file\"\r\n accept={accept}\r\n multiple={multiple}\r\n onChange={handleFileChange}\r\n />\r\n {/* Render child, if not defined render old style fix*/}\r\n <Button component=\"span\" variant={variant} size={size}>\r\n {children ?? (\r\n <>\r\n <FileUploadRounded />\r\n {label}\r\n </>\r\n )}\r\n </Button>\r\n </label>\r\n );\r\n};\r\n"],"names":["styled","toast","useId","_jsxs","_jsx","Button","_Fragment","FileUploadRounded"],"mappings":"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"}
|
|
@@ -13,7 +13,12 @@ function AutocompleteSelect({ id, label, error, helperText, placeholder, fullWid
|
|
|
13
13
|
return (jsxs(AutocompleteWrapper, { className: className, sx: [
|
|
14
14
|
{ ...(!fullWidth && { width: "auto" }) },
|
|
15
15
|
...(Array.isArray(sx) ? sx : [sx]),
|
|
16
|
-
], children: [label && (jsx(StyledLabel, { htmlFor: selectId, shrink: false, children: label })), jsx(Autocomplete, { id: selectId, options: options, value: value, disabled: disabled,
|
|
16
|
+
], children: [label && (jsx(StyledLabel, { htmlFor: selectId, shrink: false, children: label })), jsx(Autocomplete, { id: selectId, options: options, value: value, disabled: disabled, getOptionLabel: (option) => option?.label || "", isOptionEqualToValue: (option, val) => option?.value === val?.value, onChange: (_event, newValue) => onChange(newValue), popupIcon: jsx(ExpandMoreRounded, { sx: { color: `${theme.palette.dark.main}66` } }), slotProps: {
|
|
17
|
+
popper: {
|
|
18
|
+
sx: {
|
|
19
|
+
zIndex: (muiTheme) => muiTheme.zIndex.modal + 1,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
17
22
|
paper: {
|
|
18
23
|
sx: {
|
|
19
24
|
borderRadius: 2,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutocompleteSelect.js","sources":["../../../../src/components/AutocompleteSelect.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n Autocomplete as MuiAutocomplete,\n FormHelperText,\n styled,\n} from \"@mui/material\";\nimport { ExpandMoreRounded } from \"@mui/icons-material\";\nimport { useTheme } from \"../ThemeProvider\"; // Adjust pathway according to project layout\nimport { Input, StyledLabel } from \"./Input\";\n\ninterface AutocompleteOption {\n value: string;\n label: string;\n}\n\ninterface AutocompleteSelectProps {\n id?: string;\n label?: string;\n error?: string;\n helperText?: string;\n placeholder?: string;\n fullWidth?: boolean;\n disabled?: boolean;\n options: AutocompleteOption[];\n value: AutocompleteOption | null;\n onChange: (value: AutocompleteOption | null) => void;\n className?: string;\n sx?: any;\n}\n\nconst AutocompleteWrapper = styled(\"div\")({\n width: \"100%\",\n});\n\nexport function AutocompleteSelect({\n id,\n label,\n error,\n helperText,\n placeholder,\n fullWidth = false,\n disabled = false,\n options,\n value,\n onChange,\n className = \"\",\n sx,\n}: AutocompleteSelectProps): React.JSX.Element {\n const theme = useTheme();\n const selectId =\n id || `auto-select-${Math.random().toString(36).substr(2, 9)}`;\n\n return (\n <AutocompleteWrapper\n className={className}\n sx={[\n { ...(!fullWidth && { width: \"auto\" }) },\n ...(Array.isArray(sx) ? sx : [sx]),\n ]}\n >\n {label && (\n <StyledLabel htmlFor={selectId} shrink={false}>\n {label}\n </StyledLabel>\n )}\n\n <MuiAutocomplete\n id={selectId}\n options={options}\n value={value}\n disabled={disabled}\n
|
|
1
|
+
{"version":3,"file":"AutocompleteSelect.js","sources":["../../../../src/components/AutocompleteSelect.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n Autocomplete as MuiAutocomplete,\n FormHelperText,\n styled,\n} from \"@mui/material\";\nimport { ExpandMoreRounded } from \"@mui/icons-material\";\nimport { useTheme } from \"../ThemeProvider\"; // Adjust pathway according to project layout\nimport { Input, StyledLabel } from \"./Input\";\n\ninterface AutocompleteOption {\n value: string;\n label: string;\n}\n\ninterface AutocompleteSelectProps {\n id?: string;\n label?: string;\n error?: string;\n helperText?: string;\n placeholder?: string;\n fullWidth?: boolean;\n disabled?: boolean;\n options: AutocompleteOption[];\n value: AutocompleteOption | null;\n onChange: (value: AutocompleteOption | null) => void;\n className?: string;\n sx?: any;\n}\n\nconst AutocompleteWrapper = styled(\"div\")({\n width: \"100%\",\n});\n\nexport function AutocompleteSelect({\n id,\n label,\n error,\n helperText,\n placeholder,\n fullWidth = false,\n disabled = false,\n options,\n value,\n onChange,\n className = \"\",\n sx,\n}: AutocompleteSelectProps): React.JSX.Element {\n const theme = useTheme();\n const selectId =\n id || `auto-select-${Math.random().toString(36).substr(2, 9)}`;\n\n return (\n <AutocompleteWrapper\n className={className}\n sx={[\n { ...(!fullWidth && { width: \"auto\" }) },\n ...(Array.isArray(sx) ? sx : [sx]),\n ]}\n >\n {label && (\n <StyledLabel htmlFor={selectId} shrink={false}>\n {label}\n </StyledLabel>\n )}\n\n <MuiAutocomplete\n id={selectId}\n options={options}\n value={value}\n disabled={disabled}\n getOptionLabel={(option: { label: string; value: string }) =>\n option?.label || \"\"\n }\n isOptionEqualToValue={(\n option: AutocompleteOption,\n val: AutocompleteOption,\n ) => option?.value === val?.value}\n onChange={(_event, newValue) => onChange(newValue)}\n popupIcon={\n <ExpandMoreRounded sx={{ color: `${theme.palette.dark.main}66` }} />\n }\n slotProps={{\n popper: {\n sx: {\n zIndex: (muiTheme) => muiTheme.zIndex.modal + 1,\n },\n },\n paper: {\n sx: {\n borderRadius: 2,\n boxShadow:\n \"0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)\",\n maxHeight: \"min(22rem, calc(100vh - 6rem))\",\n overflow: \"hidden\",\n backgroundColor: theme.palette.light.main,\n mt: 0.5,\n },\n },\n }}\n sx={{\n \"& .MuiOutlinedInput-root\": {\n padding: \"0 9px !important\",\n height: 48,\n display: \"flex\",\n alignItems: \"center\",\n },\n \"& .MuiAutocomplete-input\": {\n padding: \"0 !important\",\n },\n \"& + .MuiAutocomplete-popper .MuiAutocomplete-option\": {\n fontSize: \"1rem\",\n color: theme.palette.dark.main,\n '&[aria-selected=\"true\"]': {\n backgroundColor: \"transparent\",\n },\n '&[aria-selected=\"true\"].Mui-focused, &:hover, &.Mui-focused': {\n backgroundColor: `${theme.palette.primary.main}1A !important`,\n },\n },\n }}\n renderInput={(params: any) => {\n // 1. Separate structural configurations from direct props\n const { InputProps, inputProps, ...restParams } = params;\n\n return (\n <Input\n {...restParams}\n // 2. Safely spread native input elements\n inputProps={inputProps}\n // 3. Bind MUI's dynamic layout objects (adornments, ref) into the slot configuration\n InputProps={{\n ...InputProps,\n }}\n error={error}\n placeholder={placeholder}\n fullWidth\n // Explicitly empty string avoids passing a raw error object down to helperText slots\n helperText=\"\"\n />\n );\n }}\n />\n\n {error && (\n <FormHelperText\n sx={{\n mt: 0.75,\n fontSize: \"0.875rem\",\n color: theme.palette.error.main,\n }}\n >\n {error}\n </FormHelperText>\n )}\n\n {helperText && !error && (\n <FormHelperText\n sx={{\n mt: 0.75,\n fontSize: \"0.875rem\",\n color: `${theme.palette.dark.main}99`,\n }}\n >\n {helperText}\n </FormHelperText>\n )}\n </AutocompleteWrapper>\n );\n}\n"],"names":["_jsxs","_jsx","MuiAutocomplete"],"mappings":"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"}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
import React from
|
|
1
|
+
import React from "react";
|
|
2
2
|
interface FileUploadButtonProps {
|
|
3
3
|
id?: string;
|
|
4
4
|
label?: string;
|
|
5
5
|
accept?: string;
|
|
6
6
|
multiple?: boolean;
|
|
7
7
|
onFileSelect?: (files: FileList | null) => void;
|
|
8
|
-
variant?:
|
|
9
|
-
size?:
|
|
8
|
+
variant?: "primary" | "secondary" | "outline" | "marked-read" | "mark-read" | "danger";
|
|
9
|
+
size?: "sm" | "md" | "lg";
|
|
10
|
+
onError?: (files: File[]) => void;
|
|
11
|
+
maxSizeBytes?: number;
|
|
12
|
+
sendToast?: boolean;
|
|
13
|
+
children?: React.ReactNode;
|
|
10
14
|
}
|
|
11
15
|
export declare const FileUploadButton: React.FC<FileUploadButtonProps>;
|
|
12
16
|
export {};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
1
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { useId } from 'react';
|
|
3
3
|
import { Button } from './Button.js';
|
|
4
4
|
import { styled } from '@mui/material/styles';
|
|
5
5
|
import { FileUploadRounded } from '@mui/icons-material';
|
|
6
6
|
import { toast } from 'react-toastify';
|
|
7
7
|
|
|
8
|
-
const HiddenInput = styled(
|
|
9
|
-
display:
|
|
8
|
+
const HiddenInput = styled("input")({
|
|
9
|
+
display: "none",
|
|
10
10
|
});
|
|
11
|
-
const FileUploadButton = ({ id, label =
|
|
11
|
+
const FileUploadButton = ({ id, label = "Upload File", accept, multiple = false, onFileSelect, variant = "primary", size = "md", onError, maxSizeBytes = 25 * 1024 * 1024, sendToast = true, children, }) => {
|
|
12
12
|
const handleFileChange = (event) => {
|
|
13
13
|
const files = event.target.files;
|
|
14
14
|
if (!files || files.length === 0) {
|
|
@@ -18,32 +18,43 @@ const FileUploadButton = ({ id, label = 'Upload File', accept, multiple = false,
|
|
|
18
18
|
// If multiple, filter; if single, validate the first
|
|
19
19
|
if (multiple) {
|
|
20
20
|
const valid = [];
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
const rejected = [];
|
|
22
|
+
for (const file of Array.from(files)) {
|
|
23
|
+
if (file.size > maxSizeBytes) {
|
|
24
|
+
rejected.push(file);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
valid.push(file);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (rejected.length > 0) {
|
|
31
|
+
onError?.(rejected);
|
|
32
|
+
}
|
|
33
|
+
if (valid.length === 0) {
|
|
34
|
+
onFileSelect?.(null);
|
|
35
|
+
event.target.value = "";
|
|
36
|
+
return;
|
|
25
37
|
}
|
|
26
38
|
const dt = new DataTransfer();
|
|
27
39
|
valid.forEach((f) => dt.items.add(f));
|
|
28
40
|
onFileSelect?.(dt.files);
|
|
41
|
+
return;
|
|
29
42
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (
|
|
33
|
-
|
|
34
|
-
// Example: toast.error('File exceeds 5MB');
|
|
35
|
-
toast.error('File exceeds 25MB');
|
|
36
|
-
onFileSelect?.(null);
|
|
37
|
-
// Clear the input so user can reselect
|
|
38
|
-
event.target.value = '';
|
|
39
|
-
return;
|
|
43
|
+
const file = files[0];
|
|
44
|
+
if (file.size > maxSizeBytes) {
|
|
45
|
+
if (sendToast) {
|
|
46
|
+
toast.error("File exceeds 25MB");
|
|
40
47
|
}
|
|
41
|
-
|
|
48
|
+
onError?.([file]);
|
|
49
|
+
onFileSelect?.(null);
|
|
50
|
+
event.target.value = "";
|
|
51
|
+
return;
|
|
42
52
|
}
|
|
53
|
+
onFileSelect?.(files);
|
|
43
54
|
};
|
|
44
55
|
const autoId = useId();
|
|
45
56
|
const inputId = id || `file-upload-${autoId}`;
|
|
46
|
-
return (jsxs("label", { htmlFor: inputId, children: [jsx(HiddenInput, { id: inputId, type: "file", accept: accept, multiple: multiple, onChange: handleFileChange }),
|
|
57
|
+
return (jsxs("label", { htmlFor: inputId, children: [jsx(HiddenInput, { id: inputId, type: "file", accept: accept, multiple: multiple, onChange: handleFileChange }), jsx(Button, { component: "span", variant: variant, size: size, children: children ?? (jsxs(Fragment, { children: [jsx(FileUploadRounded, {}), label] })) })] }));
|
|
47
58
|
};
|
|
48
59
|
|
|
49
60
|
export { FileUploadButton };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileUploadButton.js","sources":["../../../../src/components/FileUploadButton.tsx"],"sourcesContent":["import React, { useId } from
|
|
1
|
+
{"version":3,"file":"FileUploadButton.js","sources":["../../../../src/components/FileUploadButton.tsx"],"sourcesContent":["import React, { useId } from \"react\";\r\nimport { Button } from \"./Button\"; // Import your existing styled button component\r\nimport { styled } from \"@mui/material/styles\";\r\nimport { FileUploadRounded } from \"@mui/icons-material\";\r\nimport { toast } from \"react-toastify\";\r\n\r\ninterface FileUploadButtonProps {\r\n id?: string;\r\n label?: string;\r\n accept?: string;\r\n multiple?: boolean;\r\n onFileSelect?: (files: FileList | null) => void;\r\n variant?:\r\n | \"primary\"\r\n | \"secondary\"\r\n | \"outline\"\r\n | \"marked-read\"\r\n | \"mark-read\"\r\n | \"danger\";\r\n size?: \"sm\" | \"md\" | \"lg\";\r\n onError?: (files: File[]) => void;\r\n maxSizeBytes?: number;\r\n sendToast?: boolean;\r\n children?: React.ReactNode;\r\n}\r\n\r\nconst HiddenInput = styled(\"input\")({\r\n display: \"none\",\r\n});\r\n\r\nexport const FileUploadButton: React.FC<FileUploadButtonProps> = ({\r\n id,\r\n label = \"Upload File\",\r\n accept,\r\n multiple = false,\r\n onFileSelect,\r\n variant = \"primary\",\r\n size = \"md\",\r\n onError,\r\n maxSizeBytes = 25 * 1024 * 1024,\r\n sendToast = true,\r\n children,\r\n}) => {\r\n const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {\r\n const files = event.target.files;\r\n\r\n if (!files || files.length === 0) {\r\n onFileSelect?.(files);\r\n return;\r\n }\r\n\r\n // If multiple, filter; if single, validate the first\r\n if (multiple) {\r\n const valid: File[] = [];\r\n const rejected: File[] = [];\r\n for (const file of Array.from(files)) {\r\n if (file.size > maxSizeBytes) {\r\n rejected.push(file);\r\n } else {\r\n valid.push(file);\r\n }\r\n }\r\n\r\n if (rejected.length > 0) {\r\n onError?.(rejected);\r\n }\r\n\r\n if (valid.length === 0) {\r\n onFileSelect?.(null);\r\n event.target.value = \"\";\r\n return;\r\n }\r\n\r\n const dt = new DataTransfer();\r\n valid.forEach((f) => dt.items.add(f));\r\n onFileSelect?.(dt.files);\r\n return;\r\n }\r\n\r\n const file = files[0];\r\n if (file.size > maxSizeBytes) {\r\n if (sendToast) {\r\n toast.error(\"File exceeds 25MB\");\r\n }\r\n onError?.([file]);\r\n onFileSelect?.(null);\r\n event.target.value = \"\";\r\n return;\r\n }\r\n onFileSelect?.(files);\r\n };\r\n const autoId = useId();\r\n const inputId = id || `file-upload-${autoId}`;\r\n return (\r\n <label htmlFor={inputId}>\r\n <HiddenInput\r\n id={inputId}\r\n type=\"file\"\r\n accept={accept}\r\n multiple={multiple}\r\n onChange={handleFileChange}\r\n />\r\n {/* Render child, if not defined render old style fix*/}\r\n <Button component=\"span\" variant={variant} size={size}>\r\n {children ?? (\r\n <>\r\n <FileUploadRounded />\r\n {label}\r\n </>\r\n )}\r\n </Button>\r\n </label>\r\n );\r\n};\r\n"],"names":["_jsxs","_jsx","_Fragment"],"mappings":"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"}
|