@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.
@@ -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, ref: ref, onUploadFiles: props.onUploadFiles }),
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, onUploadFiles: handleUpload }),
33
- react_1.default.createElement(index_1.AvatarFileInput, { isDisabled: true, onChange: handleChange, onUploadError: handleUploadError, onUploadFiles: handleUpload }),
34
- react_1.default.createElement(index_1.AvatarFileInput, { id: "afi", isInvalid: true, label: "Vyberte Avatar", onChange: handleChange, onUploadError: handleUploadError, onUploadFiles: handleUpload })));
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
@@ -31,7 +31,7 @@
31
31
  }
32
32
 
33
33
  &__item {
34
- @apply overflow-scroll border px-4 py-3 shadow-sm sm:rounded-md sm:px-6 flex w-full
34
+ @apply overflow-auto border px-4 py-3 shadow-sm sm:rounded-md sm:px-6 flex w-full
35
35
  items-center justify-between space-x-6;
36
36
 
37
37
  :root .light & {
@@ -1,94 +1,63 @@
1
1
  .uxf-file-input {
2
2
  &__input {
3
- @apply border uxf-input pr-2;
3
+ @apply hidden;
4
+ }
4
5
 
5
- &:hover {
6
- @apply cursor-pointer;
7
- }
6
+ &__label {
7
+ @apply cursor-pointer flex overflow-auto;
8
8
 
9
- :root .light & {
10
- @apply border-gray-200;
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
- &::file-selector-button {
18
- @apply border-none outline outline-1 h-full px-4 mr-3;
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 bg-gray-200;
17
+ @apply border-error-500 text-error-500;
33
18
  }
34
19
 
35
20
  :root .dark & {
36
- @apply bg-gray-700;
21
+ @apply border-error-500 text-error-500;
37
22
  }
38
23
  }
39
24
  }
40
25
 
41
- &.is-disabled {
42
- @apply cursor-not-allowed;
26
+ &__button {
27
+ @apply px-3;
43
28
 
44
29
  :root .light & {
45
- @apply text-gray-400;
30
+ @apply border-gray-200 bg-gray-100;
46
31
  }
47
32
 
48
33
  :root .dark & {
49
- @apply text-gray-400;
34
+ @apply border-gray-700 bg-gray-800;
50
35
  }
51
36
 
52
- &::file-selector-button:hover {
53
- @apply cursor-not-allowed;
54
-
37
+ &:hover {
55
38
  :root .light & {
56
- @apply bg-inherit;
39
+ @apply bg-gray-200;
57
40
  }
58
41
 
59
42
  :root .dark & {
60
- @apply bg-inherit;
43
+ @apply bg-gray-700;
61
44
  }
62
45
  }
63
46
  }
64
47
 
65
- &.is-invalid {
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-error-500 text-error-500;
52
+ @apply border-gray-200;
68
53
  }
69
54
 
70
55
  :root .dark & {
71
- @apply border-error-500 text-error-500;
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
- &.is-focused {
86
- :root .light & {
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 = exports.uploadFile = void 0;
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<string> {
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
- onUploadFiles: (files: File[]) => Promise<FileResponse[]>;
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 __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;
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 = __importStar(require("react"));
8
+ const react_1 = __importDefault(require("react"));
30
9
  exports.BaseFileInput = (0, forwardRef_1.forwardRef)("BaseFileInput", (props, ref) => {
31
- const [, setUploading] = (0, react_1.useState)(false);
32
- const onChange = async (e) => {
33
- var _a, _b;
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: (0, cx_1.cx)("uxf-input__element", 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" }));
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
  }
@@ -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(file_input_base_1.BaseFileInput, { accept: props.accept, "aria-describedby": errorId, "aria-invalid": props.isInvalid, className: (0, cx_1.cx)("uxf-file-input__input", input.focused && classes_1.CLASSES.IS_FOCUSED, (props.isDisabled || props.isReadOnly) && classes_1.CLASSES.IS_DISABLED, props.isInvalid && classes_1.CLASSES.IS_INVALID, `uxf-input--size-${(_a = props.size) !== null && _a !== void 0 ? _a : "default"}`, `uxf-input--variant-${(_b = props.variant) !== null && _b !== void 0 ? _b : "default"}`), 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, onUploadFiles: props.onUploadFiles, ref: ref })));
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 __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
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 react_1 = __importDefault(require("react"));
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 handleChange = (value) => {
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: handleChange, onUploadError: handleUploadError, onUploadFiles: handleUpload }),
33
- react_1.default.createElement(index_1.FileInput, { helperText: "Error file input", id: "error-file-input", isInvalid: true, label: "Error file input", onChange: handleChange, onUploadError: handleUploadError, onUploadFiles: handleUpload }),
34
- react_1.default.createElement(index_1.FileInput, { helperText: "Readonly/disabled file input", label: "Readonly/disabled file input", isReadOnly: true, isDisabled: true, onChange: handleChange, onUploadError: handleUploadError, onUploadFiles: handleUpload })));
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 [selectedOptions, setSelectedOptions] = (0, react_2.useState)(() => options.filter((option) => { var _a; return (_a = props.value) === null || _a === void 0 ? void 0 : _a.some((v) => v.id === option.id); }));
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)((_c = props.dropdownPlacement) !== null && _c !== void 0 ? _c : "bottom", true);
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 = (_d = props.iconName) !== null && _d !== void 0 ? _d : "chevronDown";
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uxf/ui",
3
- "version": "1.0.0-beta.103",
3
+ "version": "1.0.0-beta.105",
4
4
  "description": "",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -0,0 +1,2 @@
1
+ import { FileResponse, UploadOptions } from "@uxf/ui/types";
2
+ export declare function uploadFile(file: File, uploadOptions?: UploadOptions): Promise<FileResponse>;
@@ -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;