uibee 3.2.0 → 3.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/alert/alert.d.ts +15 -0
- package/dist/components/alert/alert.js +29 -0
- package/dist/components/badge/badge.d.ts +16 -0
- package/dist/components/badge/badge.js +26 -0
- package/dist/components/buttons/button.d.ts +25 -0
- package/dist/components/buttons/button.js +44 -0
- package/dist/components/code/code.d.ts +23 -0
- package/dist/components/code/code.js +39 -0
- package/dist/components/confirm/confirmPopup.d.ts +23 -0
- package/dist/components/confirm/confirmPopup.js +52 -0
- package/dist/components/container/accordion.d.ts +25 -0
- package/dist/components/container/accordion.js +41 -0
- package/dist/components/container/card.d.ts +13 -0
- package/dist/components/container/card.js +10 -0
- package/dist/components/container/expandableCard.d.ts +32 -0
- package/dist/components/container/expandableCard.js +70 -0
- package/dist/components/container/glassCard.d.ts +13 -0
- package/dist/components/container/glassCard.js +10 -0
- package/dist/components/container/highlight.d.ts +10 -0
- package/dist/components/container/highlight.js +10 -0
- package/dist/components/container/iconBubble.d.ts +25 -0
- package/dist/components/container/iconBubble.js +21 -0
- package/dist/components/container/leftBarPanel.d.ts +15 -0
- package/dist/components/container/leftBarPanel.js +10 -0
- package/dist/components/container/page.d.ts +15 -0
- package/dist/components/container/page.js +16 -0
- package/dist/components/container/pulseDot.d.ts +12 -0
- package/dist/components/container/pulseDot.js +23 -0
- package/dist/components/container/statCard.d.ts +18 -0
- package/dist/components/container/statCard.js +25 -0
- package/dist/components/container/tabs.d.ts +35 -0
- package/dist/components/container/tabs.js +36 -0
- package/dist/components/empty/emptyState.d.ts +19 -0
- package/dist/components/empty/emptyState.js +27 -0
- package/dist/components/footer/footer.d.ts +49 -0
- package/dist/components/footer/footer.js +109 -0
- package/dist/components/footer/loginContent.d.ts +18 -0
- package/dist/components/footer/loginContent.js +138 -0
- package/dist/components/inputs/checkbox.d.ts +20 -0
- package/dist/components/inputs/checkbox.js +76 -0
- package/dist/components/inputs/fileInput.d.ts +19 -0
- package/dist/components/inputs/fileInput.js +108 -0
- package/dist/components/inputs/input.d.ts +16 -0
- package/dist/components/inputs/input.js +157 -0
- package/dist/components/inputs/multiSelect.d.ts +37 -0
- package/dist/components/inputs/multiSelect.js +99 -0
- package/dist/components/inputs/radio.d.ts +20 -0
- package/dist/components/inputs/radio.js +70 -0
- package/dist/components/inputs/range.d.ts +14 -0
- package/dist/components/inputs/range.js +60 -0
- package/dist/components/inputs/searchInput.d.ts +11 -0
- package/dist/components/inputs/searchInput.js +56 -0
- package/dist/components/inputs/select.d.ts +42 -0
- package/dist/components/inputs/select.js +164 -0
- package/dist/components/inputs/shared/colorPickerPopup.js +293 -0
- package/dist/components/inputs/shared/dateTimePickerPopup.js +225 -0
- package/dist/components/inputs/shared/fieldWrapper.js +33 -0
- package/dist/components/inputs/shared/index.js +6 -0
- package/dist/components/inputs/shared/inputError.js +17 -0
- package/dist/components/inputs/shared/inputInfo.js +13 -0
- package/dist/components/inputs/shared/inputLabel.js +19 -0
- package/dist/components/inputs/switch.d.ts +14 -0
- package/dist/components/inputs/switch.js +37 -0
- package/dist/components/inputs/tagInput.d.ts +31 -0
- package/dist/components/inputs/tagInput.js +72 -0
- package/dist/components/inputs/textarea.d.ts +14 -0
- package/dist/components/inputs/textarea.js +76 -0
- package/dist/components/inputs/toggle.d.ts +21 -0
- package/dist/components/inputs/toggle.js +33 -0
- package/dist/components/login/loginPage.d.ts +15 -0
- package/dist/components/login/loginPage.js +80 -0
- package/dist/components/logo/logo.d.ts +9 -0
- package/dist/components/logo/logo.js +138 -0
- package/dist/components/logo/logoSmall.d.ts +4 -0
- package/dist/components/logo/logoSmall.js +56 -0
- package/dist/components/markdownrender/markdownRender.d.ts +16 -0
- package/dist/components/markdownrender/markdownRender.js +59 -0
- package/dist/components/modal/modal.d.ts +22 -0
- package/dist/components/modal/modal.js +59 -0
- package/dist/components/navbar/bubble.js +36 -0
- package/dist/components/navbar/navbar.d.ts +50 -0
- package/dist/components/navbar/navbar.js +99 -0
- package/dist/components/navbar/navbarDropdown.d.ts +15 -0
- package/dist/components/navbar/navbarDropdown.js +63 -0
- package/dist/components/navbar/navbarItem.d.ts +23 -0
- package/dist/components/navbar/navbarItem.js +38 -0
- package/dist/components/sidebar/sidebar.d.ts +34 -0
- package/dist/components/sidebar/sidebar.js +135 -0
- package/dist/components/spinner/spinner.d.ts +11 -0
- package/dist/components/spinner/spinner.js +16 -0
- package/dist/components/table/body.js +253 -0
- package/dist/components/table/constants.js +58 -0
- package/dist/components/table/empty.js +24 -0
- package/dist/components/table/format.js +39 -0
- package/dist/components/table/header.js +109 -0
- package/dist/components/table/menu.d.ts +18 -0
- package/dist/components/table/menu.js +76 -0
- package/dist/components/table/pagination.d.ts +14 -0
- package/dist/components/table/pagination.js +130 -0
- package/dist/components/table/skeleton.js +39 -0
- package/dist/components/table/table.d.ts +7 -0
- package/dist/components/table/table.js +213 -0
- package/dist/components/table/types.d.ts +52 -0
- package/dist/components/table/utils.js +9 -0
- package/dist/components/toast/toastItem.js +61 -0
- package/dist/components/toast/toaster.d.ts +13 -0
- package/dist/components/toast/toaster.js +117 -0
- package/dist/components/toggle/language.d.ts +10 -0
- package/dist/components/toggle/language.js +34 -0
- package/dist/components/toggle/theme.d.ts +8 -0
- package/dist/components/toggle/theme.js +135 -0
- package/dist/components/version/version.d.ts +13 -0
- package/dist/components/version/version.js +19 -0
- package/dist/components/vulnerability/constants.d.ts +4 -0
- package/dist/components/vulnerability/constants.js +17 -0
- package/dist/components/vulnerability/severityPill.d.ts +15 -0
- package/dist/components/vulnerability/severityPill.js +20 -0
- package/dist/{style.css → globals.css} +155 -226
- package/dist/hooks/useClickOutside.d.ts +6 -0
- package/dist/{useClickOutside-Cmp-RsP3.js → hooks/useClickOutside.js} +1 -1
- package/dist/hooks/useDarkMode.d.ts +4 -0
- package/dist/hooks/useDarkMode.js +19 -0
- package/dist/hooks/useVisibility.d.ts +7 -0
- package/dist/hooks/useVisibility.js +25 -0
- package/dist/icons/icons.d.ts +420 -0
- package/dist/{icons-lZYQ6Vlr.js → icons/icons.js} +1 -1
- package/dist/src/components/index.d.ts +51 -901
- package/dist/src/components/index.js +49 -4160
- package/dist/src/hooks/index.d.ts +3 -14
- package/dist/src/hooks/index.js +3 -42
- package/dist/src/icons/index.d.ts +1 -419
- package/dist/src/icons/index.js +1 -1
- package/dist/src/styles/index.js +1 -1
- package/dist/src/utils/index.d.ts +5 -37
- package/dist/src/utils/index.js +5 -124
- package/dist/utils/auth/callback.d.ts +14 -0
- package/dist/utils/auth/callback.js +53 -0
- package/dist/utils/auth/getDomain.js +6 -0
- package/dist/utils/auth/login.d.ts +12 -0
- package/dist/utils/auth/login.js +17 -0
- package/dist/utils/auth/logout.d.ts +10 -0
- package/dist/utils/auth/logout.js +20 -0
- package/dist/utils/auth/token.d.ts +10 -0
- package/dist/utils/auth/token.js +30 -0
- package/dist/utils/logoConsoleOutput/logoConsoleOutput.d.ts +4 -0
- package/dist/utils/logoConsoleOutput/logoConsoleOutput.js +11 -0
- package/package.json +1 -1
- package/src/components/buttons/button.tsx +2 -0
- package/src/components/footer/footer.tsx +65 -28
- package/src/components/index.ts +0 -1
- package/src/components/inputs/checkbox.tsx +2 -0
- package/src/components/inputs/input.tsx +2 -0
- package/src/components/inputs/radio.tsx +2 -0
- package/src/components/inputs/range.tsx +2 -0
- package/src/components/inputs/shared/colorPickerPopup.tsx +2 -0
- package/src/components/inputs/shared/dateTimePickerPopup.tsx +2 -0
- package/src/components/inputs/textarea.tsx +2 -0
- package/src/components/inputs/toggle.tsx +2 -0
- package/src/components/sidebar/sidebar.tsx +37 -10
- package/src/components/toast/toastItem.tsx +2 -0
- package/src/globals.css +6 -1
- package/tsdown.config.ts +1 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useRef, useState } from "react";
|
|
3
|
+
import { FileIcon, UploadCloud, X } from "lucide-react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region src/components/inputs/fileInput.tsx
|
|
6
|
+
function FileInput({ name, label, accept, multiple = false, onChange, className = "" }) {
|
|
7
|
+
const [files, setFiles] = useState([]);
|
|
8
|
+
const [dragging, setDragging] = useState(false);
|
|
9
|
+
const inputRef = useRef(null);
|
|
10
|
+
function handleFiles(incoming) {
|
|
11
|
+
if (!incoming) return;
|
|
12
|
+
const arr = multiple ? Array.from(incoming) : [incoming[0]];
|
|
13
|
+
setFiles(arr);
|
|
14
|
+
onChange(arr);
|
|
15
|
+
}
|
|
16
|
+
function removeFile(index) {
|
|
17
|
+
const next = files.filter((_, i) => i !== index);
|
|
18
|
+
setFiles(next);
|
|
19
|
+
onChange(next);
|
|
20
|
+
if (inputRef.current) inputRef.current.value = "";
|
|
21
|
+
}
|
|
22
|
+
function onDrop(e) {
|
|
23
|
+
e.preventDefault();
|
|
24
|
+
setDragging(false);
|
|
25
|
+
handleFiles(e.dataTransfer.files);
|
|
26
|
+
}
|
|
27
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
28
|
+
className: `flex flex-col gap-2 ${className}`,
|
|
29
|
+
children: [
|
|
30
|
+
label && /* @__PURE__ */ jsx("label", {
|
|
31
|
+
className: "text-sm font-medium text-login-200",
|
|
32
|
+
children: label
|
|
33
|
+
}),
|
|
34
|
+
/* @__PURE__ */ jsxs("div", {
|
|
35
|
+
role: "button",
|
|
36
|
+
tabIndex: 0,
|
|
37
|
+
onClick: () => inputRef.current?.click(),
|
|
38
|
+
onKeyDown: (e) => {
|
|
39
|
+
if (e.key === "Enter" || e.key === " ") inputRef.current?.click();
|
|
40
|
+
},
|
|
41
|
+
onDragOver: (e) => {
|
|
42
|
+
e.preventDefault();
|
|
43
|
+
setDragging(true);
|
|
44
|
+
},
|
|
45
|
+
onDragLeave: () => setDragging(false),
|
|
46
|
+
onDrop,
|
|
47
|
+
className: `
|
|
48
|
+
flex cursor-pointer flex-col items-center justify-center gap-2 rounded-xl border-2 border-dashed p-6
|
|
49
|
+
transition-all duration-150
|
|
50
|
+
${dragging ? "scale-[1.01] border-login bg-login/5" : "border-login-500/50 bg-login-800/30 hover:border-login/50 hover:bg-login/5"}
|
|
51
|
+
`,
|
|
52
|
+
children: [
|
|
53
|
+
/* @__PURE__ */ jsx("input", {
|
|
54
|
+
ref: inputRef,
|
|
55
|
+
type: "file",
|
|
56
|
+
name,
|
|
57
|
+
accept,
|
|
58
|
+
multiple,
|
|
59
|
+
className: "hidden",
|
|
60
|
+
onChange: (e) => handleFiles(e.target.files)
|
|
61
|
+
}),
|
|
62
|
+
/* @__PURE__ */ jsx(UploadCloud, { className: "h-7 w-7 text-login-400" }),
|
|
63
|
+
/* @__PURE__ */ jsxs("div", {
|
|
64
|
+
className: "text-center",
|
|
65
|
+
children: [/* @__PURE__ */ jsxs("p", {
|
|
66
|
+
className: "text-sm text-login-200",
|
|
67
|
+
children: ["Drop files here or ", /* @__PURE__ */ jsx("span", {
|
|
68
|
+
className: "text-login",
|
|
69
|
+
children: "browse"
|
|
70
|
+
})]
|
|
71
|
+
}), accept && /* @__PURE__ */ jsx("p", {
|
|
72
|
+
className: "mt-0.5 text-xs text-login-400",
|
|
73
|
+
children: accept
|
|
74
|
+
})]
|
|
75
|
+
})
|
|
76
|
+
]
|
|
77
|
+
}),
|
|
78
|
+
files.length > 0 && /* @__PURE__ */ jsx("ul", {
|
|
79
|
+
className: "flex flex-col gap-1.5",
|
|
80
|
+
children: files.map((file, i) => /* @__PURE__ */ jsxs("li", {
|
|
81
|
+
className: "\n flex items-center gap-2 rounded-lg\n border border-login-500/25 bg-login-800/50 px-3 py-2 text-sm\n ",
|
|
82
|
+
children: [
|
|
83
|
+
/* @__PURE__ */ jsx(FileIcon, { className: "h-4 w-4 shrink-0 text-login-400" }),
|
|
84
|
+
/* @__PURE__ */ jsx("span", {
|
|
85
|
+
className: "flex-1 truncate text-login-200",
|
|
86
|
+
children: file.name
|
|
87
|
+
}),
|
|
88
|
+
/* @__PURE__ */ jsxs("span", {
|
|
89
|
+
className: "shrink-0 text-xs text-login-400",
|
|
90
|
+
children: [(file.size / 1024).toFixed(1), " KB"]
|
|
91
|
+
}),
|
|
92
|
+
/* @__PURE__ */ jsx("button", {
|
|
93
|
+
type: "button",
|
|
94
|
+
onClick: (e) => {
|
|
95
|
+
e.stopPropagation();
|
|
96
|
+
removeFile(i);
|
|
97
|
+
},
|
|
98
|
+
className: "cursor-pointer text-login-400 transition-colors hover:text-red-400",
|
|
99
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" })
|
|
100
|
+
})
|
|
101
|
+
]
|
|
102
|
+
}, i))
|
|
103
|
+
})
|
|
104
|
+
]
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
//#endregion
|
|
108
|
+
export { FileInput as default };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React, { JSX } from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/components/inputs/input.d.ts
|
|
4
|
+
type InputProps = Omit<React.ComponentProps<'input'>, 'name'> & {
|
|
5
|
+
name: string;
|
|
6
|
+
label?: string;
|
|
7
|
+
error?: string;
|
|
8
|
+
className?: string;
|
|
9
|
+
icon?: JSX.Element;
|
|
10
|
+
info?: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
textSize?: 'sm' | 'md';
|
|
13
|
+
};
|
|
14
|
+
declare function Input(props: InputProps): JSX.Element;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { InputProps, Input as default };
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import FieldWrapper from "./shared/fieldWrapper.js";
|
|
3
|
+
import ColorPickerPopup from "./shared/colorPickerPopup.js";
|
|
4
|
+
import "./shared/index.js";
|
|
5
|
+
import DateTimePickerPopup from "./shared/dateTimePickerPopup.js";
|
|
6
|
+
import useClickOutside from "../../hooks/useClickOutside.js";
|
|
7
|
+
import { useId, useRef, useState } from "react";
|
|
8
|
+
import { Calendar, Clock } from "lucide-react";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
//#region src/components/inputs/input.tsx
|
|
11
|
+
function Input(props) {
|
|
12
|
+
const { name, label, error, className, icon, info, description, textSize = "sm", ...inputProps } = props;
|
|
13
|
+
const { type = "text", value } = inputProps;
|
|
14
|
+
const localRef = useRef(null);
|
|
15
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
16
|
+
const anchorName = `--input-${useId().replace(/:/g, "")}`;
|
|
17
|
+
const containerRef = useRef(null);
|
|
18
|
+
useClickOutside(containerRef, () => setIsOpen(false));
|
|
19
|
+
const isDateType = [
|
|
20
|
+
"date",
|
|
21
|
+
"datetime-local",
|
|
22
|
+
"time"
|
|
23
|
+
].includes(type);
|
|
24
|
+
const isColorType = type === "color";
|
|
25
|
+
const isClickableType = isDateType || isColorType;
|
|
26
|
+
function handleIconClick() {
|
|
27
|
+
if (isClickableType && !inputProps.disabled) setIsOpen(!isOpen);
|
|
28
|
+
else if (localRef.current && !inputProps.disabled) localRef.current.focus();
|
|
29
|
+
}
|
|
30
|
+
function pad(n) {
|
|
31
|
+
return n.toString().padStart(2, "0");
|
|
32
|
+
}
|
|
33
|
+
function handleDateChange(date) {
|
|
34
|
+
const onChange = inputProps.onChange;
|
|
35
|
+
if (!onChange) return;
|
|
36
|
+
const yyyy = date.getFullYear();
|
|
37
|
+
const MM = pad(date.getMonth() + 1);
|
|
38
|
+
const dd = pad(date.getDate());
|
|
39
|
+
const hh = pad(date.getHours());
|
|
40
|
+
const mm = pad(date.getMinutes());
|
|
41
|
+
let newValue = "";
|
|
42
|
+
if (type === "date") newValue = `${yyyy}-${MM}-${dd}`;
|
|
43
|
+
else if (type === "time") newValue = `${hh}:${mm}`;
|
|
44
|
+
else if (type === "datetime-local") newValue = `${yyyy}-${MM}-${dd}T${hh}:${mm}`;
|
|
45
|
+
onChange({ target: {
|
|
46
|
+
name,
|
|
47
|
+
value: newValue,
|
|
48
|
+
type
|
|
49
|
+
} });
|
|
50
|
+
}
|
|
51
|
+
function handleColorChange(color) {
|
|
52
|
+
const onChange = inputProps.onChange;
|
|
53
|
+
if (!onChange) return;
|
|
54
|
+
onChange({ target: {
|
|
55
|
+
name,
|
|
56
|
+
value: color,
|
|
57
|
+
type
|
|
58
|
+
} });
|
|
59
|
+
}
|
|
60
|
+
let displayIcon = icon;
|
|
61
|
+
if (!displayIcon && isDateType) if (type === "time") displayIcon = /* @__PURE__ */ jsx(Clock, { className: "w-4 h-4" });
|
|
62
|
+
else displayIcon = /* @__PURE__ */ jsx(Calendar, { className: "w-4 h-4" });
|
|
63
|
+
else if (!displayIcon && isColorType) displayIcon = /* @__PURE__ */ jsx("div", {
|
|
64
|
+
className: "w-4 h-4 rounded border border-login-200",
|
|
65
|
+
style: { backgroundColor: value || "#000000" }
|
|
66
|
+
});
|
|
67
|
+
function getDateValue() {
|
|
68
|
+
if (!value) return null;
|
|
69
|
+
if (type === "time") {
|
|
70
|
+
const date = /* @__PURE__ */ new Date(`2000-01-01T${value}`);
|
|
71
|
+
return isNaN(date.getTime()) ? null : date;
|
|
72
|
+
}
|
|
73
|
+
const date = new Date(value);
|
|
74
|
+
return isNaN(date.getTime()) ? null : date;
|
|
75
|
+
}
|
|
76
|
+
function getDateDisplayValue() {
|
|
77
|
+
if (!value || !isDateType) return value;
|
|
78
|
+
const date = getDateValue();
|
|
79
|
+
if (!date) return value;
|
|
80
|
+
const yyyy = date.getFullYear();
|
|
81
|
+
const MM = pad(date.getMonth() + 1);
|
|
82
|
+
const dd = pad(date.getDate());
|
|
83
|
+
const hh = pad(date.getHours());
|
|
84
|
+
const mm = pad(date.getMinutes());
|
|
85
|
+
if (type === "date") return `${dd}.${MM}.${yyyy}`;
|
|
86
|
+
if (type === "time") return `${hh}:${mm}`;
|
|
87
|
+
if (type === "datetime-local") return `${dd}.${MM}.${yyyy} ${hh}:${mm}`;
|
|
88
|
+
return value;
|
|
89
|
+
}
|
|
90
|
+
return /* @__PURE__ */ jsx(FieldWrapper, {
|
|
91
|
+
label,
|
|
92
|
+
name,
|
|
93
|
+
required: inputProps.required,
|
|
94
|
+
info,
|
|
95
|
+
error,
|
|
96
|
+
description,
|
|
97
|
+
textSize,
|
|
98
|
+
className,
|
|
99
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
100
|
+
className: "relative flex items-center",
|
|
101
|
+
ref: containerRef,
|
|
102
|
+
children: [
|
|
103
|
+
displayIcon && /* @__PURE__ */ jsx("div", {
|
|
104
|
+
className: `
|
|
105
|
+
absolute left-3 text-login-200
|
|
106
|
+
${isClickableType && !inputProps.disabled ? "cursor-pointer hover:text-login-text" : "pointer-events-none"}
|
|
107
|
+
`,
|
|
108
|
+
onClick: handleIconClick,
|
|
109
|
+
children: displayIcon
|
|
110
|
+
}),
|
|
111
|
+
/* @__PURE__ */ jsx("input", {
|
|
112
|
+
...inputProps,
|
|
113
|
+
ref: localRef,
|
|
114
|
+
id: name,
|
|
115
|
+
name: isClickableType ? void 0 : name,
|
|
116
|
+
type: isClickableType ? "text" : type,
|
|
117
|
+
value: isDateType ? getDateDisplayValue() : value,
|
|
118
|
+
readOnly: isClickableType,
|
|
119
|
+
onClick: () => isClickableType && !inputProps.disabled && setIsOpen(true),
|
|
120
|
+
"aria-describedby": error ? `${name}-error` : void 0,
|
|
121
|
+
style: { anchorName },
|
|
122
|
+
className: `
|
|
123
|
+
w-full rounded-md bg-login-500/50 border border-login-500
|
|
124
|
+
text-login-text placeholder-login-200 text-sm
|
|
125
|
+
focus:outline-none focus:border-login/60 focus:ring-1 focus:ring-login/30
|
|
126
|
+
disabled:opacity-40 disabled:cursor-not-allowed
|
|
127
|
+
h-10 py-2 ${displayIcon ? "pl-10 pr-3" : "px-3"}
|
|
128
|
+
transition-all duration-150
|
|
129
|
+
input-reset
|
|
130
|
+
${error ? "border-red-500/70 focus:border-red-500/70 focus:ring-red-500/30" : ""}
|
|
131
|
+
${isClickableType && !inputProps.disabled ? "cursor-pointer" : ""}
|
|
132
|
+
`
|
|
133
|
+
}),
|
|
134
|
+
isClickableType && /* @__PURE__ */ jsx("input", {
|
|
135
|
+
type: "hidden",
|
|
136
|
+
name,
|
|
137
|
+
value
|
|
138
|
+
}),
|
|
139
|
+
isOpen && isDateType && !inputProps.disabled && /* @__PURE__ */ jsx(DateTimePickerPopup, {
|
|
140
|
+
value: getDateValue(),
|
|
141
|
+
onChange: handleDateChange,
|
|
142
|
+
type,
|
|
143
|
+
onClose: () => setIsOpen(false),
|
|
144
|
+
anchorName
|
|
145
|
+
}),
|
|
146
|
+
isOpen && isColorType && !inputProps.disabled && /* @__PURE__ */ jsx(ColorPickerPopup, {
|
|
147
|
+
value: value || "",
|
|
148
|
+
onChange: handleColorChange,
|
|
149
|
+
onClose: () => setIsOpen(false),
|
|
150
|
+
anchorName
|
|
151
|
+
})
|
|
152
|
+
]
|
|
153
|
+
})
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
//#endregion
|
|
157
|
+
export { Input as default };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
//#region src/components/inputs/multiSelect.d.ts
|
|
2
|
+
type Option = {
|
|
3
|
+
label: string;
|
|
4
|
+
value: string;
|
|
5
|
+
};
|
|
6
|
+
type MultiSelectProps = {
|
|
7
|
+
label?: string;
|
|
8
|
+
name: string;
|
|
9
|
+
options: Option[];
|
|
10
|
+
value?: string[];
|
|
11
|
+
onChange?: (value: string[]) => void;
|
|
12
|
+
placeholder?: string;
|
|
13
|
+
error?: string;
|
|
14
|
+
className?: string;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
required?: boolean;
|
|
17
|
+
info?: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
textSize?: 'sm' | 'md';
|
|
20
|
+
};
|
|
21
|
+
declare function MultiSelect({
|
|
22
|
+
label,
|
|
23
|
+
name,
|
|
24
|
+
options,
|
|
25
|
+
value,
|
|
26
|
+
onChange,
|
|
27
|
+
placeholder,
|
|
28
|
+
error,
|
|
29
|
+
className,
|
|
30
|
+
disabled,
|
|
31
|
+
required,
|
|
32
|
+
info,
|
|
33
|
+
description,
|
|
34
|
+
textSize
|
|
35
|
+
}: MultiSelectProps): import("react").JSX.Element;
|
|
36
|
+
//#endregion
|
|
37
|
+
export { MultiSelectProps, MultiSelect as default };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import FieldWrapper from "./shared/fieldWrapper.js";
|
|
3
|
+
import "./shared/index.js";
|
|
4
|
+
import useClickOutside from "../../hooks/useClickOutside.js";
|
|
5
|
+
import { useRef, useState } from "react";
|
|
6
|
+
import { Check, ChevronDown, X } from "lucide-react";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
//#region src/components/inputs/multiSelect.tsx
|
|
9
|
+
function MultiSelect({ label, name, options, value = [], onChange, placeholder = "Select…", error, className, disabled, required, info, description, textSize = "sm" }) {
|
|
10
|
+
const [open, setOpen] = useState(false);
|
|
11
|
+
const containerRef = useRef(null);
|
|
12
|
+
useClickOutside(containerRef, () => setOpen(false));
|
|
13
|
+
function toggleOption(optionValue) {
|
|
14
|
+
if (!onChange) return;
|
|
15
|
+
if (value.includes(optionValue)) onChange(value.filter((v) => v !== optionValue));
|
|
16
|
+
else onChange([...value, optionValue]);
|
|
17
|
+
}
|
|
18
|
+
function removeOption(optionValue) {
|
|
19
|
+
if (!onChange) return;
|
|
20
|
+
onChange(value.filter((v) => v !== optionValue));
|
|
21
|
+
}
|
|
22
|
+
return /* @__PURE__ */ jsx(FieldWrapper, {
|
|
23
|
+
label,
|
|
24
|
+
name,
|
|
25
|
+
required,
|
|
26
|
+
info,
|
|
27
|
+
description,
|
|
28
|
+
error,
|
|
29
|
+
className,
|
|
30
|
+
textSize,
|
|
31
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
32
|
+
ref: containerRef,
|
|
33
|
+
className: "relative w-full",
|
|
34
|
+
children: [
|
|
35
|
+
/* @__PURE__ */ jsxs("div", {
|
|
36
|
+
onClick: () => !disabled && setOpen((o) => !o),
|
|
37
|
+
className: `
|
|
38
|
+
flex min-h-10 cursor-pointer items-center justify-between gap-2
|
|
39
|
+
rounded-md bg-login-500/50 border border-login-500 px-3 py-1.5
|
|
40
|
+
transition-all duration-150 select-none
|
|
41
|
+
${open ? "border-login/60 ring-1 ring-login/30" : ""}
|
|
42
|
+
${error ? "border-red-500/70" : ""}
|
|
43
|
+
${disabled ? "opacity-40 cursor-not-allowed" : ""}
|
|
44
|
+
`,
|
|
45
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
46
|
+
className: "flex flex-wrap gap-1.5",
|
|
47
|
+
children: [value.length === 0 && /* @__PURE__ */ jsx("span", {
|
|
48
|
+
className: "text-sm text-login-200",
|
|
49
|
+
children: placeholder
|
|
50
|
+
}), value.map((val) => {
|
|
51
|
+
const option = options.find((o) => o.value === val);
|
|
52
|
+
if (!option) return null;
|
|
53
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
54
|
+
className: "\n flex items-center gap-1 rounded px-2 py-0.5 text-sm\n border border-login-500 bg-login-600 text-login-100\n ",
|
|
55
|
+
children: [option.label, !disabled && /* @__PURE__ */ jsx("button", {
|
|
56
|
+
type: "button",
|
|
57
|
+
onClick: (e) => {
|
|
58
|
+
e.stopPropagation();
|
|
59
|
+
removeOption(val);
|
|
60
|
+
},
|
|
61
|
+
className: "hover:text-red-300 transition-colors",
|
|
62
|
+
children: /* @__PURE__ */ jsx(X, { size: 13 })
|
|
63
|
+
})]
|
|
64
|
+
}, val);
|
|
65
|
+
})]
|
|
66
|
+
}), /* @__PURE__ */ jsx(ChevronDown, {
|
|
67
|
+
size: 16,
|
|
68
|
+
className: `shrink-0 text-login-200 transition-transform duration-150 ${open ? "rotate-180" : ""}`
|
|
69
|
+
})]
|
|
70
|
+
}),
|
|
71
|
+
open && options.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
72
|
+
className: "\n absolute z-50 mt-1 w-full max-h-60 overflow-auto\n rounded-md border border-login-500/50 bg-login-800 shadow-lg\n ",
|
|
73
|
+
children: options.map((option) => {
|
|
74
|
+
const selected = value.includes(option.value);
|
|
75
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
76
|
+
onClick: () => toggleOption(option.value),
|
|
77
|
+
className: `
|
|
78
|
+
flex cursor-pointer items-center justify-between px-3 py-2 text-sm
|
|
79
|
+
hover:bg-login-700 transition-colors select-none
|
|
80
|
+
${selected ? "text-login-50" : "text-login-100"}
|
|
81
|
+
`,
|
|
82
|
+
children: [/* @__PURE__ */ jsx("span", { children: option.label }), selected && /* @__PURE__ */ jsx(Check, {
|
|
83
|
+
size: 14,
|
|
84
|
+
className: "text-login shrink-0"
|
|
85
|
+
})]
|
|
86
|
+
}, option.value);
|
|
87
|
+
})
|
|
88
|
+
}),
|
|
89
|
+
/* @__PURE__ */ jsx("input", {
|
|
90
|
+
type: "hidden",
|
|
91
|
+
name,
|
|
92
|
+
value: value.join(",")
|
|
93
|
+
})
|
|
94
|
+
]
|
|
95
|
+
})
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
//#endregion
|
|
99
|
+
export { MultiSelect as default };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/components/inputs/radio.d.ts
|
|
2
|
+
type RadioOption = {
|
|
3
|
+
label: string;
|
|
4
|
+
value: string | number;
|
|
5
|
+
};
|
|
6
|
+
type RadioProps = Omit<React.ComponentProps<'input'>, 'name' | 'onChange' | 'value'> & {
|
|
7
|
+
name: string;
|
|
8
|
+
label?: string;
|
|
9
|
+
error?: string;
|
|
10
|
+
info?: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
className?: string;
|
|
13
|
+
options: RadioOption[];
|
|
14
|
+
value?: string | number | null;
|
|
15
|
+
onChange?: (value: string | number) => void;
|
|
16
|
+
textSize?: 'sm' | 'md';
|
|
17
|
+
};
|
|
18
|
+
declare function Radio(props: RadioProps): import("react").JSX.Element;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { RadioOption, RadioProps, Radio as default };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import InputLabel from "./shared/inputLabel.js";
|
|
3
|
+
import FieldWrapper from "./shared/fieldWrapper.js";
|
|
4
|
+
import "./shared/index.js";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
//#region src/components/inputs/radio.tsx
|
|
7
|
+
function Radio(props) {
|
|
8
|
+
const { options, onChange, value, label, description, error, info, name, className, textSize = "sm", ...rest } = props;
|
|
9
|
+
return /* @__PURE__ */ jsx(FieldWrapper, {
|
|
10
|
+
label,
|
|
11
|
+
name,
|
|
12
|
+
required: rest.required,
|
|
13
|
+
info,
|
|
14
|
+
description,
|
|
15
|
+
error,
|
|
16
|
+
textSize,
|
|
17
|
+
className,
|
|
18
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
19
|
+
className: "flex flex-col gap-2",
|
|
20
|
+
children: options.map((option) => /* @__PURE__ */ jsx(RadioItem, {
|
|
21
|
+
name,
|
|
22
|
+
value: option.value,
|
|
23
|
+
label: option.label,
|
|
24
|
+
checked: value === option.value,
|
|
25
|
+
disabled: rest.disabled,
|
|
26
|
+
onChange: () => {
|
|
27
|
+
if (onChange) onChange(option.value);
|
|
28
|
+
},
|
|
29
|
+
className: "mb-0"
|
|
30
|
+
}, option.value))
|
|
31
|
+
})
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function RadioItem(props) {
|
|
35
|
+
const { name, label, error, ...inputProps } = props;
|
|
36
|
+
const { value } = inputProps;
|
|
37
|
+
const id = `${name}-${value}`;
|
|
38
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
39
|
+
className: "flex items-center gap-2",
|
|
40
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
41
|
+
className: "relative w-5 h-5 shrink-0",
|
|
42
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
43
|
+
...inputProps,
|
|
44
|
+
id,
|
|
45
|
+
name,
|
|
46
|
+
type: "radio",
|
|
47
|
+
className: `
|
|
48
|
+
peer appearance-none rounded-full border border-login-500 bg-login-500/50
|
|
49
|
+
checked:bg-login checked:border-login
|
|
50
|
+
focus:outline-none focus:ring-1 focus:ring-login/30
|
|
51
|
+
disabled:opacity-40 disabled:cursor-not-allowed
|
|
52
|
+
cursor-pointer transition-all duration-150
|
|
53
|
+
w-5 h-5 absolute inset-0
|
|
54
|
+
${error ? "border-red-500/70" : ""}
|
|
55
|
+
`
|
|
56
|
+
}), /* @__PURE__ */ jsx("div", { className: `
|
|
57
|
+
absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2
|
|
58
|
+
w-2 h-2 rounded-full bg-white pointer-events-none opacity-0
|
|
59
|
+
peer-checked:opacity-100 transition-opacity duration-200
|
|
60
|
+
` })]
|
|
61
|
+
}), label && /* @__PURE__ */ jsx(InputLabel, {
|
|
62
|
+
label,
|
|
63
|
+
name,
|
|
64
|
+
disabled: inputProps.disabled,
|
|
65
|
+
className: "select-none cursor-pointer"
|
|
66
|
+
})]
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
//#endregion
|
|
70
|
+
export { Radio as default };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/components/inputs/range.d.ts
|
|
2
|
+
type RangeProps = Omit<React.ComponentProps<'input'>, 'name'> & {
|
|
3
|
+
name: string;
|
|
4
|
+
label?: string;
|
|
5
|
+
error?: string;
|
|
6
|
+
className?: string;
|
|
7
|
+
info?: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
showValue?: boolean;
|
|
10
|
+
textSize?: 'sm' | 'md';
|
|
11
|
+
};
|
|
12
|
+
declare function Range(props: RangeProps): import("react").JSX.Element;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { RangeProps, Range as default };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import FieldWrapper from "./shared/fieldWrapper.js";
|
|
3
|
+
import "./shared/index.js";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region src/components/inputs/range.tsx
|
|
6
|
+
function Range(props) {
|
|
7
|
+
const { name, label, error, className, info, description, showValue = true, textSize = "sm", ...inputProps } = props;
|
|
8
|
+
const { min = 0, max = 100, step = 1, value, defaultValue, onChange, ...restInputProps } = inputProps;
|
|
9
|
+
const displayValue = value ?? defaultValue ?? 0;
|
|
10
|
+
return /* @__PURE__ */ jsx(FieldWrapper, {
|
|
11
|
+
label,
|
|
12
|
+
name,
|
|
13
|
+
required: restInputProps.required,
|
|
14
|
+
info,
|
|
15
|
+
description,
|
|
16
|
+
error,
|
|
17
|
+
textSize,
|
|
18
|
+
className,
|
|
19
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
20
|
+
className: "flex items-center gap-4",
|
|
21
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
22
|
+
...restInputProps,
|
|
23
|
+
id: name,
|
|
24
|
+
name,
|
|
25
|
+
type: "range",
|
|
26
|
+
min,
|
|
27
|
+
max,
|
|
28
|
+
step,
|
|
29
|
+
...onChange ? {
|
|
30
|
+
value,
|
|
31
|
+
onChange
|
|
32
|
+
} : { defaultValue: value ?? defaultValue ?? 0 },
|
|
33
|
+
title: label,
|
|
34
|
+
"aria-invalid": !!error,
|
|
35
|
+
"aria-describedby": error ? `${name}-error` : void 0,
|
|
36
|
+
className: `
|
|
37
|
+
flex-1 h-2 bg-login-500 rounded-lg appearance-none cursor-pointer
|
|
38
|
+
accent-login
|
|
39
|
+
[&::-webkit-slider-thumb]:appearance-none
|
|
40
|
+
[&::-webkit-slider-thumb]:w-4
|
|
41
|
+
[&::-webkit-slider-thumb]:h-4
|
|
42
|
+
[&::-webkit-slider-thumb]:rounded-full
|
|
43
|
+
[&::-webkit-slider-thumb]:bg-login
|
|
44
|
+
[&::-moz-range-thumb]:w-4
|
|
45
|
+
[&::-moz-range-thumb]:h-4
|
|
46
|
+
[&::-moz-range-thumb]:rounded-full
|
|
47
|
+
[&::-moz-range-thumb]:bg-login
|
|
48
|
+
[&::-moz-range-thumb]:border-none
|
|
49
|
+
disabled:opacity-50 disabled:cursor-not-allowed
|
|
50
|
+
${error ? "accent-red-500" : ""}
|
|
51
|
+
`
|
|
52
|
+
}), showValue && /* @__PURE__ */ jsx("span", {
|
|
53
|
+
className: "text-login-text text-sm font-medium min-w-10 text-right",
|
|
54
|
+
children: displayValue
|
|
55
|
+
})]
|
|
56
|
+
})
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
//#endregion
|
|
60
|
+
export { Range as default };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/components/inputs/searchInput.d.ts
|
|
2
|
+
interface SearchInputProps {
|
|
3
|
+
placeholder?: string;
|
|
4
|
+
variant?: 'default' | 'minimal';
|
|
5
|
+
}
|
|
6
|
+
declare function SearchInput({
|
|
7
|
+
placeholder,
|
|
8
|
+
variant
|
|
9
|
+
}: SearchInputProps): import("react").JSX.Element;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { SearchInput as default };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import Input from "./input.js";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { Search } from "lucide-react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { usePathname, useRouter, useSearchParams } from "next/navigation.js";
|
|
7
|
+
//#region src/components/inputs/searchInput.tsx
|
|
8
|
+
function SearchInput({ placeholder = "Search...", variant = "default" }) {
|
|
9
|
+
const router = useRouter();
|
|
10
|
+
const pathname = usePathname();
|
|
11
|
+
const searchParams = useSearchParams();
|
|
12
|
+
const [searchValue, setSearchValue] = useState(searchParams.get("q") || "");
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
setSearchValue(searchParams.get("q") || "");
|
|
15
|
+
}, [searchParams]);
|
|
16
|
+
function handleSearch(value) {
|
|
17
|
+
setSearchValue(value);
|
|
18
|
+
const params = new URLSearchParams(searchParams.toString());
|
|
19
|
+
if (value.trim()) params.set("q", value.trim());
|
|
20
|
+
else params.delete("q");
|
|
21
|
+
params.delete("page");
|
|
22
|
+
router.push(`${pathname}?${params.toString()}`);
|
|
23
|
+
}
|
|
24
|
+
function handleKeyDown(e) {
|
|
25
|
+
if (e.key === "Enter") handleSearch(searchValue);
|
|
26
|
+
}
|
|
27
|
+
function handleChange(e) {
|
|
28
|
+
setSearchValue(e.target.value);
|
|
29
|
+
}
|
|
30
|
+
if (variant === "minimal") return /* @__PURE__ */ jsxs("div", {
|
|
31
|
+
className: "relative",
|
|
32
|
+
children: [/* @__PURE__ */ jsx(Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 h-5 w-5" }), /* @__PURE__ */ jsx("input", {
|
|
33
|
+
type: "text",
|
|
34
|
+
value: searchValue,
|
|
35
|
+
onChange: (e) => setSearchValue(e.target.value),
|
|
36
|
+
onKeyDown: handleKeyDown,
|
|
37
|
+
onBlur: () => handleSearch(searchValue),
|
|
38
|
+
placeholder,
|
|
39
|
+
className: "pl-10 pr-4 py-2 border-b outline-none w-64"
|
|
40
|
+
})]
|
|
41
|
+
});
|
|
42
|
+
else return /* @__PURE__ */ jsx("div", {
|
|
43
|
+
className: "w-fit min-w-48",
|
|
44
|
+
children: /* @__PURE__ */ jsx(Input, {
|
|
45
|
+
name: "search",
|
|
46
|
+
icon: /* @__PURE__ */ jsx(Search, { className: "w-5 h-5" }),
|
|
47
|
+
value: searchValue,
|
|
48
|
+
onChange: handleChange,
|
|
49
|
+
onKeyDown: handleKeyDown,
|
|
50
|
+
onBlur: () => handleSearch(searchValue),
|
|
51
|
+
placeholder
|
|
52
|
+
})
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
56
|
+
export { SearchInput as default };
|