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.
Files changed (162) hide show
  1. package/dist/components/alert/alert.d.ts +15 -0
  2. package/dist/components/alert/alert.js +29 -0
  3. package/dist/components/badge/badge.d.ts +16 -0
  4. package/dist/components/badge/badge.js +26 -0
  5. package/dist/components/buttons/button.d.ts +25 -0
  6. package/dist/components/buttons/button.js +44 -0
  7. package/dist/components/code/code.d.ts +23 -0
  8. package/dist/components/code/code.js +39 -0
  9. package/dist/components/confirm/confirmPopup.d.ts +23 -0
  10. package/dist/components/confirm/confirmPopup.js +52 -0
  11. package/dist/components/container/accordion.d.ts +25 -0
  12. package/dist/components/container/accordion.js +41 -0
  13. package/dist/components/container/card.d.ts +13 -0
  14. package/dist/components/container/card.js +10 -0
  15. package/dist/components/container/expandableCard.d.ts +32 -0
  16. package/dist/components/container/expandableCard.js +70 -0
  17. package/dist/components/container/glassCard.d.ts +13 -0
  18. package/dist/components/container/glassCard.js +10 -0
  19. package/dist/components/container/highlight.d.ts +10 -0
  20. package/dist/components/container/highlight.js +10 -0
  21. package/dist/components/container/iconBubble.d.ts +25 -0
  22. package/dist/components/container/iconBubble.js +21 -0
  23. package/dist/components/container/leftBarPanel.d.ts +15 -0
  24. package/dist/components/container/leftBarPanel.js +10 -0
  25. package/dist/components/container/page.d.ts +15 -0
  26. package/dist/components/container/page.js +16 -0
  27. package/dist/components/container/pulseDot.d.ts +12 -0
  28. package/dist/components/container/pulseDot.js +23 -0
  29. package/dist/components/container/statCard.d.ts +18 -0
  30. package/dist/components/container/statCard.js +25 -0
  31. package/dist/components/container/tabs.d.ts +35 -0
  32. package/dist/components/container/tabs.js +36 -0
  33. package/dist/components/empty/emptyState.d.ts +19 -0
  34. package/dist/components/empty/emptyState.js +27 -0
  35. package/dist/components/footer/footer.d.ts +49 -0
  36. package/dist/components/footer/footer.js +109 -0
  37. package/dist/components/footer/loginContent.d.ts +18 -0
  38. package/dist/components/footer/loginContent.js +138 -0
  39. package/dist/components/inputs/checkbox.d.ts +20 -0
  40. package/dist/components/inputs/checkbox.js +76 -0
  41. package/dist/components/inputs/fileInput.d.ts +19 -0
  42. package/dist/components/inputs/fileInput.js +108 -0
  43. package/dist/components/inputs/input.d.ts +16 -0
  44. package/dist/components/inputs/input.js +157 -0
  45. package/dist/components/inputs/multiSelect.d.ts +37 -0
  46. package/dist/components/inputs/multiSelect.js +99 -0
  47. package/dist/components/inputs/radio.d.ts +20 -0
  48. package/dist/components/inputs/radio.js +70 -0
  49. package/dist/components/inputs/range.d.ts +14 -0
  50. package/dist/components/inputs/range.js +60 -0
  51. package/dist/components/inputs/searchInput.d.ts +11 -0
  52. package/dist/components/inputs/searchInput.js +56 -0
  53. package/dist/components/inputs/select.d.ts +42 -0
  54. package/dist/components/inputs/select.js +164 -0
  55. package/dist/components/inputs/shared/colorPickerPopup.js +293 -0
  56. package/dist/components/inputs/shared/dateTimePickerPopup.js +225 -0
  57. package/dist/components/inputs/shared/fieldWrapper.js +33 -0
  58. package/dist/components/inputs/shared/index.js +6 -0
  59. package/dist/components/inputs/shared/inputError.js +17 -0
  60. package/dist/components/inputs/shared/inputInfo.js +13 -0
  61. package/dist/components/inputs/shared/inputLabel.js +19 -0
  62. package/dist/components/inputs/switch.d.ts +14 -0
  63. package/dist/components/inputs/switch.js +37 -0
  64. package/dist/components/inputs/tagInput.d.ts +31 -0
  65. package/dist/components/inputs/tagInput.js +72 -0
  66. package/dist/components/inputs/textarea.d.ts +14 -0
  67. package/dist/components/inputs/textarea.js +76 -0
  68. package/dist/components/inputs/toggle.d.ts +21 -0
  69. package/dist/components/inputs/toggle.js +33 -0
  70. package/dist/components/login/loginPage.d.ts +15 -0
  71. package/dist/components/login/loginPage.js +80 -0
  72. package/dist/components/logo/logo.d.ts +9 -0
  73. package/dist/components/logo/logo.js +138 -0
  74. package/dist/components/logo/logoSmall.d.ts +4 -0
  75. package/dist/components/logo/logoSmall.js +56 -0
  76. package/dist/components/markdownrender/markdownRender.d.ts +16 -0
  77. package/dist/components/markdownrender/markdownRender.js +59 -0
  78. package/dist/components/modal/modal.d.ts +22 -0
  79. package/dist/components/modal/modal.js +59 -0
  80. package/dist/components/navbar/bubble.js +36 -0
  81. package/dist/components/navbar/navbar.d.ts +50 -0
  82. package/dist/components/navbar/navbar.js +99 -0
  83. package/dist/components/navbar/navbarDropdown.d.ts +15 -0
  84. package/dist/components/navbar/navbarDropdown.js +63 -0
  85. package/dist/components/navbar/navbarItem.d.ts +23 -0
  86. package/dist/components/navbar/navbarItem.js +38 -0
  87. package/dist/components/sidebar/sidebar.d.ts +34 -0
  88. package/dist/components/sidebar/sidebar.js +135 -0
  89. package/dist/components/spinner/spinner.d.ts +11 -0
  90. package/dist/components/spinner/spinner.js +16 -0
  91. package/dist/components/table/body.js +253 -0
  92. package/dist/components/table/constants.js +58 -0
  93. package/dist/components/table/empty.js +24 -0
  94. package/dist/components/table/format.js +39 -0
  95. package/dist/components/table/header.js +109 -0
  96. package/dist/components/table/menu.d.ts +18 -0
  97. package/dist/components/table/menu.js +76 -0
  98. package/dist/components/table/pagination.d.ts +14 -0
  99. package/dist/components/table/pagination.js +130 -0
  100. package/dist/components/table/skeleton.js +39 -0
  101. package/dist/components/table/table.d.ts +7 -0
  102. package/dist/components/table/table.js +213 -0
  103. package/dist/components/table/types.d.ts +52 -0
  104. package/dist/components/table/utils.js +9 -0
  105. package/dist/components/toast/toastItem.js +61 -0
  106. package/dist/components/toast/toaster.d.ts +13 -0
  107. package/dist/components/toast/toaster.js +117 -0
  108. package/dist/components/toggle/language.d.ts +10 -0
  109. package/dist/components/toggle/language.js +34 -0
  110. package/dist/components/toggle/theme.d.ts +8 -0
  111. package/dist/components/toggle/theme.js +135 -0
  112. package/dist/components/version/version.d.ts +13 -0
  113. package/dist/components/version/version.js +19 -0
  114. package/dist/components/vulnerability/constants.d.ts +4 -0
  115. package/dist/components/vulnerability/constants.js +17 -0
  116. package/dist/components/vulnerability/severityPill.d.ts +15 -0
  117. package/dist/components/vulnerability/severityPill.js +20 -0
  118. package/dist/{style.css → globals.css} +155 -226
  119. package/dist/hooks/useClickOutside.d.ts +6 -0
  120. package/dist/{useClickOutside-Cmp-RsP3.js → hooks/useClickOutside.js} +1 -1
  121. package/dist/hooks/useDarkMode.d.ts +4 -0
  122. package/dist/hooks/useDarkMode.js +19 -0
  123. package/dist/hooks/useVisibility.d.ts +7 -0
  124. package/dist/hooks/useVisibility.js +25 -0
  125. package/dist/icons/icons.d.ts +420 -0
  126. package/dist/{icons-lZYQ6Vlr.js → icons/icons.js} +1 -1
  127. package/dist/src/components/index.d.ts +51 -901
  128. package/dist/src/components/index.js +49 -4160
  129. package/dist/src/hooks/index.d.ts +3 -14
  130. package/dist/src/hooks/index.js +3 -42
  131. package/dist/src/icons/index.d.ts +1 -419
  132. package/dist/src/icons/index.js +1 -1
  133. package/dist/src/styles/index.js +1 -1
  134. package/dist/src/utils/index.d.ts +5 -37
  135. package/dist/src/utils/index.js +5 -124
  136. package/dist/utils/auth/callback.d.ts +14 -0
  137. package/dist/utils/auth/callback.js +53 -0
  138. package/dist/utils/auth/getDomain.js +6 -0
  139. package/dist/utils/auth/login.d.ts +12 -0
  140. package/dist/utils/auth/login.js +17 -0
  141. package/dist/utils/auth/logout.d.ts +10 -0
  142. package/dist/utils/auth/logout.js +20 -0
  143. package/dist/utils/auth/token.d.ts +10 -0
  144. package/dist/utils/auth/token.js +30 -0
  145. package/dist/utils/logoConsoleOutput/logoConsoleOutput.d.ts +4 -0
  146. package/dist/utils/logoConsoleOutput/logoConsoleOutput.js +11 -0
  147. package/package.json +1 -1
  148. package/src/components/buttons/button.tsx +2 -0
  149. package/src/components/footer/footer.tsx +65 -28
  150. package/src/components/index.ts +0 -1
  151. package/src/components/inputs/checkbox.tsx +2 -0
  152. package/src/components/inputs/input.tsx +2 -0
  153. package/src/components/inputs/radio.tsx +2 -0
  154. package/src/components/inputs/range.tsx +2 -0
  155. package/src/components/inputs/shared/colorPickerPopup.tsx +2 -0
  156. package/src/components/inputs/shared/dateTimePickerPopup.tsx +2 -0
  157. package/src/components/inputs/textarea.tsx +2 -0
  158. package/src/components/inputs/toggle.tsx +2 -0
  159. package/src/components/sidebar/sidebar.tsx +37 -10
  160. package/src/components/toast/toastItem.tsx +2 -0
  161. package/src/globals.css +6 -1
  162. 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 };