@uxf/ui 1.0.0-beta.103 → 1.0.0-beta.105
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/avatar-file-input/avatar-file-input.js +1 -1
- package/avatar-file-input/avatar-file-input.stories.js +4 -10
- package/css/dropzone.css +1 -1
- package/css/file-input.css +25 -56
- package/dropzone/dropzone-input.js +4 -0
- package/dropzone/dropzone.stories.d.ts +0 -2
- package/dropzone/dropzone.stories.js +7 -47
- package/file-input/file-input-base.d.ts +2 -2
- package/file-input/file-input-base.js +7 -42
- package/file-input/file-input.d.ts +2 -1
- package/file-input/file-input.js +29 -2
- package/file-input/file-input.stories.js +28 -19
- package/mutli-combobox/multi-combobox.js +5 -7
- package/package.json +1 -1
- package/utils/mocks/uploadFIle.mock.d.ts +2 -0
- package/utils/mocks/uploadFIle.mock.js +44 -0
|
@@ -42,6 +42,6 @@ exports.AvatarFileInput = (0, forwardRef_1.forwardRef)("AvatarFileInput", (props
|
|
|
42
42
|
react_1.default.createElement("label", { className: (0, cx_1.cx)("uxf-avatar-file-input__label", stateClassNames), htmlFor: id, tabIndex: 0 },
|
|
43
43
|
react_1.default.createElement(icon_1.Icon, { className: (0, cx_1.cx)("uxf-avatar-file-input__label__icon", stateClassNames), name: "cloud", size: 28 })),
|
|
44
44
|
props.label && typeof props.label === "string" ? (react_1.default.createElement("span", { className: (0, cx_1.cx)("uxf-avatar-file-input__label-text", stateClassNames) }, props.label)) : (props.label),
|
|
45
|
-
react_1.default.createElement(file_input_base_1.BaseFileInput, { accept: props.accept, "aria-describedby": errorId, "aria-invalid": props.isInvalid, className: "uxf-avatar-file-input__input", form: props.form, id: id, isDisabled: props.isDisabled, isInvalid: props.isInvalid, isReadOnly: props.isReadOnly, isRequired: props.isRequired, name: props.name, onBlur: input.onBlur, onChange: props.onChange, onFocus: input.onFocus, onUploadError: props.onUploadError,
|
|
45
|
+
react_1.default.createElement(file_input_base_1.BaseFileInput, { accept: props.accept, "aria-describedby": errorId, "aria-invalid": props.isInvalid, className: "uxf-avatar-file-input__input", form: props.form, id: id, isDisabled: props.isDisabled, isInvalid: props.isInvalid, isReadOnly: props.isReadOnly, isRequired: props.isRequired, name: props.name, onBlur: input.onBlur, onChange: props.onChange, onFocus: input.onFocus, onUploadError: props.onUploadError, onUploadFile: props.onUploadFile, ref: ref }),
|
|
46
46
|
props.helperText && (react_1.default.createElement("div", { className: (0, cx_1.cx)("uxf-helper-text", errorId && classes_1.CLASSES.IS_INVALID), id: errorId }, props.helperText))));
|
|
47
47
|
});
|
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.Default = void 0;
|
|
7
|
+
const uploadFIle_mock_1 = require("@uxf/ui/utils/mocks/uploadFIle.mock");
|
|
7
8
|
const react_1 = __importDefault(require("react"));
|
|
8
9
|
const index_1 = require("./index");
|
|
9
10
|
exports.default = {
|
|
@@ -21,17 +22,10 @@ function Default() {
|
|
|
21
22
|
// eslint-disable-next-line no-console
|
|
22
23
|
console.log("Upload error", err);
|
|
23
24
|
};
|
|
24
|
-
const handleUpload = (files, namespace) => {
|
|
25
|
-
return new Promise((resolve) => {
|
|
26
|
-
// eslint-disable-next-line no-console
|
|
27
|
-
console.log("Upload handler", files, namespace);
|
|
28
|
-
resolve([]);
|
|
29
|
-
});
|
|
30
|
-
};
|
|
31
25
|
const storyAvatarFileInputs = (react_1.default.createElement("div", { className: "space-y-8" },
|
|
32
|
-
react_1.default.createElement(index_1.AvatarFileInput, { onChange: handleChange, onUploadError: handleUploadError,
|
|
33
|
-
react_1.default.createElement(index_1.AvatarFileInput, { isDisabled: true, onChange: handleChange, onUploadError: handleUploadError,
|
|
34
|
-
react_1.default.createElement(index_1.AvatarFileInput, { id: "afi", isInvalid: true, label: "Vyberte Avatar", onChange: handleChange, onUploadError: handleUploadError,
|
|
26
|
+
react_1.default.createElement(index_1.AvatarFileInput, { onChange: handleChange, onUploadError: handleUploadError, onUploadFile: uploadFIle_mock_1.uploadFile }),
|
|
27
|
+
react_1.default.createElement(index_1.AvatarFileInput, { isDisabled: true, onChange: handleChange, onUploadError: handleUploadError, onUploadFile: uploadFIle_mock_1.uploadFile }),
|
|
28
|
+
react_1.default.createElement(index_1.AvatarFileInput, { id: "afi", isInvalid: true, label: "Vyberte Avatar", onChange: handleChange, onUploadError: handleUploadError, onUploadFile: uploadFIle_mock_1.uploadFile })));
|
|
35
29
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
36
30
|
react_1.default.createElement("div", { className: "light space-y-2 p-20" }, storyAvatarFileInputs),
|
|
37
31
|
react_1.default.createElement("div", { className: "dark space-y-2 bg-gray-900 p-20" }, storyAvatarFileInputs)));
|
package/css/dropzone.css
CHANGED
package/css/file-input.css
CHANGED
|
@@ -1,94 +1,63 @@
|
|
|
1
1
|
.uxf-file-input {
|
|
2
2
|
&__input {
|
|
3
|
-
@apply
|
|
3
|
+
@apply hidden;
|
|
4
|
+
}
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
6
|
+
&__label {
|
|
7
|
+
@apply cursor-pointer flex overflow-auto;
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
@apply
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
:root .dark & {
|
|
14
|
-
@apply border-gray-700 bg-gray-800;
|
|
9
|
+
&.is-loading {
|
|
10
|
+
@apply cursor-not-allowed;
|
|
15
11
|
}
|
|
16
12
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
:root .light & {
|
|
21
|
-
@apply bg-gray-100 outline-gray-200;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
:root .dark & {
|
|
25
|
-
@apply bg-gray-800 text-gray-200 outline-gray-700;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
&:hover {
|
|
29
|
-
@apply cursor-pointer;
|
|
30
|
-
|
|
13
|
+
&.is-invalid {
|
|
14
|
+
.uxf-file-input__label__button,
|
|
15
|
+
.uxf-file-input__label__wrapper {
|
|
31
16
|
:root .light & {
|
|
32
|
-
@apply
|
|
17
|
+
@apply border-error-500 text-error-500;
|
|
33
18
|
}
|
|
34
19
|
|
|
35
20
|
:root .dark & {
|
|
36
|
-
@apply
|
|
21
|
+
@apply border-error-500 text-error-500;
|
|
37
22
|
}
|
|
38
23
|
}
|
|
39
24
|
}
|
|
40
25
|
|
|
41
|
-
|
|
42
|
-
@apply
|
|
26
|
+
&__button {
|
|
27
|
+
@apply px-3;
|
|
43
28
|
|
|
44
29
|
:root .light & {
|
|
45
|
-
@apply
|
|
30
|
+
@apply border-gray-200 bg-gray-100;
|
|
46
31
|
}
|
|
47
32
|
|
|
48
33
|
:root .dark & {
|
|
49
|
-
@apply
|
|
34
|
+
@apply border-gray-700 bg-gray-800;
|
|
50
35
|
}
|
|
51
36
|
|
|
52
|
-
|
|
53
|
-
@apply cursor-not-allowed;
|
|
54
|
-
|
|
37
|
+
&:hover {
|
|
55
38
|
:root .light & {
|
|
56
|
-
@apply bg-
|
|
39
|
+
@apply bg-gray-200;
|
|
57
40
|
}
|
|
58
41
|
|
|
59
42
|
:root .dark & {
|
|
60
|
-
@apply bg-
|
|
43
|
+
@apply bg-gray-700;
|
|
61
44
|
}
|
|
62
45
|
}
|
|
63
46
|
}
|
|
64
47
|
|
|
65
|
-
|
|
48
|
+
&__wrapper {
|
|
49
|
+
@apply flex items-center border px-3 rounded-r-md w-full min-w-0;
|
|
50
|
+
|
|
66
51
|
:root .light & {
|
|
67
|
-
@apply border-
|
|
52
|
+
@apply border-gray-200;
|
|
68
53
|
}
|
|
69
54
|
|
|
70
55
|
:root .dark & {
|
|
71
|
-
@apply border-
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
&::file-selector-button {
|
|
75
|
-
:root .light & {
|
|
76
|
-
@apply text-error-500;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
:root .dark & {
|
|
80
|
-
@apply text-error-500;
|
|
81
|
-
}
|
|
56
|
+
@apply border-gray-700;
|
|
82
57
|
}
|
|
83
|
-
}
|
|
84
58
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
@apply border-primary-500;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
:root .dark & {
|
|
91
|
-
@apply border-primary-500;
|
|
59
|
+
&__file-name {
|
|
60
|
+
@apply truncate;
|
|
92
61
|
}
|
|
93
62
|
}
|
|
94
63
|
}
|
|
@@ -104,9 +104,13 @@ exports.DropzoneInput = (0, react_1.forwardRef)((props, ref) => {
|
|
|
104
104
|
onDrop: handleFileDrop,
|
|
105
105
|
preventDropOnDocument: props.noDrag,
|
|
106
106
|
});
|
|
107
|
+
const labelOnCLick = (e) => {
|
|
108
|
+
e.stopPropagation();
|
|
109
|
+
};
|
|
107
110
|
return (react_1.default.createElement("div", { className: "uxf-dropzone" },
|
|
108
111
|
react_1.default.createElement("label", { ...getRootProps({
|
|
109
112
|
className: (0, cx_1.cx)("uxf-dropzone__label", props.isInvalid && classes_1.CLASSES.IS_INVALID, props.isDisabled && classes_1.CLASSES.IS_DISABLED, props.noClick && "cursor-auto"),
|
|
113
|
+
onClick: labelOnCLick,
|
|
110
114
|
}), ref: (0, composeRefs_1.composeRefs)(ref, rootRef) },
|
|
111
115
|
react_1.default.createElement(icon_1.Icon, { className: "uxf-dropzone__label__icon", name: (_a = props.icon) !== null && _a !== void 0 ? _a : "cloud" }),
|
|
112
116
|
typeof props.label === "string" ? react_1.default.createElement("span", null, props.label) : props.label,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { FileResponse, UploadOptions } from "@uxf/ui/types/file-response";
|
|
2
1
|
import React from "react";
|
|
3
2
|
declare const _default: {
|
|
4
3
|
title: string;
|
|
@@ -7,6 +6,5 @@ declare const _default: {
|
|
|
7
6
|
};
|
|
8
7
|
};
|
|
9
8
|
export default _default;
|
|
10
|
-
export declare function uploadFile(file: File, uploadOptions?: UploadOptions): Promise<FileResponse>;
|
|
11
9
|
export declare function Default(): JSX.Element;
|
|
12
10
|
export declare function ComponentStructure(): JSX.Element;
|
|
@@ -26,63 +26,23 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
26
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.ComponentStructure = exports.Default =
|
|
29
|
+
exports.ComponentStructure = exports.Default = void 0;
|
|
30
30
|
const component_structure_analyzer_1 = __importDefault(require("@uxf/ui/utils/component-structure-analyzer"));
|
|
31
|
+
const uploadFIle_mock_1 = require("@uxf/ui/utils/mocks/uploadFIle.mock");
|
|
31
32
|
const react_1 = __importStar(require("react"));
|
|
32
33
|
const index_1 = require("./index");
|
|
33
34
|
exports.default = {
|
|
34
35
|
title: "UI/Dropzone",
|
|
35
36
|
component: index_1.Dropzone,
|
|
36
37
|
};
|
|
37
|
-
function getRandomUuid() {
|
|
38
|
-
return "00000000-0000-0000-0000-000000000000"
|
|
39
|
-
.split("-")
|
|
40
|
-
.map((el) => Array(el.length)
|
|
41
|
-
.fill(0)
|
|
42
|
-
.map(() => Math.round(Math.random() * 9).toString())
|
|
43
|
-
.join(""))
|
|
44
|
-
.join("-");
|
|
45
|
-
}
|
|
46
|
-
function uploadFile(file, uploadOptions) {
|
|
47
|
-
// axios.put("/api/upload", file, { signal: uploadOptions?.abortController?.signal });
|
|
48
|
-
return new Promise((resolve) => {
|
|
49
|
-
const time = file.size / 10;
|
|
50
|
-
const interval = time / 10;
|
|
51
|
-
let loaded = 0;
|
|
52
|
-
const timeoutTimer = window.setTimeout(() => {
|
|
53
|
-
const nameParts = file.name.split(".");
|
|
54
|
-
resolve({
|
|
55
|
-
id: Math.round(Math.random() * 100000000),
|
|
56
|
-
uuid: getRandomUuid(),
|
|
57
|
-
name: nameParts.slice(0, -1).join("."),
|
|
58
|
-
extension: nameParts[nameParts.length - 1],
|
|
59
|
-
});
|
|
60
|
-
}, time);
|
|
61
|
-
const intervalTimer = window.setInterval(() => {
|
|
62
|
-
var _a, _b;
|
|
63
|
-
if ((_a = uploadOptions === null || uploadOptions === void 0 ? void 0 : uploadOptions.abortController) === null || _a === void 0 ? void 0 : _a.signal.aborted) {
|
|
64
|
-
clearInterval(intervalTimer);
|
|
65
|
-
clearTimeout(timeoutTimer);
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
loaded += (file.size / time) * interval;
|
|
69
|
-
(_b = uploadOptions === null || uploadOptions === void 0 ? void 0 : uploadOptions.onUploadProgress) === null || _b === void 0 ? void 0 : _b.call(uploadOptions, {
|
|
70
|
-
lengthComputable: true,
|
|
71
|
-
loaded,
|
|
72
|
-
total: file.size,
|
|
73
|
-
});
|
|
74
|
-
}, interval);
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
exports.uploadFile = uploadFile;
|
|
78
38
|
function Default() {
|
|
79
39
|
const [files, setFiles] = (0, react_1.useState)([]);
|
|
80
40
|
const storyDropzone = (react_1.default.createElement("div", { className: "space-y-2" },
|
|
81
|
-
react_1.default.createElement(index_1.Dropzone, { helperText: "Disabled drag 'n' drop", label: "Use drag and drop or click to upload", noDrag: true, onChange: setFiles, onUploadFile: uploadFile, value: files }),
|
|
82
|
-
react_1.default.createElement(index_1.Dropzone, { helperText: "Disabled onClick upload", label: react_1.default.createElement("span", { className: "rounded-lg bg-primary-600 px-4 py-2 font-bold text-white" }, "JSX label"), noClick: true, onChange: setFiles, onUploadFile: uploadFile, value: files }),
|
|
83
|
-
react_1.default.createElement(index_1.Dropzone, { accept: { "image/*": [] }, label: "Only images upload", onChange: setFiles, onUploadFile: uploadFile, value: files }),
|
|
84
|
-
react_1.default.createElement(index_1.Dropzone, { label: "Single file upload", maxFilesCount: 1, onChange: setFiles, onUploadFile: uploadFile, value: files }),
|
|
85
|
-
react_1.default.createElement(index_1.Dropzone, { isDisabled: true, label: "Disabled dropzone", onChange: setFiles, onUploadFile: uploadFile, value: files }),
|
|
41
|
+
react_1.default.createElement(index_1.Dropzone, { helperText: "Disabled drag 'n' drop", label: "Use drag and drop or click to upload", noDrag: true, onChange: setFiles, onUploadFile: uploadFIle_mock_1.uploadFile, value: files }),
|
|
42
|
+
react_1.default.createElement(index_1.Dropzone, { helperText: "Disabled onClick upload", label: react_1.default.createElement("span", { className: "rounded-lg bg-primary-600 px-4 py-2 font-bold text-white" }, "JSX label"), noClick: true, onChange: setFiles, onUploadFile: uploadFIle_mock_1.uploadFile, value: files }),
|
|
43
|
+
react_1.default.createElement(index_1.Dropzone, { accept: { "image/*": [] }, label: "Only images upload", onChange: setFiles, onUploadFile: uploadFIle_mock_1.uploadFile, value: files }),
|
|
44
|
+
react_1.default.createElement(index_1.Dropzone, { label: "Single file upload", maxFilesCount: 1, onChange: setFiles, onUploadFile: uploadFIle_mock_1.uploadFile, value: files }),
|
|
45
|
+
react_1.default.createElement(index_1.Dropzone, { isDisabled: true, label: "Disabled dropzone", onChange: setFiles, onUploadFile: uploadFIle_mock_1.uploadFile, value: files }),
|
|
86
46
|
react_1.default.createElement(index_1.Dropzone.List, { errorText: "Chyba p\u0159i nahr\u00E1v\u00E1n\u00ED souboru", onAbortWarning: "Opravdu chcete p\u0159eru\u0161it nahr\u00E1v\u00E1n\u00ED?", onChange: setFiles, onRemoveWarning: "Opravdu chcete soubor smazat?", value: files }),
|
|
87
47
|
react_1.default.createElement(index_1.Dropzone.List, { onChange: setFiles, value: files, renderItem: (file) => (react_1.default.createElement("li", { key: file.id },
|
|
88
48
|
react_1.default.createElement("pre", null, JSON.stringify(file, null, 4)))) })));
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { FileResponse, FormControlProps } from "@uxf/ui/types";
|
|
2
2
|
import React from "react";
|
|
3
|
-
export interface BaseFileInputProps extends FormControlProps<
|
|
3
|
+
export interface BaseFileInputProps extends FormControlProps<FileResponse | null> {
|
|
4
4
|
"aria-describedby"?: string;
|
|
5
5
|
accept?: string;
|
|
6
6
|
className?: string;
|
|
7
7
|
form?: string;
|
|
8
8
|
id?: string;
|
|
9
9
|
onUploadError?: (err: unknown) => void;
|
|
10
|
-
|
|
10
|
+
onUploadFile: (file: File) => Promise<FileResponse>;
|
|
11
11
|
}
|
|
12
12
|
export declare const BaseFileInput: React.ForwardRefExoticComponent<BaseFileInputProps & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -1,50 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
24
4
|
};
|
|
25
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
6
|
exports.BaseFileInput = void 0;
|
|
27
|
-
const cx_1 = require("@uxf/core/utils/cx");
|
|
28
7
|
const forwardRef_1 = require("@uxf/core/utils/forwardRef");
|
|
29
|
-
const react_1 =
|
|
8
|
+
const react_1 = __importDefault(require("react"));
|
|
30
9
|
exports.BaseFileInput = (0, forwardRef_1.forwardRef)("BaseFileInput", (props, ref) => {
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const files = e.target.files;
|
|
35
|
-
if (files && files.length > 0) {
|
|
36
|
-
setUploading(true);
|
|
37
|
-
try {
|
|
38
|
-
const response = await props.onUploadFiles(Array.from(files).slice(0, 1));
|
|
39
|
-
await ((_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, response[0].name));
|
|
40
|
-
}
|
|
41
|
-
catch (err) {
|
|
42
|
-
(_b = props.onUploadError) === null || _b === void 0 ? void 0 : _b.call(props, err);
|
|
43
|
-
}
|
|
44
|
-
finally {
|
|
45
|
-
setUploading(false);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
10
|
+
const onChange = (e) => {
|
|
11
|
+
var _a;
|
|
12
|
+
(_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, null, e);
|
|
48
13
|
};
|
|
49
|
-
return (react_1.default.createElement("input", { accept: props.accept, "aria-describedby": props["aria-describedby"], "aria-invalid": props.isInvalid, className:
|
|
14
|
+
return (react_1.default.createElement("input", { accept: props.accept, "aria-describedby": props["aria-describedby"], "aria-invalid": props.isInvalid, className: props.className, disabled: props.isDisabled, form: props.form, id: props.id, name: props.name, onBlur: props.onBlur, onChange: onChange, onFocus: props.onFocus, readOnly: props.isReadOnly, ref: ref, required: props.isRequired, tabIndex: props.isDisabled ? -1 : undefined, type: "file" }));
|
|
50
15
|
});
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { InputGroupSizes, InputGroupVariants } from "@uxf/ui/input/theme";
|
|
1
2
|
import React, { ReactNode } from "react";
|
|
2
|
-
import { InputGroupSizes, InputGroupVariants } from "../input/theme";
|
|
3
3
|
import { BaseFileInputProps } from "./file-input-base";
|
|
4
4
|
export interface FileInputProps extends BaseFileInputProps {
|
|
5
5
|
helperText?: ReactNode;
|
|
6
6
|
label?: ReactNode;
|
|
7
|
+
placeholder?: string;
|
|
7
8
|
size?: keyof InputGroupSizes;
|
|
8
9
|
variant?: keyof InputGroupVariants;
|
|
9
10
|
}
|
package/file-input/file-input.js
CHANGED
|
@@ -28,16 +28,43 @@ const classes_1 = require("@uxf/core/constants/classes");
|
|
|
28
28
|
const useInputFocus_1 = require("@uxf/core/hooks/useInputFocus");
|
|
29
29
|
const cx_1 = require("@uxf/core/utils/cx");
|
|
30
30
|
const forwardRef_1 = require("@uxf/core/utils/forwardRef");
|
|
31
|
+
const form_control_1 = require("@uxf/ui/form-control");
|
|
32
|
+
const loader_1 = require("@uxf/ui/loader/loader");
|
|
31
33
|
const react_1 = __importStar(require("react"));
|
|
32
|
-
const form_control_1 = require("../form-control");
|
|
33
34
|
const file_input_base_1 = require("./file-input-base");
|
|
34
35
|
exports.FileInput = (0, forwardRef_1.forwardRef)("FileInput", (props, ref) => {
|
|
35
36
|
var _a, _b;
|
|
37
|
+
const [isUploading, setIsUploading] = (0, react_1.useState)(false);
|
|
36
38
|
const generatedId = (0, react_1.useId)();
|
|
37
39
|
const id = props.id || generatedId;
|
|
38
40
|
const innerRef = (0, react_1.useRef)(null);
|
|
39
41
|
const input = (0, useInputFocus_1.useInputFocus)(innerRef, props.onBlur, props.onFocus);
|
|
40
42
|
const errorId = props.isInvalid && props.id ? `${props.id}--errormessage` : undefined;
|
|
43
|
+
const onChange = async (_, e) => {
|
|
44
|
+
var _a, _b, _c;
|
|
45
|
+
const file = (_a = e === null || e === void 0 ? void 0 : e.target.files) === null || _a === void 0 ? void 0 : _a[0];
|
|
46
|
+
if (!file) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
setIsUploading(true);
|
|
50
|
+
try {
|
|
51
|
+
const response = await props.onUploadFile(file);
|
|
52
|
+
await ((_b = props.onChange) === null || _b === void 0 ? void 0 : _b.call(props, response));
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
(_c = props.onUploadError) === null || _c === void 0 ? void 0 : _c.call(props, err);
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
setIsUploading(false);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
41
61
|
return (react_1.default.createElement(form_control_1.FormControl, { className: (0, cx_1.cx)(input.focused && classes_1.CLASSES.IS_FOCUSED, (props.isDisabled || props.isReadOnly) && classes_1.CLASSES.IS_DISABLED, props.isInvalid && classes_1.CLASSES.IS_INVALID), errorId: errorId, form: props.form, helperText: props.helperText, inputId: id, isRequired: props.isRequired, label: props.label },
|
|
42
|
-
react_1.default.createElement(
|
|
62
|
+
react_1.default.createElement(react_1.default.Fragment, null,
|
|
63
|
+
react_1.default.createElement("label", { className: (0, cx_1.cx)("uxf-input", "uxf-file-input__label", input.focused && classes_1.CLASSES.IS_FOCUSED, (props.isDisabled || props.isReadOnly) && classes_1.CLASSES.IS_DISABLED, props.isInvalid && classes_1.CLASSES.IS_INVALID, isUploading && classes_1.CLASSES.IS_LOADING, isUploading && "uxf-file-input__label--has-right-addon", `uxf-input--size-${(_a = props.size) !== null && _a !== void 0 ? _a : "default"}`, `uxf-input--variant-${(_b = props.variant) !== null && _b !== void 0 ? _b : "default"}`), htmlFor: id },
|
|
64
|
+
react_1.default.createElement("div", { className: "uxf-input__left-addon uxf-file-input__label__button" }, !isUploading ? ("Vyberte soubor") : (react_1.default.createElement(loader_1.Loader, { className: "uxf-file-input__label__loader", size: "sm" }))),
|
|
65
|
+
react_1.default.createElement("div", { className: "uxf-file-input__label__wrapper" },
|
|
66
|
+
react_1.default.createElement("span", { className: "uxf-file-input__label__wrapper__file-name" }, props.value
|
|
67
|
+
? `${props.value.name}.${props.value.extension}`
|
|
68
|
+
: props.placeholder || "No file has been selected yet"))),
|
|
69
|
+
react_1.default.createElement(file_input_base_1.BaseFileInput, { accept: props.accept, "aria-describedby": errorId, "aria-invalid": props.isInvalid, className: "uxf-file-input__input", form: props.form, id: id, isDisabled: props.isDisabled, isInvalid: props.isInvalid, isReadOnly: props.isReadOnly, isRequired: props.isRequired, name: props.name, onBlur: input.onBlur, onChange: onChange, onFocus: input.onFocus, onUploadError: props.onUploadError, onUploadFile: props.onUploadFile, ref: ref }))));
|
|
43
70
|
});
|
|
@@ -1,37 +1,46 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
4
24
|
};
|
|
5
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
26
|
exports.Default = void 0;
|
|
7
|
-
const
|
|
27
|
+
const uploadFIle_mock_1 = require("@uxf/ui/utils/mocks/uploadFIle.mock");
|
|
28
|
+
const react_1 = __importStar(require("react"));
|
|
8
29
|
const index_1 = require("./index");
|
|
9
30
|
exports.default = {
|
|
10
31
|
title: "UI/FileInput",
|
|
11
32
|
component: index_1.FileInput,
|
|
12
33
|
};
|
|
13
34
|
function Default() {
|
|
14
|
-
const
|
|
15
|
-
return new Promise(() => {
|
|
16
|
-
// eslint-disable-next-line no-console
|
|
17
|
-
console.log("Changed:", value);
|
|
18
|
-
});
|
|
19
|
-
};
|
|
35
|
+
const [value, setValue] = (0, react_1.useState)(null);
|
|
20
36
|
const handleUploadError = (err) => {
|
|
21
37
|
// eslint-disable-next-line no-console
|
|
22
38
|
console.log("Upload error", err);
|
|
23
39
|
};
|
|
24
|
-
const handleUpload = (files, namespace) => {
|
|
25
|
-
return new Promise((resolve) => {
|
|
26
|
-
// eslint-disable-next-line no-console
|
|
27
|
-
console.log("Upload handler", files, namespace);
|
|
28
|
-
resolve([]);
|
|
29
|
-
});
|
|
30
|
-
};
|
|
31
40
|
const storyFileInputs = (react_1.default.createElement("div", { className: "space-y-2" },
|
|
32
|
-
react_1.default.createElement(index_1.FileInput, { label: "Default file input", onChange:
|
|
33
|
-
react_1.default.createElement(index_1.FileInput, { helperText: "Error file input", id: "error-file-input", isInvalid: true, label: "Error file input", onChange:
|
|
34
|
-
react_1.default.createElement(index_1.FileInput, { helperText: "Readonly/disabled file input", label: "Readonly/disabled file input", isReadOnly: true, isDisabled: true, onChange:
|
|
41
|
+
react_1.default.createElement(index_1.FileInput, { label: "Default file input", onChange: setValue, onUploadError: handleUploadError, onUploadFile: uploadFIle_mock_1.uploadFile, value: value }),
|
|
42
|
+
react_1.default.createElement(index_1.FileInput, { helperText: "Error file input", id: "error-file-input", isInvalid: true, label: "Error file input", onChange: setValue, onUploadError: handleUploadError, onUploadFile: uploadFIle_mock_1.uploadFile, value: value }),
|
|
43
|
+
react_1.default.createElement(index_1.FileInput, { helperText: "Readonly/disabled file input", label: "Readonly/disabled file input", isReadOnly: true, isDisabled: true, onChange: setValue, onUploadError: handleUploadError, onUploadFile: uploadFIle_mock_1.uploadFile, value: value })));
|
|
35
44
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
36
45
|
react_1.default.createElement("div", { className: "light space-y-2 p-20" }, storyFileInputs),
|
|
37
46
|
react_1.default.createElement("div", { className: "dark space-y-2 bg-gray-900 p-20" }, storyFileInputs)));
|
|
@@ -39,13 +39,13 @@ const icon_1 = require("../icon");
|
|
|
39
39
|
const label_1 = require("../label");
|
|
40
40
|
const use_async_loading_1 = require("../hooks/use-async-loading");
|
|
41
41
|
exports.MultiCombobox = (0, forwardRef_1.forwardRef)("MultiCombobox", (props, ref) => {
|
|
42
|
-
var _a, _b, _c, _d;
|
|
42
|
+
var _a, _b, _c, _d, _e;
|
|
43
43
|
const generatedId = (0, react_2.useId)();
|
|
44
44
|
const id = (_a = props.id) !== null && _a !== void 0 ? _a : generatedId;
|
|
45
45
|
const isAsync = !!props.loadOptions;
|
|
46
46
|
const [query, setQuery] = (0, react_2.useState)("");
|
|
47
47
|
const options = (0, use_async_loading_1.useAsyncLoading)(query, (_b = props.options) !== null && _b !== void 0 ? _b : [], props.loadOptions);
|
|
48
|
-
const
|
|
48
|
+
const selectedOptions = (_c = props.value) !== null && _c !== void 0 ? _c : [];
|
|
49
49
|
const filteredData = isAsync
|
|
50
50
|
? options
|
|
51
51
|
: options.filter((item) => {
|
|
@@ -56,12 +56,11 @@ exports.MultiCombobox = (0, forwardRef_1.forwardRef)("MultiCombobox", (props, re
|
|
|
56
56
|
const innerRef = (0, react_2.useRef)(null);
|
|
57
57
|
const errorId = props.isInvalid ? `${id}--error-message` : undefined;
|
|
58
58
|
const input = (0, useInputFocus_1.useInputFocus)(innerRef, props.onBlur, props.onFocus);
|
|
59
|
-
const dropdown = (0, use_dropdown_1.useDropdown)((
|
|
59
|
+
const dropdown = (0, use_dropdown_1.useDropdown)((_d = props.dropdownPlacement) !== null && _d !== void 0 ? _d : "bottom", true);
|
|
60
60
|
const stableRef = (0, react_2.useMemo)(() => (0, composeRefs_1.composeRefs)(innerRef, ref, dropdown.reference), [ref, dropdown.reference]);
|
|
61
|
-
const iconName = (
|
|
61
|
+
const iconName = (_e = props.iconName) !== null && _e !== void 0 ? _e : "chevronDown";
|
|
62
62
|
const handleRemove = (valueId) => () => {
|
|
63
63
|
var _a, _b, _c;
|
|
64
|
-
setSelectedOptions((prev) => prev.filter((v) => v.id !== valueId));
|
|
65
64
|
(_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, (_c = (_b = props.value) === null || _b === void 0 ? void 0 : _b.filter((v) => v.id !== valueId)) !== null && _c !== void 0 ? _c : []);
|
|
66
65
|
};
|
|
67
66
|
const handleCheckboxChange = (valueId) => (checked) => {
|
|
@@ -84,11 +83,10 @@ exports.MultiCombobox = (0, forwardRef_1.forwardRef)("MultiCombobox", (props, re
|
|
|
84
83
|
const handleInputChange = (event) => setQuery(event.target.value);
|
|
85
84
|
const handleComboboxValueChange = (v) => {
|
|
86
85
|
var _a;
|
|
87
|
-
setSelectedOptions(v);
|
|
88
86
|
(_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, v.map((option) => option));
|
|
89
87
|
setQuery("");
|
|
90
88
|
};
|
|
91
|
-
return (react_2.default.createElement(react_1.Combobox, { as: "div", className: (0, cx_1.cx)("uxf-combobox", props.isInvalid && classes_1.CLASSES.IS_INVALID, props.isRequired && classes_1.CLASSES.IS_REQUIRED, props.isReadOnly && classes_1.CLASSES.IS_READONLY, props.isDisabled && classes_1.CLASSES.IS_DISABLED, props.className), disabled: props.isDisabled || props.isReadOnly, multiple: true, onChange: handleComboboxValueChange, value: selectedOptions }, (renderProps) => (react_2.default.createElement(react_2.default.Fragment, null,
|
|
89
|
+
return (react_2.default.createElement(react_1.Combobox, { as: "div", by: "id", className: (0, cx_1.cx)("uxf-combobox", props.isInvalid && classes_1.CLASSES.IS_INVALID, props.isRequired && classes_1.CLASSES.IS_REQUIRED, props.isReadOnly && classes_1.CLASSES.IS_READONLY, props.isDisabled && classes_1.CLASSES.IS_DISABLED, props.className), disabled: props.isDisabled || props.isReadOnly, multiple: true, onChange: handleComboboxValueChange, value: selectedOptions }, (renderProps) => (react_2.default.createElement(react_2.default.Fragment, null,
|
|
92
90
|
react_2.default.createElement(react_1.Combobox.Label, { as: label_1.Label, isHidden: props.hiddenLabel, onClick: props.isDisabled || props.isReadOnly ? undefined : input.focus }, props.label),
|
|
93
91
|
react_2.default.createElement(react_1.Combobox.Button, { as: "div", className: (0, cx_1.cx)("uxf-multi-combobox__button", (renderProps.open || input.focused) && classes_1.CLASSES.IS_FOCUSED, renderProps.disabled && classes_1.CLASSES.IS_DISABLED, props.isReadOnly && classes_1.CLASSES.IS_READONLY, props.isInvalid && classes_1.CLASSES.IS_INVALID, dropdown.placement === "bottom" && "is-open--bottom", dropdown.placement === "top" && "is-open--top", renderProps.open && classes_1.CLASSES.IS_OPEN), onBlur: input.onBlur, onFocus: input.onFocus, tabIndex: props.isDisabled || props.isReadOnly ? undefined : 0, ref: stableRef, "aria-invalid": props.isInvalid, "aria-describedby": errorId },
|
|
94
92
|
selectedOptions.map((item) => (react_2.default.createElement(chip_1.Chip, { className: "mr-2 mt-2", color: item.color, key: item.id, onClose: handleRemove(item.id), size: "large" }, item.label))),
|
package/package.json
CHANGED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.uploadFile = void 0;
|
|
4
|
+
function getRandomUuid() {
|
|
5
|
+
return "00000000-0000-0000-0000-000000000000"
|
|
6
|
+
.split("-")
|
|
7
|
+
.map((el) => Array(el.length)
|
|
8
|
+
.fill(0)
|
|
9
|
+
.map(() => Math.round(Math.random() * 9).toString())
|
|
10
|
+
.join(""))
|
|
11
|
+
.join("-");
|
|
12
|
+
}
|
|
13
|
+
function uploadFile(file, uploadOptions) {
|
|
14
|
+
// axios.put("/api/upload", file, { signal: uploadOptions?.abortController?.signal, onUploadProgress: uploadOptions?.onUploadProgress });
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
const time = file.size / 10;
|
|
17
|
+
const interval = time / 10;
|
|
18
|
+
let loaded = 0;
|
|
19
|
+
const timeoutTimer = window.setTimeout(() => {
|
|
20
|
+
const nameParts = file.name.split(".");
|
|
21
|
+
resolve({
|
|
22
|
+
id: Math.round(Math.random() * 100000000),
|
|
23
|
+
uuid: getRandomUuid(),
|
|
24
|
+
name: nameParts.slice(0, -1).join("."),
|
|
25
|
+
extension: nameParts[nameParts.length - 1],
|
|
26
|
+
});
|
|
27
|
+
}, time);
|
|
28
|
+
const intervalTimer = window.setInterval(() => {
|
|
29
|
+
var _a, _b;
|
|
30
|
+
if ((_a = uploadOptions === null || uploadOptions === void 0 ? void 0 : uploadOptions.abortController) === null || _a === void 0 ? void 0 : _a.signal.aborted) {
|
|
31
|
+
clearInterval(intervalTimer);
|
|
32
|
+
clearTimeout(timeoutTimer);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
loaded += (file.size / time) * interval;
|
|
36
|
+
(_b = uploadOptions === null || uploadOptions === void 0 ? void 0 : uploadOptions.onUploadProgress) === null || _b === void 0 ? void 0 : _b.call(uploadOptions, {
|
|
37
|
+
lengthComputable: true,
|
|
38
|
+
loaded,
|
|
39
|
+
total: file.size,
|
|
40
|
+
});
|
|
41
|
+
}, interval);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
exports.uploadFile = uploadFile;
|