@uxf/ui 11.34.1 → 11.35.0

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.
@@ -1,7 +1,7 @@
1
1
  import { UseAnchorProps } from "@uxf/core-react/hooks/use-anchor-props";
2
2
  import { ButtonColors, ButtonSizes, ButtonVariants } from "@uxf/ui/button/theme";
3
3
  import React, { AnchorHTMLAttributes } from "react";
4
- import { NextLink } from "./next-link";
4
+ import { NextLink } from "../utils/next-link";
5
5
  export type ButtonVariant = keyof ButtonVariants;
6
6
  export type ButtonSize = keyof ButtonSizes;
7
7
  export type ButtonColor = keyof ButtonColors;
@@ -36,12 +36,13 @@ const use_dropdown_1 = require("../hooks/use-dropdown");
36
36
  const icon_1 = require("../icon");
37
37
  const MenuButton = (0, react_3.forwardRef)((props, ref) => {
38
38
  // eslint-disable-next-line react/destructuring-assignment,@typescript-eslint/no-unused-vars
39
- const { variant, color, isIconButton, isFullWidth, size, icon, label, className, ...restProps } = props;
39
+ const { as = "a", variant, color, isIconButton, isFullWidth, size, icon, label, className, ...restProps } = props;
40
+ const Component = as;
40
41
  const anchorProps = (0, use_anchor_props_1.useAnchorProps)({
41
42
  ...restProps,
42
43
  className: (0, cx_1.cx)("uxf-button-list__menu-button", `uxf-button-list__menu-button--color-${color !== null && color !== void 0 ? color : "default"}`, `uxf-button-list__menu-button--variant-${variant !== null && variant !== void 0 ? variant : "default"}`, className),
43
44
  });
44
- return (react_3.default.createElement("a", { ref: ref, ...anchorProps },
45
+ return (react_3.default.createElement(Component, { ref: ref, ...anchorProps },
45
46
  icon && react_3.default.createElement(icon_1.Icon, { className: "uxf-button-list__menu-button-icon", name: icon }),
46
47
  label && react_3.default.createElement("span", { className: "uxf-button-list__menu-button-label" }, label)));
47
48
  });
package/chip/chip.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import { UseAnchorProps } from "@uxf/core-react/hooks/use-anchor-props";
2
2
  import { ChipColor, ChipSize, ChipVariant } from "@uxf/ui/chip/theme";
3
3
  import React, { AnchorHTMLAttributes, MouseEventHandler } from "react";
4
+ import { NextLink } from "../utils/next-link";
4
5
  export interface ChipProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "color" | "type">, UseAnchorProps {
6
+ as?: NextLink | "a";
5
7
  color?: ChipColor;
6
8
  onClose?: MouseEventHandler;
7
9
  size?: ChipSize;
package/chip/chip.js CHANGED
@@ -42,14 +42,15 @@ const CloseButton = (props) => {
42
42
  };
43
43
  exports.Chip = (0, react_1.forwardRef)((props, ref) => {
44
44
  var _a, _b, _c;
45
- const { children, className, onClose, suppressFocus, tabIndex, ...restProps } = props;
45
+ const { as = "a", children, className, onClose, suppressFocus, tabIndex, ...restProps } = props;
46
46
  const chipClassName = (0, cx_1.cx)("uxf-chip", `uxf-chip--color-${(_a = props.color) !== null && _a !== void 0 ? _a : "default"}`, `uxf-chip--size-${(_b = props.size) !== null && _b !== void 0 ? _b : "default"}`, `uxf-chip--variant-${(_c = props.variant) !== null && _c !== void 0 ? _c : "default"}`, (0, is_not_nil_1.isNotNil)(onClose) && "has-button", className);
47
+ const Component = as;
47
48
  const anchorProps = (0, use_anchor_props_1.useAnchorProps)({
48
49
  className: (0, cx_1.cx)(chipClassName),
49
50
  tabIndex: suppressFocus ? -1 : tabIndex,
50
51
  ...restProps,
51
52
  });
52
- return (react_1.default.createElement("a", { ref: ref, ...anchorProps },
53
+ return (react_1.default.createElement(Component, { ref: ref, ...anchorProps },
53
54
  typeof children === "string" ? react_1.default.createElement("span", { className: "uxf-chip__text" }, children) : children,
54
55
  (0, is_not_nil_1.isNotNil)(onClose) && react_1.default.createElement(CloseButton, { onClose: onClose })));
55
56
  });
@@ -16,11 +16,11 @@
16
16
  }
17
17
  }
18
18
 
19
- &.is-first {
19
+ &:first-child {
20
20
  @apply rounded-l-md;
21
21
  }
22
22
 
23
- &.is-last {
23
+ &:last-child {
24
24
  @apply rounded-r-md;
25
25
  }
26
26
 
@@ -1,6 +1,8 @@
1
1
  import { UseAnchorProps } from "@uxf/core-react/hooks/use-anchor-props";
2
2
  import React, { AnchorHTMLAttributes, HTMLAttributes } from "react";
3
+ import { NextLink } from "../utils/next-link";
3
4
  export interface DropdownItemProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "type">, UseAnchorProps {
5
+ as?: NextLink | "a";
4
6
  }
5
7
  type ItemsProps = HTMLAttributes<HTMLDivElement>;
6
8
  export type DropdownItemsProps = HTMLDivElement;
@@ -29,13 +29,14 @@ const cx_1 = require("@uxf/core/utils/cx");
29
29
  const react_1 = __importStar(require("react"));
30
30
  const Item = (0, react_1.forwardRef)((props, ref) => {
31
31
  // eslint-disable-next-line react/destructuring-assignment
32
- const { children, className, ...restProps } = props;
32
+ const { as = "a", children, className, ...restProps } = props;
33
+ const Component = as;
33
34
  const anchorProps = (0, use_anchor_props_1.useAnchorProps)({
34
35
  className: `uxf-dropdown__item ${className || ""}`,
35
36
  role: "menuitem",
36
37
  ...restProps,
37
38
  });
38
- return (react_1.default.createElement("a", { ref: ref, ...anchorProps }, children));
39
+ return (react_1.default.createElement(Component, { ref: ref, ...anchorProps }, children));
39
40
  });
40
41
  Item.displayName = "UxfUiDropdownItem";
41
42
  const Items = (0, react_1.forwardRef)((props, ref) => {
@@ -1,8 +1,106 @@
1
1
  # Dropzone
2
2
 
3
+ ---
4
+
3
5
  ## CSS dependencies
4
6
 
5
7
  ```css
6
8
  @import url("@uxf/ui/icon/icon.css");
7
9
  @import url("@uxf/ui/dropzone/dropzone.css");
8
- ```
10
+ ```
11
+
12
+ ---
13
+
14
+ #### The Dropzone component is split into two parts:
15
+
16
+ 1. `<Dropzone />` (**DropzoneInput**): This handles file input via drag-and-drop or file selection. It manages file upload and validation.
17
+ 2. `<Dropzone.List />`: Displays the uploaded files and allows managing them (e.g., removing files) and provides the upload status of files. It works with the same `value` and `onChange` properties as the main `Dropzone` component to ensure synchronization between the uploaded files and their display.
18
+
19
+ ### **getDropzoneState**
20
+ ---
21
+ This function returns the current status of the uploaded files. It can be used to determine whether the Dropzone component should be disabled or not.
22
+
23
+ The status can be one of the following: `"ERROR" | "OK" | "UPLOADING"`
24
+
25
+ ```tsx
26
+ const { status } = getDropzoneState(files);
27
+ ```
28
+
29
+ ## Component Overview
30
+ ---
31
+ ### How it works:
32
+
33
+ - `value` and `onChange`: Both components share the same `value`, which represents the list of uploaded files, and `onChange`, which updates that list. This ensures that the files selected for upload are consistent with what is displayed in the file list.
34
+ - We can use the `getDropzoneState` function to determine the current status of the uploaded files. This status can be used to disable the Dropzone component while files are being uploaded.
35
+ - We can use the `onDropRejected` prop to handle rejected files. This prop is called when the user tries to upload files that exceed the size limit or the maximum number of files allowed. We can use this prop to display an error message to the user.
36
+
37
+ Example of handling rejected files:
38
+ ```tsx
39
+ const handleDropRejectedFiles = async (fileRejections: FileRejection[]) => {
40
+ const bigFiles = fileRejections.filter((rejection) =>
41
+ rejection.errors.some((error) => error.code === ErrorCode.FileTooLarge),
42
+ );
43
+ const tooManyFiles = fileRejections.filter((rejection) =>
44
+ rejection.errors.some((error) => error.code === ErrorCode.TooManyFiles),
45
+ );
46
+ if (isNotEmpty(bigFiles)) {
47
+ alert(
48
+ `Tyto soubory jsou příliš velké a nebyly nahrány: ${bigFiles.map((file) => file.file.name).join(", ")}`,
49
+ );
50
+ }
51
+ if (isNotEmpty(tooManyFiles)) {
52
+ alert(`Bylo nahráno příliš mnoho souborů. Maximální počet souborů je ${fileCountLimit}`);
53
+ }
54
+ };
55
+ ```
56
+
57
+ ## Basic Example:
58
+ ---
59
+ This example shows how to use the **Dropzone** component with useState to manage file uploads:
60
+
61
+ ```tsx
62
+ import React, {useState} from "react";
63
+ import {Dropzone} from "./path/to/dropzone";
64
+ import {DropzoneFile} from "./path/to/dropzone/types";
65
+ import {uploadFile} from "@uxf/ui/utils/mocks/upload-file.mock";
66
+
67
+ function BasicExample() {
68
+ // Store uploaded files in state
69
+ const [files, setFiles] = useState<DropzoneFile[]>([]);
70
+
71
+ // Get the current status of uploaded files
72
+ const { status } = getDropzoneState(files);
73
+
74
+ // Confirm file removal
75
+ const onRemoveConfirm = (): Promise<boolean> => Promise.resolve(confirm("Do you want to delete the file?"));
76
+
77
+ // Handle upload errors
78
+ const onUploadError = (error: unknown) => {
79
+ console.error(error);
80
+ };
81
+
82
+ return (
83
+ <div>
84
+ {/* Dropzone component for uploading files */}
85
+ <Dropzone
86
+ isDisabled={status === "UPLOADING"}
87
+ onChange={setFiles}
88
+ onUploadError={onUploadError}
89
+ onUploadFile={uploadFile}
90
+ value={files}
91
+ />
92
+
93
+ {/* List of uploaded files */}
94
+ <Dropzone.List
95
+ onChange={setFiles}
96
+ onRemoveConfirm={onRemoveConfirm}
97
+ value={files}
98
+ />
99
+ </div>
100
+ );
101
+ };
102
+ ```
103
+
104
+ ## Advanced Example:
105
+ ---
106
+ This example shows how to use the **Dropzone** component with limited file types and sizes:
@@ -1,6 +1,7 @@
1
1
  import { FileResponse } from "@uxf/core/types";
2
2
  import { FormControlProps, UploadOptions } from "@uxf/ui/types";
3
3
  import React, { CSSProperties, ReactNode } from "react";
4
+ import { FileRejection } from "react-dropzone";
4
5
  import { IconName } from "../icon/types";
5
6
  import { Accept, DropzoneFile } from "./types";
6
7
  export interface DropzoneInputProps extends FormControlProps<DropzoneFile[] | undefined> {
@@ -9,12 +10,13 @@ export interface DropzoneInputProps extends FormControlProps<DropzoneFile[] | un
9
10
  helperText?: ReactNode;
10
11
  icon?: IconName;
11
12
  id?: string;
13
+ isNotClickable?: boolean;
14
+ isNotDraggable?: boolean;
12
15
  label?: ReactNode;
13
16
  maxFileSize?: number;
14
17
  maxFilesCount?: number;
15
18
  minFileSize?: number;
16
- noClick?: boolean;
17
- noDrag?: boolean;
19
+ onDropRejected?: (fileRejections: FileRejection[]) => void;
18
20
  onUploadError?: (err: unknown) => void;
19
21
  onUploadFile: (file: File, options?: UploadOptions) => Promise<FileResponse>;
20
22
  style?: CSSProperties;
@@ -30,7 +30,6 @@ const cx_1 = require("@uxf/core/utils/cx");
30
30
  const react_1 = __importStar(require("react"));
31
31
  const react_dropzone_1 = require("react-dropzone");
32
32
  const icon_1 = require("../icon");
33
- const validator_exceptions_1 = require("../utils/validator/validator-exceptions");
34
33
  function fileToFileResponse(file) {
35
34
  return {
36
35
  id: -Math.round(Math.random() * 100000000),
@@ -68,16 +67,6 @@ exports.DropzoneInput = (0, react_1.forwardRef)((props, ref) => {
68
67
  var _a, _b;
69
68
  const refValue = (0, react_1.useRef)();
70
69
  refValue.current = props.value;
71
- const handleFileRejected = async (fileRejections) => {
72
- fileRejections.forEach((fileRejection) => {
73
- if (props.maxFileSize && fileRejection.file.size > props.maxFileSize) {
74
- if (props.onUploadError) {
75
- props.onUploadError(validator_exceptions_1.ValidatorExceptions.MaxFileSize);
76
- }
77
- throw validator_exceptions_1.ValidatorExceptions.MaxFileSize;
78
- }
79
- });
80
- };
81
70
  const handleFileDrop = async (acceptedFiles, inputRef) => {
82
71
  const files = acceptedFiles.map((file) => ({
83
72
  ...fileToFileResponse(file),
@@ -116,18 +105,18 @@ exports.DropzoneInput = (0, react_1.forwardRef)((props, ref) => {
116
105
  maxSize: props.maxFileSize,
117
106
  minSize: props.minFileSize,
118
107
  multiple: props.maxFilesCount !== 1,
119
- noClick: props.noClick,
120
- noDrag: props.noDrag,
108
+ noClick: props.isNotClickable,
109
+ noDrag: props.isNotDraggable,
121
110
  onDrop: (acceptedFiles) => handleFileDrop(acceptedFiles, inputRef),
122
- preventDropOnDocument: props.noDrag,
123
- onDropRejected: handleFileRejected,
111
+ preventDropOnDocument: props.isNotDraggable,
112
+ onDropRejected: props.onDropRejected,
124
113
  });
125
114
  const labelOnCLick = (e) => {
126
115
  e.stopPropagation();
127
116
  };
128
117
  return (react_1.default.createElement("div", { className: `uxf-dropzone ${(_a = props.className) !== null && _a !== void 0 ? _a : ""}`, style: props.style },
129
118
  react_1.default.createElement("label", { ...getRootProps({
130
- 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"),
119
+ className: (0, cx_1.cx)("uxf-dropzone__label", props.isInvalid && classes_1.CLASSES.IS_INVALID, props.isDisabled && classes_1.CLASSES.IS_DISABLED, props.isNotClickable && "cursor-auto"),
131
120
  onClick: labelOnCLick,
132
121
  }), ref: (0, compose_refs_1.composeRefs)(ref, rootRef) },
133
122
  react_1.default.createElement(icon_1.Icon, { className: "uxf-dropzone__label__icon", name: (_b = props.icon) !== null && _b !== void 0 ? _b : "cloud" }),
@@ -1,5 +1,5 @@
1
1
  import { FormControlProps } from "@uxf/ui/types";
2
- import { CSSProperties, FC, ReactNode } from "react";
2
+ import React, { CSSProperties, ReactNode } from "react";
3
3
  import { DropzoneFile } from "./types";
4
4
  export interface DropzoneListProps extends FormControlProps<DropzoneFile[] | undefined> {
5
5
  className?: string;
@@ -9,4 +9,7 @@ export interface DropzoneListProps extends FormControlProps<DropzoneFile[] | und
9
9
  renderItem?: (file: DropzoneFile) => ReactNode;
10
10
  style?: CSSProperties;
11
11
  }
12
- export declare const DropzoneList: FC<DropzoneListProps>;
12
+ export declare function DropzoneList(props: DropzoneListProps): React.JSX.Element | null;
13
+ export declare namespace DropzoneList {
14
+ var displayName: string;
15
+ }
@@ -23,7 +23,8 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.DropzoneList = void 0;
26
+ exports.DropzoneList = DropzoneList;
27
+ const hide_1 = require("@uxf/core-react/components/hide");
27
28
  const classes_1 = require("@uxf/core/constants/classes");
28
29
  const cx_1 = require("@uxf/core/utils/cx");
29
30
  const context_1 = require("@uxf/ui/context");
@@ -39,7 +40,7 @@ function formatBytes(bytes, decimals = 2) {
39
40
  const i = Math.floor(Math.log(bytes) / Math.log(k));
40
41
  return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
41
42
  }
42
- const DropzoneList = (props) => {
43
+ function DropzoneList(props) {
43
44
  var _a, _b, _c;
44
45
  const context = (0, react_1.useContext)(context_1.UiContext);
45
46
  const handleRemove = (file, value, isUploading) => {
@@ -76,10 +77,10 @@ const DropzoneList = (props) => {
76
77
  react_1.default.createElement("div", { className: "uxf-dropzone-list__item__block" },
77
78
  isUploading ? (react_1.default.createElement(loader_1.Loader, { size: "sm" })) : (!file.error &&
78
79
  ((_c = file.originalFile) === null || _c === void 0 ? void 0 : _c.size) && (react_1.default.createElement("span", { className: "uxf-dropzone-list__item__block__file-size" }, formatBytes(file.originalFile.size)))),
79
- react_1.default.createElement("button", { className: "uxf-dropzone-list__item__block__remove-button", onClick: onRemove(file, isUploading), type: "button" },
80
- react_1.default.createElement(icon_1.Icon, { className: "uxf-dropzone-list__item__block__remove-button__icon", name: "xmarkLarge" })))),
80
+ react_1.default.createElement(hide_1.Hide, { when: Boolean(props.isDisabled) },
81
+ react_1.default.createElement("button", { className: "uxf-dropzone-list__item__block__remove-button", onClick: onRemove(file, isUploading), type: "button" },
82
+ react_1.default.createElement(icon_1.Icon, { className: "uxf-dropzone-list__item__block__remove-button__icon", name: "xmarkLarge" }))))),
81
83
  Boolean(file.error) && (react_1.default.createElement("span", { className: (0, cx_1.cx)("uxf-helper-text", classes_1.CLASSES.IS_INVALID) }, props.errorText || "File upload error")))));
82
84
  })));
83
- };
84
- exports.DropzoneList = DropzoneList;
85
- exports.DropzoneList.displayName = "UxfUiDropzoneList";
85
+ }
86
+ DropzoneList.displayName = "UxfUiDropzoneList";
@@ -2,9 +2,8 @@ import React from "react";
2
2
  declare const _default: {
3
3
  title: string;
4
4
  component: React.ForwardRefExoticComponent<import("./dropzone-input").DropzoneInputProps & React.RefAttributes<HTMLDivElement>> & {
5
- List: React.FC<import("./dropzone-list").DropzoneListProps>;
5
+ List: typeof import("./dropzone-list").DropzoneList;
6
6
  };
7
7
  };
8
8
  export default _default;
9
9
  export declare function Default(): React.JSX.Element;
10
- export declare function ComponentStructure(): React.JSX.Element;
@@ -22,54 +22,46 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
25
  Object.defineProperty(exports, "__esModule", { value: true });
29
26
  exports.Default = Default;
30
- exports.ComponentStructure = ComponentStructure;
31
- const component_structure_analyzer_1 = __importDefault(require("@uxf/ui/utils/component-structure-analyzer"));
27
+ const show_1 = require("@uxf/core-react/components/show");
28
+ const is_not_empty_1 = require("@uxf/core/utils/is-not-empty");
29
+ const handle_rejected_files_1 = require("@uxf/ui/dropzone/handle-rejected-files");
32
30
  const react_1 = __importStar(require("react"));
33
- const get_provider_config_1 = require("../_private-utils/get-provider-config");
34
- const context_1 = require("../context");
35
- const message_1 = require("../message");
31
+ const toggle_1 = require("../toggle");
36
32
  const action_1 = require("../utils/action");
37
- const get_dropzone_state_1 = require("../utils/get-dropzone-state");
38
33
  const upload_file_mock_1 = require("../utils/mocks/upload-file.mock");
39
34
  const index_1 = require("./index");
40
35
  exports.default = {
41
36
  title: "UI/Dropzone",
42
37
  component: index_1.Dropzone,
43
38
  };
39
+ const MB_SIZE = 1024 * 1024;
44
40
  function Default() {
41
+ const [isDisabled, setIsDisabled] = (0, react_1.useState)(false);
42
+ const [isFileCountLimited, setIsFileCountLimited] = (0, react_1.useState)(false);
43
+ const [fileCountLimit, setFileCountLimit] = (0, react_1.useState)(1);
44
+ const [isFileSizeLimited, setIsFileSizeLimited] = (0, react_1.useState)(false);
45
+ const [fileSizeLimit, setFileSizeLimit] = (0, react_1.useState)(1);
46
+ const [hasOnlyImagesAllowed, setHasOnlyImagesAllowed] = (0, react_1.useState)(false);
45
47
  const [files, setFiles] = (0, react_1.useState)([]);
46
48
  const onChange = (0, action_1.action)("onChange", setFiles);
47
- const { status } = (0, get_dropzone_state_1.getDropzoneState)(files);
48
- const onRemoveConfirm = () => {
49
- return new Promise((resolve) => {
50
- message_1.MessageService.openConfirm({
51
- acceptLabel: "Yes, delete",
52
- cancelLabel: "Cancel",
53
- title: "Do you want to delete the file?",
54
- color: "error",
55
- variant: "centered",
56
- onAccept: () => resolve(true),
57
- onCancel: () => resolve(false),
58
- CustomIconComponent: null,
59
- });
60
- });
61
- };
62
- return (react_1.default.createElement(context_1.UiContextProvider, { value: (0, get_provider_config_1.getProviderConfig)() },
63
- react_1.default.createElement(index_1.Dropzone, { helperText: "Disabled drag 'n' drop", isDisabled: status === "UPLOADING", label: "Use drag and drop or click to upload", name: "dropzone-disabled-drag-and-drop", noDrag: true, onChange: onChange, onUploadFile: upload_file_mock_1.uploadFile, value: files }),
64
- react_1.default.createElement(index_1.Dropzone, { helperText: "Disabled onClick upload", label: react_1.default.createElement("span", { className: "bg-primary-600 rounded-lg px-4 py-2 font-bold text-white" }, "JSX label"), name: "dropzone-disabled-click", noClick: true, onChange: onChange, onUploadFile: upload_file_mock_1.uploadFile, value: files }),
65
- react_1.default.createElement(index_1.Dropzone, { accept: { "image/*": [] }, label: "Only images upload", name: "dropzone-only-images", onChange: onChange, onUploadFile: upload_file_mock_1.uploadFile, value: files }),
66
- react_1.default.createElement(index_1.Dropzone, { label: "Single file upload", maxFilesCount: 1, name: "dropzone-single-file", onChange: onChange, onUploadFile: upload_file_mock_1.uploadFile, value: files }),
67
- react_1.default.createElement(index_1.Dropzone, { isDisabled: true, label: "Disabled dropzone", name: "dropzone-disabled", onChange: onChange, onUploadFile: upload_file_mock_1.uploadFile, value: files }),
68
- react_1.default.createElement(index_1.Dropzone.List, { errorText: "Chyba p\u0159i nahr\u00E1v\u00E1n\u00ED souboru", name: "dropzone-error-message", onChange: onChange, onRemoveConfirm: onRemoveConfirm, value: files }),
69
- react_1.default.createElement(index_1.Dropzone.List, { name: "dropzone-list", onChange: onChange, onRemoveConfirm: onRemoveConfirm, renderItem: (file) => (react_1.default.createElement("li", { key: file.id },
70
- react_1.default.createElement("pre", { className: "text-wrap" }, JSON.stringify(file, null, 4)))), value: files })));
71
- }
72
- function ComponentStructure() {
73
- return (react_1.default.createElement(component_structure_analyzer_1.default, null,
74
- react_1.default.createElement(index_1.Dropzone, null)));
49
+ const onRemoveConfirm = () => Promise.resolve(confirm("Do you want to delete the file?"));
50
+ return (react_1.default.createElement(react_1.default.Fragment, null,
51
+ react_1.default.createElement(toggle_1.Toggle, { label: "Disabled", name: "toggle", onChange: () => setIsDisabled((prev) => !prev), value: isDisabled }),
52
+ react_1.default.createElement(toggle_1.Toggle, { label: "Only images upload", name: "toggle", onChange: () => setHasOnlyImagesAllowed((prev) => !prev), value: hasOnlyImagesAllowed }),
53
+ react_1.default.createElement("div", { className: "flex items-center" },
54
+ react_1.default.createElement(toggle_1.Toggle, { label: "Limit file count", name: "toggle", onChange: () => setIsFileCountLimited((prev) => !prev), value: isFileCountLimited }),
55
+ react_1.default.createElement("input", { className: "w-20", onChange: (event) => setFileCountLimit(parseInt(event.target.value, 10)), type: "number", value: fileCountLimit })),
56
+ react_1.default.createElement("div", { className: "flex items-center" },
57
+ react_1.default.createElement(toggle_1.Toggle, { label: "Limit file size", name: "toggle", onChange: () => setIsFileSizeLimited((prev) => !prev), value: isFileSizeLimited }),
58
+ react_1.default.createElement("input", { className: "w-20", onChange: (event) => setFileSizeLimit(parseInt(event.target.value, 10)), type: "number", value: fileSizeLimit }),
59
+ "MB"),
60
+ react_1.default.createElement(index_1.Dropzone, { accept: hasOnlyImagesAllowed ? { "image/*": [] } : undefined, isDisabled: isDisabled, label: "Use drag and drop or click to upload", maxFileSize: isFileSizeLimited ? fileSizeLimit * MB_SIZE : undefined, maxFilesCount: isFileCountLimited ? fileCountLimit : undefined, name: "dropzone-disabled-drag-and-drop", onChange: onChange, onDropRejected: (fileRejections) => (0, handle_rejected_files_1.handleRejectedFiles)(fileRejections, fileCountLimit), onUploadFile: upload_file_mock_1.uploadFile, value: files }),
61
+ react_1.default.createElement(index_1.Dropzone.List, { className: "mt-6", errorText: "Chyba p\u0159i nahr\u00E1v\u00E1n\u00ED souboru", isDisabled: isDisabled, name: "dropzone-error-message", onChange: onChange, onRemoveConfirm: onRemoveConfirm, value: files }),
62
+ react_1.default.createElement(show_1.Show, { when: (0, is_not_empty_1.isNotEmpty)(files) },
63
+ react_1.default.createElement("div", { className: "mt-6" },
64
+ react_1.default.createElement("p", null, "File response:"),
65
+ react_1.default.createElement(index_1.Dropzone.List, { className: "w-max bg-gray-200 p-4", name: "dropzone-list", onChange: onChange, onRemoveConfirm: onRemoveConfirm, renderItem: (file) => (react_1.default.createElement("li", { key: file.id },
66
+ react_1.default.createElement("pre", { className: "text-wrap" }, JSON.stringify(file, null, 4)))), value: files })))));
75
67
  }
@@ -0,0 +1,2 @@
1
+ import { FileRejection } from "react-dropzone";
2
+ export declare function handleRejectedFiles(fileRejections: FileRejection[], fileCountLimit: number): Promise<void>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleRejectedFiles = handleRejectedFiles;
4
+ const is_not_empty_1 = require("@uxf/core/utils/is-not-empty");
5
+ const react_dropzone_1 = require("react-dropzone");
6
+ async function handleRejectedFiles(fileRejections, fileCountLimit) {
7
+ const bigFiles = fileRejections.filter((rejection) => rejection.errors.some((error) => error.code === react_dropzone_1.ErrorCode.FileTooLarge));
8
+ const tooManyFiles = fileRejections.filter((rejection) => rejection.errors.some((error) => error.code === react_dropzone_1.ErrorCode.TooManyFiles));
9
+ if ((0, is_not_empty_1.isNotEmpty)(bigFiles)) {
10
+ // eslint-disable-next-line no-alert
11
+ alert(`Tyto soubory jsou příliš velké a nebyly nahrány: ${bigFiles.map((file) => file.file.name).join(", ")}`);
12
+ }
13
+ if ((0, is_not_empty_1.isNotEmpty)(tooManyFiles)) {
14
+ // eslint-disable-next-line no-alert
15
+ alert(`Bylo nahráno příliš mnoho souborů. Maximální počet souborů je ${fileCountLimit}`);
16
+ }
17
+ }
@@ -1,5 +1,6 @@
1
+ import { DropzoneList } from "./dropzone-list";
1
2
  export type { DropzoneInputProps } from "./dropzone-input";
2
3
  export type { DropzoneListProps } from "./dropzone-list";
3
4
  export declare const Dropzone: import("react").ForwardRefExoticComponent<import("./dropzone-input").DropzoneInputProps & import("react").RefAttributes<HTMLDivElement>> & {
4
- List: import("react").FC<import("./dropzone-list").DropzoneListProps>;
5
+ List: typeof DropzoneList;
5
6
  };
@@ -1,7 +1,9 @@
1
1
  import { UseAnchorProps } from "@uxf/core-react/hooks/use-anchor-props";
2
2
  import React, { AnchorHTMLAttributes, ReactNode } from "react";
3
3
  import { IconName } from "../icon/types";
4
+ import { NextLink } from "../utils/next-link";
4
5
  export interface ListItemProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "type">, UseAnchorProps {
6
+ as?: NextLink | "a";
5
7
  endIcon?: IconName;
6
8
  endElement?: ReactNode;
7
9
  }
@@ -30,12 +30,13 @@ const react_1 = __importStar(require("react"));
30
30
  const icon_1 = require("../icon");
31
31
  exports.ListItem = (0, react_1.forwardRef)((props, ref) => {
32
32
  // eslint-disable-next-line react/destructuring-assignment
33
- const { className, children, endElement, endIcon, ...restProps } = props;
33
+ const { as = "a", className, children, endElement, endIcon, ...restProps } = props;
34
+ const Component = as;
34
35
  const anchorProps = (0, use_anchor_props_1.useAnchorProps)({
35
36
  ...restProps,
36
37
  className: (0, cx_1.cx)("uxf-list-item", className),
37
38
  });
38
- return (react_1.default.createElement("a", { ref: ref, ...anchorProps },
39
+ return (react_1.default.createElement(Component, { ref: ref, ...anchorProps },
39
40
  react_1.default.createElement("span", { className: "uxf-list-item__inner" }, children),
40
41
  endElement && react_1.default.createElement("span", { className: "uxf-list-item__end-element-wrapper" }, endElement),
41
42
  endIcon && (react_1.default.createElement("span", { className: "uxf-list-item__end-icon-wrapper" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uxf/ui",
3
- "version": "11.34.1",
3
+ "version": "11.35.0",
4
4
  "description": "",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -17,10 +17,10 @@
17
17
  "dependencies": {
18
18
  "@floating-ui/react": "0.26.23",
19
19
  "@headlessui/react": "1.7.14",
20
- "@uxf/core": "11.32.0",
21
- "@uxf/core-react": "11.33.0",
20
+ "@uxf/core": "11.35.0",
21
+ "@uxf/core-react": "11.35.0",
22
22
  "@uxf/datepicker": "11.32.0",
23
- "@uxf/styles": "11.32.0",
23
+ "@uxf/styles": "11.35.0",
24
24
  "color2k": "2.0.3",
25
25
  "dayjs": "1.11.13",
26
26
  "jump.js": "1.0.2",
@@ -1,8 +1,10 @@
1
1
  import { UseAnchorProps } from "@uxf/core-react/hooks/use-anchor-props";
2
2
  import { TextLinkVariants } from "@uxf/ui/text-link/theme";
3
3
  import React, { AnchorHTMLAttributes } from "react";
4
+ import { NextLink } from "../utils/next-link";
4
5
  export type TextLinkVariant = keyof TextLinkVariants;
5
6
  export interface TextLinkProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "type">, UseAnchorProps {
7
+ as?: NextLink | "a";
6
8
  variant?: TextLinkVariant;
7
9
  }
8
10
  export declare const TextLink: React.ForwardRefExoticComponent<TextLinkProps & React.RefAttributes<HTMLAnchorElement>>;
@@ -29,11 +29,12 @@ const cx_1 = require("@uxf/core/utils/cx");
29
29
  const react_1 = __importStar(require("react"));
30
30
  exports.TextLink = (0, react_1.forwardRef)((props, ref) => {
31
31
  // eslint-disable-next-line react/destructuring-assignment
32
- const { className, children, variant, ...restProps } = props;
32
+ const { as = "a", className, children, variant, ...restProps } = props;
33
+ const Component = as;
33
34
  const anchorProps = (0, use_anchor_props_1.useAnchorProps)({
34
35
  ...restProps,
35
36
  className: (0, cx_1.cx)("uxf-text-link", `uxf-text-link--variant-${variant !== null && variant !== void 0 ? variant : "default"}`, className),
36
37
  });
37
- return (react_1.default.createElement("a", { ref: ref, ...anchorProps }, children));
38
+ return (react_1.default.createElement(Component, { ref: ref, ...anchorProps }, children));
38
39
  });
39
40
  exports.TextLink.displayName = "UxfUiTextLink";
File without changes
File without changes