@pk-design/react-tailwind 1.0.2
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/LICENSE +21 -0
- package/README.md +11 -0
- package/dist/react-tailwind.cjs.js +938 -0
- package/dist/react-tailwind.cjs.js.map +1 -0
- package/dist/react-tailwind.css +2 -0
- package/dist/react-tailwind.css.map +1 -0
- package/dist/react-tailwind.es.js +872 -0
- package/dist/react-tailwind.es.js.map +1 -0
- package/dist/types/components/Alert/index.d.ts +35 -0
- package/dist/types/components/Badge/index.d.ts +24 -0
- package/dist/types/components/Banner/index.d.ts +16 -0
- package/dist/types/components/BodyText/index.d.ts +28 -0
- package/dist/types/components/Breadcrumb/index.d.ts +30 -0
- package/dist/types/components/Button/Button.d.ts +3 -0
- package/dist/types/components/Button/index.d.ts +2 -0
- package/dist/types/components/Button/type.d.ts +58 -0
- package/dist/types/components/Card/index.d.ts +9 -0
- package/dist/types/components/Checkbox/index.d.ts +13 -0
- package/dist/types/components/CheckboxGroup/index.d.ts +56 -0
- package/dist/types/components/DetailedInformation/index.d.ts +63 -0
- package/dist/types/components/Dot/index.d.ts +4 -0
- package/dist/types/components/Drawer/Drawer.d.ts +3 -0
- package/dist/types/components/Drawer/index.d.ts +2 -0
- package/dist/types/components/Drawer/type.d.ts +71 -0
- package/dist/types/components/Dropdown/index.d.ts +62 -0
- package/dist/types/components/EmptyState/index.d.ts +8 -0
- package/dist/types/components/HeadingText/index.d.ts +12 -0
- package/dist/types/components/Input/index.d.ts +13 -0
- package/dist/types/components/Label/index.d.ts +5 -0
- package/dist/types/components/Loader/index.d.ts +9 -0
- package/dist/types/components/Pagination/Pagination.d.ts +33 -0
- package/dist/types/components/Pagination/index.d.ts +2 -0
- package/dist/types/components/Pagination/usePagination.d.ts +7 -0
- package/dist/types/components/PasswordInput/index.d.ts +6 -0
- package/dist/types/components/RadioButton/index.d.ts +7 -0
- package/dist/types/components/RadioButtonGroup/index.d.ts +19 -0
- package/dist/types/components/RadioSwtich/index.d.ts +14 -0
- package/dist/types/components/RangeInput/index.d.ts +10 -0
- package/dist/types/components/SelectBox/index.d.ts +40 -0
- package/dist/types/components/Table/index.d.ts +48 -0
- package/dist/types/components/Tabs/index.d.ts +2 -0
- package/dist/types/components/Tag/index.d.ts +12 -0
- package/dist/types/components/TextContent/index.d.ts +10 -0
- package/dist/types/components/Textarea/index.d.ts +7 -0
- package/dist/types/components/Toast/Toast.d.ts +9 -0
- package/dist/types/components/Toast/ToastProvider.d.ts +16 -0
- package/dist/types/components/Toast/index.d.ts +2 -0
- package/dist/types/components/common-type.d.ts +31 -0
- package/dist/types/components/hooks/use-debounce.d.ts +1 -0
- package/dist/types/index.d.ts +36 -0
- package/dist/types/utils/build-classname.d.ts +1 -0
- package/dist/types/utils/is-array.d.ts +5 -0
- package/dist/types/utils/is-empty.d.ts +6 -0
- package/package.json +89 -0
|
@@ -0,0 +1,872 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
|
|
2
|
+
import { twMerge } from 'tailwind-merge';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import React__default, { forwardRef, useState, useEffect, Fragment, isValidElement, useRef, createContext, useContext } from 'react';
|
|
5
|
+
import { Dialog, DialogBackdrop, DialogPanel, DialogTitle, Menu, MenuButton, MenuItems, MenuItem, RadioGroup, Radio, Combobox, ComboboxInput, ComboboxButton, ComboboxOptions, ComboboxOption, TabGroup, TabList, Tab, TabPanels, TabPanel, Transition } from '@headlessui/react';
|
|
6
|
+
|
|
7
|
+
const buildClassName = (...classes) => twMerge(classes.filter(Boolean));
|
|
8
|
+
|
|
9
|
+
var _path$d, _path2;
|
|
10
|
+
function _extends$d() { return _extends$d = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$d.apply(null, arguments); }
|
|
11
|
+
var SvgBadgeCheck = function SvgBadgeCheck(props) {
|
|
12
|
+
return /*#__PURE__*/React.createElement("svg", _extends$d({
|
|
13
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
14
|
+
width: 24,
|
|
15
|
+
height: 24,
|
|
16
|
+
fill: "none",
|
|
17
|
+
stroke: "currentColor",
|
|
18
|
+
strokeLinecap: "round",
|
|
19
|
+
strokeLinejoin: "round",
|
|
20
|
+
strokeWidth: 2,
|
|
21
|
+
className: "lucide lucide-badge-check-icon lucide-badge-check",
|
|
22
|
+
viewBox: "0 0 24 24"
|
|
23
|
+
}, props), _path$d || (_path$d = /*#__PURE__*/React.createElement("path", {
|
|
24
|
+
d: "M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76"
|
|
25
|
+
})), _path2 || (_path2 = /*#__PURE__*/React.createElement("path", {
|
|
26
|
+
d: "m9 12 2 2 4-4"
|
|
27
|
+
})));
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
var _circle$4, _path$c;
|
|
31
|
+
function _extends$c() { return _extends$c = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$c.apply(null, arguments); }
|
|
32
|
+
var SvgCircleX = function SvgCircleX(props) {
|
|
33
|
+
return /*#__PURE__*/React.createElement("svg", _extends$c({
|
|
34
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
35
|
+
width: 24,
|
|
36
|
+
height: 24,
|
|
37
|
+
fill: "none",
|
|
38
|
+
stroke: "currentColor",
|
|
39
|
+
strokeLinecap: "round",
|
|
40
|
+
strokeLinejoin: "round",
|
|
41
|
+
strokeWidth: 2,
|
|
42
|
+
className: "lucide lucide-circle-x-icon lucide-circle-x",
|
|
43
|
+
viewBox: "0 0 24 24"
|
|
44
|
+
}, props), _circle$4 || (_circle$4 = /*#__PURE__*/React.createElement("circle", {
|
|
45
|
+
cx: 12,
|
|
46
|
+
cy: 12,
|
|
47
|
+
r: 10
|
|
48
|
+
})), _path$c || (_path$c = /*#__PURE__*/React.createElement("path", {
|
|
49
|
+
d: "m15 9-6 6M9 9l6 6"
|
|
50
|
+
})));
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
var _circle$3, _path$b;
|
|
54
|
+
function _extends$b() { return _extends$b = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$b.apply(null, arguments); }
|
|
55
|
+
var SvgCircleAlert = function SvgCircleAlert(props) {
|
|
56
|
+
return /*#__PURE__*/React.createElement("svg", _extends$b({
|
|
57
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
58
|
+
width: 24,
|
|
59
|
+
height: 24,
|
|
60
|
+
fill: "none",
|
|
61
|
+
stroke: "currentColor",
|
|
62
|
+
strokeLinecap: "round",
|
|
63
|
+
strokeLinejoin: "round",
|
|
64
|
+
strokeWidth: 2,
|
|
65
|
+
className: "lucide lucide-circle-alert-icon lucide-circle-alert",
|
|
66
|
+
viewBox: "0 0 24 24"
|
|
67
|
+
}, props), _circle$3 || (_circle$3 = /*#__PURE__*/React.createElement("circle", {
|
|
68
|
+
cx: 12,
|
|
69
|
+
cy: 12,
|
|
70
|
+
r: 10
|
|
71
|
+
})), _path$b || (_path$b = /*#__PURE__*/React.createElement("path", {
|
|
72
|
+
d: "M12 8v4M12 16h.01"
|
|
73
|
+
})));
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
var _circle$2, _path$a;
|
|
77
|
+
function _extends$a() { return _extends$a = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$a.apply(null, arguments); }
|
|
78
|
+
var SvgInfo = function SvgInfo(props) {
|
|
79
|
+
return /*#__PURE__*/React.createElement("svg", _extends$a({
|
|
80
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
81
|
+
width: 24,
|
|
82
|
+
height: 24,
|
|
83
|
+
fill: "none",
|
|
84
|
+
stroke: "currentColor",
|
|
85
|
+
strokeLinecap: "round",
|
|
86
|
+
strokeLinejoin: "round",
|
|
87
|
+
strokeWidth: 2,
|
|
88
|
+
className: "lucide lucide-info-icon lucide-info",
|
|
89
|
+
viewBox: "0 0 24 24"
|
|
90
|
+
}, props), _circle$2 || (_circle$2 = /*#__PURE__*/React.createElement("circle", {
|
|
91
|
+
cx: 12,
|
|
92
|
+
cy: 12,
|
|
93
|
+
r: 10
|
|
94
|
+
})), _path$a || (_path$a = /*#__PURE__*/React.createElement("path", {
|
|
95
|
+
d: "M12 16v-4M12 8h.01"
|
|
96
|
+
})));
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
var _path$9;
|
|
100
|
+
function _extends$9() { return _extends$9 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$9.apply(null, arguments); }
|
|
101
|
+
var SvgX = function SvgX(props) {
|
|
102
|
+
return /*#__PURE__*/React.createElement("svg", _extends$9({
|
|
103
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
104
|
+
width: 24,
|
|
105
|
+
height: 24,
|
|
106
|
+
fill: "none",
|
|
107
|
+
stroke: "currentColor",
|
|
108
|
+
strokeLinecap: "round",
|
|
109
|
+
strokeLinejoin: "round",
|
|
110
|
+
strokeWidth: 2,
|
|
111
|
+
className: "lucide lucide-x-icon lucide-x",
|
|
112
|
+
viewBox: "0 0 24 24"
|
|
113
|
+
}, props), _path$9 || (_path$9 = /*#__PURE__*/React.createElement("path", {
|
|
114
|
+
d: "M18 6 6 18M6 6l12 12"
|
|
115
|
+
})));
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const loaderSizeMap = {
|
|
119
|
+
xs: 'size-4',
|
|
120
|
+
sm: 'size-6',
|
|
121
|
+
md: 'size-8',
|
|
122
|
+
lg: 'size-10',
|
|
123
|
+
};
|
|
124
|
+
const Loader = ({ className = 'text-blue-600', size = 'md' }) => {
|
|
125
|
+
return (jsx("svg", { className: buildClassName(loaderSizeMap[size], className, 'spinner'), viewBox: "0 0 50 50", children: jsx("circle", { className: "path", cx: "25", cy: "25", r: "20", fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeWidth: "5" }) }));
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const TextContent = forwardRef((props, ref) => {
|
|
129
|
+
const { as = 'span', xsmall = false, small = false, strong = false, muted = false, error = false, className, ...rest } = props;
|
|
130
|
+
return React__default.createElement(as, {
|
|
131
|
+
ref,
|
|
132
|
+
className: buildClassName(xsmall && 'text-xs/5', small && 'text-sm/6', strong && 'font-semibold', muted && 'text-gray-500', error && 'text-red-500', className),
|
|
133
|
+
...rest,
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const THEMED_BTN_CLASS = {
|
|
138
|
+
primary: {
|
|
139
|
+
default: 'text-white bg-blue-600 hover:bg-blue-700 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-blue-600 disabled:bg-blue-400 dark:disabled:bg-blue-500',
|
|
140
|
+
outlined: 'text-blue-600 hover:text-white border border-blue-600 hover:bg-blue-600 dark:border-blue-500 dark:text-blue-500 dark:hover:text-white dark:hover:bg-blue-500 focus:outline-blue-600 disabled:text-blue-400 disabled:border-blue-400',
|
|
141
|
+
plain: 'text-blue-600 hover:bg-black/5 dark:text-blue-400 dark:hover:bg-gray-700 focus:outline-blue-600 disabled:text-blue-400',
|
|
142
|
+
},
|
|
143
|
+
danger: {
|
|
144
|
+
default: 'text-white bg-red-600 hover:bg-red-700 dark:bg-red-600 dark:hover:bg-red-700 focus:outline-red-600 disabled:bg-red-400 dark:disabled:bg-red-500',
|
|
145
|
+
outlined: 'text-red-600 hover:text-white border border-red-600 hover:bg-red-600 dark:border-red-500 dark:text-red-500 dark:hover:text-white dark:hover:bg-red-500 focus:outline-red-600 disabled:text-red-400 disabled:border-red-400',
|
|
146
|
+
plain: 'text-red-600 hover:bg-black/5 dark:text-red-400 dark:hover:bg-gray-700 focus:outline-red-600 disabled:text-red-400',
|
|
147
|
+
},
|
|
148
|
+
secondary: {
|
|
149
|
+
default: 'text-gray-700 bg-white border border-gray-300 hover:bg-gray-100 dark:bg-gray-800 dark:text-white dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-600 focus:outline-blue-600 disabled:bg-gray-200 dark:disabled:bg-gray-700',
|
|
150
|
+
outlined: 'text-gray-700 hover:text-white border border-gray-500 hover:bg-gray-700 dark:border-gray-500 dark:text-gray-200 dark:hover:text-white dark:hover:bg-gray-600 focus:outline-blue-600 disabled:text-gray-400 disabled:border-gray-400',
|
|
151
|
+
plain: 'text-gray-700 hover:bg-black/5 dark:text-gray-200 dark:hover:bg-gray-700 focus:outline-blue-600 disabled:text-gray-400',
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
const getBtnSizeClasses = (size, iconOnly = false) => {
|
|
155
|
+
switch (size) {
|
|
156
|
+
case 'xs':
|
|
157
|
+
return `text-xs h-6 ${iconOnly ? 'p-1 rounded-sm' : 'px-2 py-1 rounded-sm gap-1'}`;
|
|
158
|
+
case 'sm':
|
|
159
|
+
return `text-sm h-8 ${iconOnly ? 'p-1.5 rounded' : ' px-3 py-1.5 rounded gap-1.5'}`;
|
|
160
|
+
case 'md':
|
|
161
|
+
return `text-sm h-10 ${iconOnly ? 'p-2 rounded-md' : 'px-4 py-2 rounded-md gap-2'}`;
|
|
162
|
+
case 'lg':
|
|
163
|
+
return `text-base h-12 ${iconOnly ? 'p-2.5 rounded-lg' : 'px-5 py-2.5 rounded-lg gap-2'}`;
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
const Button = forwardRef((props, ref) => {
|
|
167
|
+
const { className = '', children, theme = 'primary', variant = 'default', size = 'md', as: Element = 'button', loading = false, loadingText = '', type = 'button', rounded = false, disabled, iconOnly = false, ...buttonProps } = props;
|
|
168
|
+
return (jsx(Element, { ref: ref, className: buildClassName(THEMED_BTN_CLASS[theme][variant], getBtnSizeClasses(size, iconOnly), 'focus:outline focus:outline-2 focus:outline-offset-2', 'font-medium flex items-center justify-center shrink-0', 'cursor-pointer disabled:cursor-not-allowed disabled:pointer-events-none disabled:opacity-75', 'transition duration-200 ease-in-out', rounded && 'rounded-full', variant === 'default' && 'shadow-xs hover:shadow-none disabled:shadow-none', className), type: type, disabled: disabled || loading, ...buttonProps, children: loading ? (jsxs("span", { className: "flex items-center gap-2", children: [jsx(Loader, { className: "text-white", size: "xs" }), loadingText && jsx(TextContent, { children: loadingText })] })) : (children) }));
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
const AlertTypeIconMap = {
|
|
172
|
+
success: SvgBadgeCheck,
|
|
173
|
+
danger: SvgCircleX,
|
|
174
|
+
warning: SvgCircleAlert,
|
|
175
|
+
info: SvgInfo,
|
|
176
|
+
};
|
|
177
|
+
const TypeClassMap = {
|
|
178
|
+
success: 'bg-green-50 ring-green-600/20 text-green-700',
|
|
179
|
+
danger: 'bg-red-50 ring-red-600/20 text-red-700',
|
|
180
|
+
warning: 'bg-orange-50 ring-orange-600/20 text-orange-700',
|
|
181
|
+
info: 'bg-blue-50 ring-blue-600/20 text-blue-700',
|
|
182
|
+
};
|
|
183
|
+
const Alert = (props) => {
|
|
184
|
+
const { type = 'info', className = '', message, children, removable = false, onRemove = () => { }, ...restProps } = props;
|
|
185
|
+
const Icon = AlertTypeIconMap[type] || SvgInfo;
|
|
186
|
+
return (jsxs("div", { className: buildClassName(className, 'flex items-center justify-between rounded-md p-3 text-sm ring-1 ring-inset gap-2', TypeClassMap[type]), ...restProps, children: [jsxs("span", { className: "inline-flex items-center gap-2", children: [jsx(Icon, { className: "size-5" }), jsx("span", { className: "pr-2 inline-flex items-center", children: message || children })] }), removable && (jsx(Button, { iconOnly: true, size: "xs", variant: "plain", theme: "secondary", className: "hover:bg-black/5 text-gray-600 dark:hover:bg-black/5 dark:text-gray-600", onClick: () => onRemove(), children: jsx(SvgX, { className: "size-4.5" }) }))] }));
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
const ThemeClassMap = {
|
|
190
|
+
success: 'bg-green-50 ring-green-600/20 text-green-700 dark:bg-green-600 dark:text-green-50 dark:ring-green-400/20',
|
|
191
|
+
danger: 'bg-red-50 dark:bg-red-600 text-red-700 dark:text-red-50 ring-red-600/20 dark:ring-red-400/20',
|
|
192
|
+
warning: 'bg-yellow-50 dark:bg-yellow-600 text-yellow-700 dark:text-yellow-50 ring-yellow-600/20 dark:ring-yellow-400/20',
|
|
193
|
+
info: 'bg-blue-50 dark:bg-blue-600 text-blue-700 dark:text-blue-50 ring-blue-600/20 dark:ring-blue-400/20',
|
|
194
|
+
secondary: 'bg-gray-50 dark:bg-gray-600 text-gray-700 dark:text-gray-50 ring-gray-600/20 dark:ring-gray-400/20',
|
|
195
|
+
};
|
|
196
|
+
const Badge = forwardRef((props, ref) => {
|
|
197
|
+
const { theme = 'info', className = '', children, removable = false, rounded = false, onRemove = () => { }, ...restProps } = props;
|
|
198
|
+
return (jsxs("span", { ref: ref, className: buildClassName(className, 'inline-flex items-center pl-3 py-1 text-xs font-medium ring-1 ring-inset', ThemeClassMap[theme], rounded ? 'rounded-full' : 'rounded-md'), ...restProps, children: [jsx("span", { className: "pr-3 inline-flex items-center", children: children }), removable ? (jsx(SvgX, { className: "size-5 px-0.5 mr-1 hover:bg-slate-200 dark:hover:bg-white/10 rounded-sm cursor-pointer", role: "button", onClick: () => onRemove() })) : null] }));
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
var _path$8;
|
|
202
|
+
function _extends$8() { return _extends$8 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$8.apply(null, arguments); }
|
|
203
|
+
var SvgTriangleAlert = function SvgTriangleAlert(props) {
|
|
204
|
+
return /*#__PURE__*/React.createElement("svg", _extends$8({
|
|
205
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
206
|
+
width: 24,
|
|
207
|
+
height: 24,
|
|
208
|
+
fill: "none",
|
|
209
|
+
stroke: "currentColor",
|
|
210
|
+
strokeLinecap: "round",
|
|
211
|
+
strokeLinejoin: "round",
|
|
212
|
+
strokeWidth: 2,
|
|
213
|
+
className: "lucide lucide-triangle-alert-icon lucide-triangle-alert",
|
|
214
|
+
viewBox: "0 0 24 24"
|
|
215
|
+
}, props), _path$8 || (_path$8 = /*#__PURE__*/React.createElement("path", {
|
|
216
|
+
d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3M12 9v4M12 17h.01"
|
|
217
|
+
})));
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
var _circle$1, _path$7;
|
|
221
|
+
function _extends$7() { return _extends$7 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$7.apply(null, arguments); }
|
|
222
|
+
var SvgCircleCheck = function SvgCircleCheck(props) {
|
|
223
|
+
return /*#__PURE__*/React.createElement("svg", _extends$7({
|
|
224
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
225
|
+
width: 24,
|
|
226
|
+
height: 24,
|
|
227
|
+
fill: "none",
|
|
228
|
+
stroke: "currentColor",
|
|
229
|
+
strokeLinecap: "round",
|
|
230
|
+
strokeLinejoin: "round",
|
|
231
|
+
strokeWidth: 2,
|
|
232
|
+
className: "lucide lucide-circle-check-icon lucide-circle-check",
|
|
233
|
+
viewBox: "0 0 24 24"
|
|
234
|
+
}, props), _circle$1 || (_circle$1 = /*#__PURE__*/React.createElement("circle", {
|
|
235
|
+
cx: 12,
|
|
236
|
+
cy: 12,
|
|
237
|
+
r: 10
|
|
238
|
+
})), _path$7 || (_path$7 = /*#__PURE__*/React.createElement("path", {
|
|
239
|
+
d: "m9 12 2 2 4-4"
|
|
240
|
+
})));
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
const sizeMap = {
|
|
244
|
+
5: `size-5`,
|
|
245
|
+
6: `size-6`,
|
|
246
|
+
7: `size-7`,
|
|
247
|
+
8: `size-8`,
|
|
248
|
+
9: `size-9`,
|
|
249
|
+
10: `size-10`,
|
|
250
|
+
};
|
|
251
|
+
const IconMap = {
|
|
252
|
+
info: SvgInfo,
|
|
253
|
+
error: SvgCircleX,
|
|
254
|
+
success: SvgCircleCheck,
|
|
255
|
+
warning: SvgTriangleAlert,
|
|
256
|
+
};
|
|
257
|
+
const Banner = forwardRef((props, ref) => {
|
|
258
|
+
const { type = 'info', iconSize = 5, children } = props;
|
|
259
|
+
const className = buildClassName('text-sm banner rounded-md flex w-full p-3 mb-4 items-center', type === 'info' ? 'bg-blue-50 text-blue-700' : '', type === 'error' ? 'bg-red-50 text-red-700' : '', type === 'success' ? 'bg-green-50 text-green-700' : '', type === 'warning' ? 'bg-orange-50 border border-orange-200 text-orange-700' : '');
|
|
260
|
+
const renderIcon = () => {
|
|
261
|
+
const Icon = IconMap[type];
|
|
262
|
+
return jsx(Icon, { className: buildClassName('ml-1 mr-3', sizeMap[iconSize]) });
|
|
263
|
+
};
|
|
264
|
+
return (jsxs("div", { ref: ref, className: className, children: [renderIcon(), jsx("div", { className: "flex items-center w-full justify-between", children: children })] }));
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
const BodyText = forwardRef((props, ref) => {
|
|
268
|
+
const { as = 'p', small = false, strong = false, muted = false, error = false, inline = false, className, ...rest } = props;
|
|
269
|
+
return React__default.createElement(as, {
|
|
270
|
+
ref: ref,
|
|
271
|
+
className: buildClassName(small && 'text-sm/6', strong && 'font-semibold', muted && 'text-gray-500', error && 'text-red-500', inline && 'inline-flex items-center gap-2', className),
|
|
272
|
+
...rest,
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
var _path$6;
|
|
277
|
+
function _extends$6() { return _extends$6 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$6.apply(null, arguments); }
|
|
278
|
+
var SvgSlash = function SvgSlash(props) {
|
|
279
|
+
return /*#__PURE__*/React.createElement("svg", _extends$6({
|
|
280
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
281
|
+
width: 24,
|
|
282
|
+
height: 24,
|
|
283
|
+
fill: "none",
|
|
284
|
+
stroke: "currentColor",
|
|
285
|
+
strokeLinecap: "round",
|
|
286
|
+
strokeLinejoin: "round",
|
|
287
|
+
strokeWidth: 2,
|
|
288
|
+
className: "lucide lucide-slash-icon lucide-slash",
|
|
289
|
+
viewBox: "0 0 24 24"
|
|
290
|
+
}, props), _path$6 || (_path$6 = /*#__PURE__*/React.createElement("path", {
|
|
291
|
+
d: "M22 2 2 22"
|
|
292
|
+
})));
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const Breadcrumb = ({ items, render }) => {
|
|
296
|
+
const count = items.length;
|
|
297
|
+
const isLast = (index) => index === count - 1;
|
|
298
|
+
return (jsx("div", { className: "flex flex-wrap items-center gap-2", children: items.map((item, index) => (jsxs("span", { className: "inline-flex gap-2 items-center dark:text-white", children: [isLast(index) ? jsx("span", { className: "font-medium", children: item.text }) : render(item), !isLast(index) && jsx(SvgSlash, { className: "size-4" })] }, item.key))) }));
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
const Card = forwardRef(({ className, as = 'div', hoverable = false, bordered = false, noPadding = false, ...rest }, ref) => React__default.createElement(as, {
|
|
302
|
+
ref: ref,
|
|
303
|
+
className: buildClassName('bg-white rounded-md dark:bg-gray-800', noPadding ? '' : 'p-2 md:p-4', hoverable && 'shadow hover:shadow-md transition-shadow duration-200', bordered && 'border border-gray-200 dark:border-gray-700', className),
|
|
304
|
+
...rest,
|
|
305
|
+
}));
|
|
306
|
+
|
|
307
|
+
const Label = forwardRef((props, ref) => {
|
|
308
|
+
const { className, children, ...labelProps } = props;
|
|
309
|
+
return (jsx("label", { ref: ref, ...labelProps, className: buildClassName('block text-sm font-medium text-gray-500 dark:text-gray-400', className), children: children }));
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
const Checkbox = forwardRef((props, ref) => {
|
|
313
|
+
const { type, name, id = name, wrapperClass = '', containerClass = '', label = null, labelClass = '', error = null, disabled = false, className = '', ...checkboxProps } = props;
|
|
314
|
+
return (jsxs("div", { className: buildClassName(wrapperClass), children: [jsxs("div", { className: buildClassName('flex items-center', containerClass), children: [jsxs("label", { className: buildClassName('inline-flex items-center relative', disabled ? 'cursor-not-allowed opacity-70' : 'cursor-pointer'), children: [jsx("input", { ref: ref, ...checkboxProps, id: id, name: name, type: "checkbox", disabled: disabled, className: buildClassName('peer size-4.5 cursor-pointer transition-all appearance-none rounded hover:shadow-md border border-gray-300 checked:bg-blue-600 checked:border-blue-600', 'bg-gray-50 dark:bg-gray-700', 'focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 dark:focus:ring-offset-gray-900') }), jsx("span", { className: "absolute text-white opacity-0 peer-checked:opacity-100 top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2", children: jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-3.25 w-3.25", viewBox: "0 0 20 20", fill: "currentColor", stroke: "currentColor", strokeWidth: "1", children: jsx("path", { fillRule: "evenodd", d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z", clipRule: "evenodd" }) }) })] }), label && (jsx(Label, { htmlFor: id, className: `${disabled ? 'cursor-not-allowed' : 'cursor-pointer'} ml-2 font-normal text-gray-600 ${labelClass}`, children: label }))] }), error && jsx("div", { className: "mt-1 text-red-600 text-sm", children: error })] }));
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
const CheckboxGroup = (props) => {
|
|
318
|
+
const { name, options, label = null, labelClass = '', labelWrapperClass = '', labelHint = null, containerClass = '', value = [], onChange, inline, } = props;
|
|
319
|
+
const [items, setItems] = useState([]);
|
|
320
|
+
useEffect(() => {
|
|
321
|
+
setItems(() => options.map((option) => {
|
|
322
|
+
if (typeof option === 'string') {
|
|
323
|
+
return { label: option, value: option };
|
|
324
|
+
}
|
|
325
|
+
return option;
|
|
326
|
+
}));
|
|
327
|
+
}, [options]);
|
|
328
|
+
return (jsxs("div", { className: buildClassName('mb-3 space-y-3', containerClass), children: [label && (jsxs("div", { className: buildClassName('flex items-center justify-between', labelWrapperClass), children: [jsx(Label, { className: labelClass, children: label }), jsx(BodyText, { muted: true, small: true, children: labelHint })] })), jsx("div", { className: buildClassName('flex gap-3', inline ? 'flex-wrap' : 'flex-col'), children: items.map((item) => (jsx(Checkbox, { label: item.label, value: item.value, checked: value.includes(item.value), name: name, id: item.value, onChange: onChange }, item.value))) })] }));
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
const Title = ({ children, className }) => (jsx("h1", { className: buildClassName('text-3xl font-bold', className), children: children }));
|
|
332
|
+
const SubTitle = ({ children, className }) => (jsx("h2", { className: buildClassName('text-2xl font-semibold', className), children: children }));
|
|
333
|
+
const SubTitle2 = ({ children, className }) => (jsx("h3", { className: buildClassName('text-xl font-semibold', className), children: children }));
|
|
334
|
+
const SubTitle3 = ({ children, className }) => (jsx("h4", { className: buildClassName('text-lg font-medium', className), children: children }));
|
|
335
|
+
const SubTitle4 = ({ children, className }) => (jsx("h5", { className: buildClassName('text-base font-medium', className), children: children }));
|
|
336
|
+
const HeadingText = {
|
|
337
|
+
Title,
|
|
338
|
+
SubTitle,
|
|
339
|
+
SubTitle2,
|
|
340
|
+
SubTitle3,
|
|
341
|
+
SubTitle4,
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
const DetailedInformation = ({ className, title, subTitle, details, compact = false, divider = true, titleClass, detailsClass, }) => {
|
|
345
|
+
const hasTitles = title || subTitle;
|
|
346
|
+
const filteredDetails = details.filter((detail) => !detail.hidden);
|
|
347
|
+
return (jsxs("div", { className: buildClassName('p-2 md:p-4', compact ? 'md:p-2' : '', className), children: [hasTitles && (jsxs("div", { className: "px-4 sm:px-0 pt-2 sm:pt-0 mb-2", children: [title && (jsx(HeadingText.SubTitle2, { className: buildClassName(titleClass), children: title })), subTitle && (jsx("p", { className: "mt-1 max-w-2xl text-sm/6 text-gray-500 dark:text-gray-300", children: subTitle }))] })), filteredDetails.length ? (jsx("div", { className: buildClassName('border-gray-100 dark:border-gray-700', hasTitles && 'border-t', detailsClass), children: jsx("dl", { className: buildClassName(divider && 'divide-y divide-gray-100 dark:divide-gray-700'), children: filteredDetails.map((detail) => (jsxs("div", { className: buildClassName('px-4 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0 items-center', compact ? 'py-1.5' : 'py-2.5'), children: [jsx("dt", { className: "text-sm/6 font-medium text-gray-900 dark:text-gray-100", children: detail.label }), jsx("dd", { className: buildClassName('mt-1 text-sm/6 text-gray-700 dark:text-gray-300 sm:col-span-2 sm:mt-0', detail.contentClass), children: detail.value || '- -' })] }, detail.label))) }) })) : null] }));
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
const Dot = ({ as = 'span', className, ...props }) => React__default.createElement(as, {
|
|
351
|
+
className: buildClassName('inline-block rounded-full bg-gray-500 dark:bg-gray-300', 'w-1 h-1', className),
|
|
352
|
+
...props,
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
var _path$5;
|
|
356
|
+
function _extends$5() { return _extends$5 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$5.apply(null, arguments); }
|
|
357
|
+
var SvgChevronLeft = function SvgChevronLeft(props) {
|
|
358
|
+
return /*#__PURE__*/React.createElement("svg", _extends$5({
|
|
359
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
360
|
+
width: 24,
|
|
361
|
+
height: 24,
|
|
362
|
+
fill: "none",
|
|
363
|
+
stroke: "currentColor",
|
|
364
|
+
strokeLinecap: "round",
|
|
365
|
+
strokeLinejoin: "round",
|
|
366
|
+
strokeWidth: 2,
|
|
367
|
+
className: "lucide lucide-chevron-left-icon lucide-chevron-left",
|
|
368
|
+
viewBox: "0 0 24 24"
|
|
369
|
+
}, props), _path$5 || (_path$5 = /*#__PURE__*/React.createElement("path", {
|
|
370
|
+
d: "m15 18-6-6 6-6"
|
|
371
|
+
})));
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
const alignmentMap = {
|
|
375
|
+
center: 'items-center justify-center h-full',
|
|
376
|
+
start: 'justify-start h-full',
|
|
377
|
+
end: 'justify-end h-full',
|
|
378
|
+
top: 'items-start',
|
|
379
|
+
bottom: 'items-end h-full',
|
|
380
|
+
'top-center': 'items-center justify-center',
|
|
381
|
+
};
|
|
382
|
+
const panelAlignmentMap = {
|
|
383
|
+
'top-center': 'data-[closed]:transform-[translateY(-50%)] rounded-b-lg',
|
|
384
|
+
center: 'data-[closed]:transform-[scale(95%)] rounded-lg',
|
|
385
|
+
start: 'data-[closed]:transform-[translateX(-50%)] rounded-r-lg',
|
|
386
|
+
end: 'data-[closed]:transform-[translateX(50%)] rounded-l-lg',
|
|
387
|
+
top: 'data-[closed]:transform-[translateY(-50%)] rounded-b-lg',
|
|
388
|
+
bottom: 'data-[closed]:transform-[translateY(50%)] rounded-t-lg',
|
|
389
|
+
};
|
|
390
|
+
const panelSizeMap = {
|
|
391
|
+
xs: 'max-w-xs',
|
|
392
|
+
sm: 'max-w-sm',
|
|
393
|
+
md: 'max-w-md',
|
|
394
|
+
lg: 'max-w-lg',
|
|
395
|
+
xl: 'max-w-xl',
|
|
396
|
+
'2xl': 'max-w-2xl',
|
|
397
|
+
full: 'w-full',
|
|
398
|
+
};
|
|
399
|
+
const Drawer = ({ isOpen, onClose = () => { }, align = 'end', size = 'md', backdrop = true, title, description = null, children = null, panelClass = '', contentClass = '', titleClass = '', descriptionClass = '', titleSticky = false, showBackButton = false, }) => {
|
|
400
|
+
return (jsxs(Dialog, { open: isOpen, as: "div", className: "relative z-15 focus:outline-none", onClose: onClose, children: [backdrop && jsx(DialogBackdrop, { className: "fixed inset-0 bg-black/20" }), jsx("div", { className: buildClassName('fixed inset-0 z-15 w-screen h-screen h-dvh'), children: jsx("div", { className: buildClassName('flex', alignmentMap[align]), children: jsxs(DialogPanel, { transition: true, className: buildClassName('w-full bg-white dark:bg-gray-800 backdrop-blur-2xl duration-200 ease-out data-[closed]:opacity-0 shadow-sm overflow-y-auto space-y-4', panelAlignmentMap[align], panelSizeMap[size], panelClass), children: [jsxs("div", { className: buildClassName('space-y-2 pt-2 md:pt-4 px-4 md:px-6', titleSticky && 'sticky top-0 bg-white dark:bg-gray-800 z-10'), children: [jsxs(DialogTitle, { as: "h3", className: buildClassName('text-lg/7 font-medium dark:text-white flex items-center gap-2', titleClass), children: [showBackButton && (jsx(Button, { iconOnly: true, variant: "plain", theme: "secondary", size: "sm", onClick: onClose, children: jsx(SvgChevronLeft, { className: "size-5" }) })), title] }), description && (jsx("p", { className: buildClassName('text-sm/6 dark:text-white/50', descriptionClass), children: description }))] }), jsx("div", { className: buildClassName(contentClass), children: children })] }) }) })] }));
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
const DROPDOWN_ITEM_CLASS = 'flex w-full px-3 py-2 cursor-pointer hover:bg-gray-50 rounded-lg';
|
|
404
|
+
const Dropdown = ({ triggerButton, items, renderItem, itemsContainerClass, transition = true, anchor = 'bottom start', }) => {
|
|
405
|
+
return (jsxs(Menu, { children: [jsx(MenuButton, { as: Fragment, children: triggerButton }), jsx(MenuItems, { transition: transition, anchor: anchor, className: buildClassName('w-52 origin-top-right rounded-xl border border-gray-100 bg-white shadow-sm p-1 text-sm/6 text-gray-800 transition duration-100 ease-out [--anchor-gap:--spacing(1)] focus:outline-none data-closed:scale-95 data-closed:opacity-0', itemsContainerClass), children: items.map((item) => (jsx(MenuItem, { children: item.divider ? (jsx("div", { className: "my-1 h-px bg-gray-200 dark:bg-white/5" })) : (renderItem(item, { className: DROPDOWN_ITEM_CLASS })) }, item.id))) })] }));
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
var _path$4;
|
|
409
|
+
function _extends$4() { return _extends$4 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$4.apply(null, arguments); }
|
|
410
|
+
var SvgFolderPlus = function SvgFolderPlus(props) {
|
|
411
|
+
return /*#__PURE__*/React.createElement("svg", _extends$4({
|
|
412
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
413
|
+
width: 24,
|
|
414
|
+
height: 24,
|
|
415
|
+
fill: "none",
|
|
416
|
+
stroke: "currentColor",
|
|
417
|
+
strokeLinecap: "round",
|
|
418
|
+
strokeLinejoin: "round",
|
|
419
|
+
strokeWidth: 2,
|
|
420
|
+
className: "lucide lucide-folder-plus-icon lucide-folder-plus",
|
|
421
|
+
viewBox: "0 0 24 24"
|
|
422
|
+
}, props), _path$4 || (_path$4 = /*#__PURE__*/React.createElement("path", {
|
|
423
|
+
d: "M12 10v6M9 13h6M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
|
|
424
|
+
})));
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
const EmptyState = ({ title, description, className, action = null, }) => {
|
|
428
|
+
return (jsx("div", { className: buildClassName('w-full flex justify-center px-4 pt-16', className), children: jsxs("div", { className: "max-w-md flex flex-col items-center gap-4", children: [jsx(SvgFolderPlus, { className: "size-8" }), jsx(HeadingText.SubTitle, { children: title }), description && (jsx(BodyText, { as: "p", className: "text-center", muted: true, small: true, children: description })), action] }) }));
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
const Input = forwardRef((props, ref) => {
|
|
432
|
+
const { name, id = name, type, label = null, labelHint = null, className = '', labelClass = '', labelWrapperClass = '', containerClass = '', error, showErrorMessage = true, rightGroup = null, leftGroup = null, autoComplete = 'off', ...inputProps } = props;
|
|
433
|
+
const hasError = Boolean(error);
|
|
434
|
+
const hasRightGroup = rightGroup != null && isValidElement(rightGroup);
|
|
435
|
+
const hasLeftGroup = leftGroup != null && isValidElement(leftGroup);
|
|
436
|
+
return (jsxs("div", { className: buildClassName('group', hasError && 'has-error', containerClass), children: [label && (jsxs("div", { className: buildClassName('flex items-center justify-between mb-2', labelWrapperClass), children: [jsx(Label, { className: labelClass, htmlFor: id, children: label }), labelHint] })), jsxs("div", { className: "relative", children: [hasLeftGroup && (jsx("span", { className: "absolute top-0 h-full flex items-center justify-center w-10", children: leftGroup })), jsx("input", { ref: ref, ...inputProps, name: name, id: id, type: type, autoComplete: autoComplete, className: buildClassName('transition-all', 'block w-full rounded-lg bg-white px-3.5 py-2 text-base sm:text-sm/6', 'text-gray-900 outline dark:outline outline-1 -outline-offset-1', 'outline-gray-300 dark:outline-gray-600', 'focus:outline-blue-600 dark:focus:outline-blue-600 focus:outline-2 focus:-outline-offset-2', 'dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-500 placeholder:text-gray-400 dark:text-white', 'invalid:group-[.has-error]:outline-red-500', 'disabled:pointer-events-none', 'dark:disabled:bg-gray-500 disabled:bg-gray-100', hasRightGroup ? 'pe-10' : '', hasLeftGroup ? 'ps-10' : '', className) }), hasRightGroup && (jsx("span", { className: "absolute end-0.75 top-0 h-full flex items-center justify-center w-10", children: rightGroup }))] }), showErrorMessage && error && (jsx("p", { className: "mt-1 text-red-500 dark:text-red-500 text-sm", children: error }))] }));
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
const DOTS = '...';
|
|
440
|
+
const usePagination = ({ totalPages, currentPage, siblingCount = 1, // number of pages to show around currentPage
|
|
441
|
+
}) => {
|
|
442
|
+
const totalPageNumbers = siblingCount * 2 + 5;
|
|
443
|
+
if (totalPageNumbers >= totalPages) {
|
|
444
|
+
return Array.from({ length: totalPages }, (_, i) => i + 1);
|
|
445
|
+
}
|
|
446
|
+
const leftSiblingIndex = Math.max(currentPage - siblingCount, 1);
|
|
447
|
+
const rightSiblingIndex = Math.min(currentPage + siblingCount, totalPages);
|
|
448
|
+
const shouldShowLeftDots = leftSiblingIndex > 2;
|
|
449
|
+
const shouldShowRightDots = rightSiblingIndex < totalPages - 1;
|
|
450
|
+
const firstPageIndex = 1;
|
|
451
|
+
const lastPageIndex = totalPages;
|
|
452
|
+
if (!shouldShowLeftDots && shouldShowRightDots) {
|
|
453
|
+
const leftRange = Array.from({ length: 3 + 2 * siblingCount }, (_, i) => i + 1);
|
|
454
|
+
return [...leftRange, DOTS, totalPages];
|
|
455
|
+
}
|
|
456
|
+
if (shouldShowLeftDots && !shouldShowRightDots) {
|
|
457
|
+
const rightRange = Array.from({ length: 3 + 2 * siblingCount }, (_, i) => totalPages - (3 + 2 * siblingCount) + 1 + i);
|
|
458
|
+
return [firstPageIndex, DOTS, ...rightRange];
|
|
459
|
+
}
|
|
460
|
+
if (shouldShowLeftDots && shouldShowRightDots) {
|
|
461
|
+
const middleRange = Array.from({ length: 2 * siblingCount + 1 }, (_, i) => leftSiblingIndex + i);
|
|
462
|
+
return [firstPageIndex, DOTS, ...middleRange, DOTS, lastPageIndex];
|
|
463
|
+
}
|
|
464
|
+
return [];
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
var _path$3;
|
|
468
|
+
function _extends$3() { return _extends$3 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$3.apply(null, arguments); }
|
|
469
|
+
var SvgChevronRight = function SvgChevronRight(props) {
|
|
470
|
+
return /*#__PURE__*/React.createElement("svg", _extends$3({
|
|
471
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
472
|
+
width: 24,
|
|
473
|
+
height: 24,
|
|
474
|
+
fill: "none",
|
|
475
|
+
stroke: "currentColor",
|
|
476
|
+
strokeLinecap: "round",
|
|
477
|
+
strokeLinejoin: "round",
|
|
478
|
+
strokeWidth: 2,
|
|
479
|
+
className: "lucide lucide-chevron-right-icon lucide-chevron-right",
|
|
480
|
+
viewBox: "0 0 24 24"
|
|
481
|
+
}, props), _path$3 || (_path$3 = /*#__PURE__*/React.createElement("path", {
|
|
482
|
+
d: "m9 18 6-6-6-6"
|
|
483
|
+
})));
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
const Pagination = ({ page: currentPage, limit, total, onChange, className, ellipsis = true, // Default to showing ellipsis
|
|
487
|
+
}) => {
|
|
488
|
+
const pages = new Array(Math.ceil(total / limit)).fill(null).map((_, i) => i + 1);
|
|
489
|
+
const isFirstPage = currentPage === 1;
|
|
490
|
+
const isLastPage = total === 0 || pages.length === currentPage;
|
|
491
|
+
const range = usePagination({ totalPages: pages.length, currentPage });
|
|
492
|
+
const handlePageChange = (nextVal) => {
|
|
493
|
+
if (nextVal === currentPage)
|
|
494
|
+
return;
|
|
495
|
+
onChange({ page: nextVal });
|
|
496
|
+
};
|
|
497
|
+
if (ellipsis) {
|
|
498
|
+
return (jsx("div", { className: buildClassName('flex items-center justify-between bg-white dark:bg-gray-800 px-4 py-3 sm:px-6', className), children: jsxs("div", { className: "hidden sm:flex sm:flex-1 sm:items-center sm:justify-between", children: [jsxs("p", { className: "text-sm text-gray-600 dark:text-gray-400 flex items-center gap-1", children: ["Showing", jsx("span", { className: "font-medium", children: total === 0 ? 0 : Math.max(currentPage * limit - limit + 1, 1) }), "to", jsx("span", { className: "font-medium", children: Math.min(currentPage * limit, total) }), "of", jsx("span", { className: "font-medium", children: total }), "results"] }), jsxs("ul", { className: "flex items-center space-x-2 text-sm", children: [jsx("li", { children: jsx(Button, { size: "xs", theme: "secondary", variant: "plain", disabled: isFirstPage, onClick: () => handlePageChange(currentPage - 1), children: "Prev" }) }), range.map((page, idx) => {
|
|
499
|
+
if (page === DOTS) {
|
|
500
|
+
return (jsx("li", { className: "px-2 py-1 text-gray-400", children: "\u2026" }, page + idx));
|
|
501
|
+
}
|
|
502
|
+
return (jsx("li", { children: jsx(Button, { size: "xs", theme: page === currentPage ? 'primary' : 'secondary', variant: page === currentPage ? 'default' : 'plain', "aria-current": page === currentPage ? 'page' : undefined, onClick: () => handlePageChange(page), children: page }, page) }, page));
|
|
503
|
+
}), jsx("li", { children: jsx(Button, { size: "xs", theme: "secondary", variant: "plain", disabled: isLastPage, onClick: () => handlePageChange(currentPage + 1), children: "Next" }) })] })] }) }));
|
|
504
|
+
}
|
|
505
|
+
return (jsxs("div", { className: buildClassName('flex items-center justify-between bg-white dark:bg-gray-800 px-4 py-3 sm:px-6', className), children: [jsxs("div", { className: "flex flex-1 justify-between sm:hidden", children: [jsx("a", { href: "#", className: "relative inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50", children: "Previous" }), jsx("a", { href: "#", className: "relative ml-3 inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50", children: "Next" })] }), jsxs("div", { className: "hidden sm:flex sm:flex-1 sm:items-center sm:justify-between", children: [jsxs("p", { className: "text-sm text-gray-600 dark:text-gray-400 flex items-center gap-1", children: ["Showing", jsx("span", { className: "font-medium", children: total === 0 ? 0 : Math.max(currentPage * limit - limit + 1, 1) }), "to", jsx("span", { className: "font-medium", children: Math.min(currentPage * limit, total) }), "of", jsx("span", { className: "font-medium", children: total }), "results"] }), jsxs("nav", { className: "isolate inline-flex items-center rounded-md", "aria-label": "Pagination", children: [jsxs(Button, { size: "xs", theme: "secondary", variant: "plain", disabled: isFirstPage, onClick: () => handlePageChange(currentPage - 1), children: [jsx("span", { className: "sr-only", children: "Previous" }), jsx(SvgChevronLeft, { className: "size-4" })] }), pages.map((page) => (jsx(Button, { size: "xs", theme: page === currentPage ? 'primary' : 'secondary', variant: page === currentPage ? 'default' : 'plain', "aria-current": page === currentPage ? 'page' : undefined, onClick: () => handlePageChange(page), children: jsx("span", { className: "size-4 block", children: page }) }, page))), jsxs(Button, { size: "xs", theme: "secondary", variant: "plain", disabled: isLastPage, onClick: () => handlePageChange(currentPage + 1), children: [jsx("span", { className: "sr-only", children: "Next" }), jsx(SvgChevronRight, { className: "size-4" })] })] })] })] }));
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
const PASSWORD_TYPE = 'password';
|
|
509
|
+
const PASSWORD_PLACEHOLDER = '••••••••••';
|
|
510
|
+
const PasswordInput = (props) => {
|
|
511
|
+
const { type, placeholder, ...inputProps } = props;
|
|
512
|
+
const [showPassword, setShowPassword] = useState(false);
|
|
513
|
+
return (jsx(Input, { ...inputProps, type: showPassword ? 'text' : PASSWORD_TYPE, placeholder: PASSWORD_PLACEHOLDER, rightGroup: jsx(Button, { theme: "secondary", variant: "plain", size: "xs", className: "px-1 mr-1", type: "button", onClick: () => setShowPassword(() => !showPassword), tabIndex: -1, children: showPassword ? (jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: "1.5", stroke: "currentColor", className: "size-4", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3.98 8.223A10.477 10.477 0 0 0 1.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.451 10.451 0 0 1 12 4.5c4.756 0 8.773 3.162 10.065 7.498a10.522 10.522 0 0 1-4.293 5.774M6.228 6.228 3 3m3.228 3.228 3.65 3.65m7.894 7.894L21 21m-3.228-3.228-3.65-3.65m0 0a3 3 0 1 0-4.243-4.243m4.242 4.242L9.88 9.88" }) })) : (jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: "1.5", stroke: "currentColor", className: "size-4", children: [jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" }), jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" })] })) }) }));
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
const RadioButton = forwardRef((props, ref) => {
|
|
517
|
+
const { type = 'radio', name, id = name, wrapperClass = '', containerClass = '', label = null, labelClass = '', labelHint = null, error = null, ...radioProps } = props;
|
|
518
|
+
return (jsxs("div", { className: buildClassName(wrapperClass), children: [jsxs("div", { className: buildClassName('flex items-center gap-2', containerClass), children: [jsx("div", { className: "grid place-items-center", children: jsx("input", { ref: ref, ...radioProps, type: "radio", id: id, name: name, className: "peer transition-all col-start-1 row-start-1 appearance-none shrink-0 size-4.5 border-1 border-gray-300 focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 checked:border-5 checked:border-blue-600 rounded-full bg-white" }) }), label && (jsx(Label, { htmlFor: id, className: buildClassName('cursor-pointer font-normal text-gray-600', labelClass), children: label }))] }), error && jsx("div", { className: "mt-1 text-red-600 text-sm", children: error })] }));
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
const RadioButtonGroup = (props) => {
|
|
522
|
+
const { name, label = null, labelClass = '', labelWrapperClass = '', labelHint = null, containerClass = '', options, value, row, onChange, } = props;
|
|
523
|
+
const [items, setItems] = useState([]);
|
|
524
|
+
useEffect(() => {
|
|
525
|
+
setItems(() => {
|
|
526
|
+
return options === null || options === void 0 ? void 0 : options.map((option) => {
|
|
527
|
+
if (typeof option === 'string') {
|
|
528
|
+
return { label: option, value: option };
|
|
529
|
+
}
|
|
530
|
+
return option;
|
|
531
|
+
});
|
|
532
|
+
});
|
|
533
|
+
}, [options]);
|
|
534
|
+
return (jsxs("div", { className: buildClassName(containerClass), children: [label && (jsxs("div", { className: buildClassName('flex items-center justify-between mb-4', labelWrapperClass), children: [jsx(Label, { className: labelClass, children: label }), labelHint] })), jsx("div", { className: buildClassName('flex gap-2', row ? 'flex-row items-center' : 'flex-col items-start'), children: items.map((item) => (jsx(RadioButton, { name: name, id: item.value, label: item.label, value: item.value, checked: value === item.value, onChange: onChange }, item.value))) })] }));
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
const RadioSwitch = ({ label, items, selected, onChange }) => {
|
|
538
|
+
const getLabel = (item) => {
|
|
539
|
+
return typeof item === 'string' ? item : item.label;
|
|
540
|
+
};
|
|
541
|
+
const getValue = (item) => {
|
|
542
|
+
return typeof item === 'string' ? item : item.value;
|
|
543
|
+
};
|
|
544
|
+
const getDescription = (item) => {
|
|
545
|
+
return typeof item === 'string' ? '' : item.description || '';
|
|
546
|
+
};
|
|
547
|
+
return (jsx(RadioGroup, { value: selected, onChange: onChange, "aria-label": label, className: "flex items-center bg-white rounded-full shadow-xs p-1 dark:bg-gray-800 gap-1 border border-gray-200 dark:border-gray-700", children: items.map((item) => (jsx(Radio, { value: getValue(item), className: buildClassName('group relative flex cursor-pointer transition', 'text-gray-500 dark:text-gray-300', 'focus:not-data-focus:outline-none data-focus:outline data-focus:outline-white'), children: jsx("div", { className: buildClassName('dark:text-white justify-between px-3 py-1 transition', 'group-data-checked:bg-blue-600 group-data-checked:text-white rounded-full'), children: jsxs("div", { className: "text-sm/6", children: [jsx("p", { className: "font-semibold dark:text-white", children: getLabel(item) }), item.description && (jsx("div", { className: "flex gap-2 text-white/50", children: getDescription(item) }))] }) }) }, getValue(item)))) }));
|
|
548
|
+
};
|
|
549
|
+
|
|
550
|
+
const RangeInput = (props) => {
|
|
551
|
+
const { name, id = name, label = null, labelClass = '', labelWrapperClass = '', labelHint = null, containerClass = '', min = 0, max = 0, value, onChange, ...rangeProps } = props;
|
|
552
|
+
const handleRangeChange = (e) => {
|
|
553
|
+
const { value: _value = '0', name: _name } = e.target;
|
|
554
|
+
let changedValue = parseInt(_value);
|
|
555
|
+
let nextValue = {
|
|
556
|
+
...props.value,
|
|
557
|
+
[_name]: changedValue,
|
|
558
|
+
};
|
|
559
|
+
if (e.target.name === 'max' && (value === null || value === void 0 ? void 0 : value.min) && changedValue < parseInt(value.min || '0')) {
|
|
560
|
+
nextValue[_name] = parseInt(value.min);
|
|
561
|
+
}
|
|
562
|
+
if (e.target.name === 'min' && (value === null || value === void 0 ? void 0 : value.max) && changedValue > parseInt(value.max || '0')) {
|
|
563
|
+
nextValue[_name] = parseInt(value.max);
|
|
564
|
+
}
|
|
565
|
+
onChange &&
|
|
566
|
+
onChange({
|
|
567
|
+
target: {
|
|
568
|
+
name,
|
|
569
|
+
value: nextValue,
|
|
570
|
+
},
|
|
571
|
+
});
|
|
572
|
+
};
|
|
573
|
+
return (jsxs("div", { className: buildClassName('mb-3 relative', containerClass), children: [label && (jsxs("div", { className: buildClassName('flex items-center justify-between mb-4', labelWrapperClass), children: [jsx(Label, { className: labelClass, htmlFor: id, children: label }), labelHint] })), jsxs("div", { className: "flex w-full gap-4 items-center", children: [jsx(Input, { ...rangeProps, id: id, name: "min", type: "number", min: min, max: value === null || value === void 0 ? void 0 : value.max, value: (value === null || value === void 0 ? void 0 : value.min) || '', className: "appearance-none", containerClass: "flex-1 shrink-0 mb-0", placeholder: "Min", onChange: handleRangeChange }), jsx("span", { children: "to" }), jsx(Input, { ...rangeProps, id: id, name: "max", type: "number", min: value === null || value === void 0 ? void 0 : value.min, max: max, value: (value === null || value === void 0 ? void 0 : value.max) || '', className: "appearance-none", containerClass: "flex-1 shrink-0 mb-0", placeholder: "Max", onChange: handleRangeChange, disabled: !(value === null || value === void 0 ? void 0 : value.min) })] })] }));
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* Checks if a value is an array.
|
|
578
|
+
* Equivalent to lodash's _.isArray.
|
|
579
|
+
*/
|
|
580
|
+
function isArray(value) {
|
|
581
|
+
return Array.isArray(value);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Checks if a value is empty.
|
|
586
|
+
* Works for arrays, objects, strings, Maps, and Sets.
|
|
587
|
+
* Equivalent to lodash's _.isEmpty.
|
|
588
|
+
*/
|
|
589
|
+
function isEmpty(value) {
|
|
590
|
+
if (value == null)
|
|
591
|
+
return true; // null or undefined
|
|
592
|
+
if (typeof value === 'string' || isArray(value)) {
|
|
593
|
+
return value.length === 0;
|
|
594
|
+
}
|
|
595
|
+
if (value instanceof Map || value instanceof Set) {
|
|
596
|
+
return value.size === 0;
|
|
597
|
+
}
|
|
598
|
+
if (typeof value === 'object') {
|
|
599
|
+
return Object.keys(value).length === 0;
|
|
600
|
+
}
|
|
601
|
+
return false; // for numbers, booleans, functions, etc.
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
const useDebounce = (value, delay) => {
|
|
605
|
+
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
606
|
+
useEffect(() => {
|
|
607
|
+
const handler = setTimeout(() => {
|
|
608
|
+
setDebouncedValue(value);
|
|
609
|
+
}, delay);
|
|
610
|
+
// Cancel the timeout if value or delay changes
|
|
611
|
+
return () => {
|
|
612
|
+
clearTimeout(handler);
|
|
613
|
+
};
|
|
614
|
+
}, [value, delay]);
|
|
615
|
+
return debouncedValue;
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
var _path$2;
|
|
619
|
+
function _extends$2() { return _extends$2 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$2.apply(null, arguments); }
|
|
620
|
+
var SvgCheck = function SvgCheck(props) {
|
|
621
|
+
return /*#__PURE__*/React.createElement("svg", _extends$2({
|
|
622
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
623
|
+
width: 24,
|
|
624
|
+
height: 24,
|
|
625
|
+
fill: "none",
|
|
626
|
+
stroke: "currentColor",
|
|
627
|
+
strokeLinecap: "round",
|
|
628
|
+
strokeLinejoin: "round",
|
|
629
|
+
strokeWidth: 2,
|
|
630
|
+
className: "lucide lucide-check-icon lucide-check",
|
|
631
|
+
viewBox: "0 0 24 24"
|
|
632
|
+
}, props), _path$2 || (_path$2 = /*#__PURE__*/React.createElement("path", {
|
|
633
|
+
d: "M20 6 9 17l-5-5"
|
|
634
|
+
})));
|
|
635
|
+
};
|
|
636
|
+
|
|
637
|
+
var _path$1;
|
|
638
|
+
function _extends$1() { return _extends$1 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$1.apply(null, arguments); }
|
|
639
|
+
var SvgChevronDown = function SvgChevronDown(props) {
|
|
640
|
+
return /*#__PURE__*/React.createElement("svg", _extends$1({
|
|
641
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
642
|
+
width: 24,
|
|
643
|
+
height: 24,
|
|
644
|
+
fill: "none",
|
|
645
|
+
stroke: "currentColor",
|
|
646
|
+
strokeLinecap: "round",
|
|
647
|
+
strokeLinejoin: "round",
|
|
648
|
+
strokeWidth: 2,
|
|
649
|
+
className: "lucide lucide-chevron-down-icon lucide-chevron-down",
|
|
650
|
+
viewBox: "0 0 24 24"
|
|
651
|
+
}, props), _path$1 || (_path$1 = /*#__PURE__*/React.createElement("path", {
|
|
652
|
+
d: "m6 9 6 6 6-6"
|
|
653
|
+
})));
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
var _circle, _path;
|
|
657
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
658
|
+
var SvgCirclePlus = function SvgCirclePlus(props) {
|
|
659
|
+
return /*#__PURE__*/React.createElement("svg", _extends({
|
|
660
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
661
|
+
width: 24,
|
|
662
|
+
height: 24,
|
|
663
|
+
fill: "none",
|
|
664
|
+
stroke: "currentColor",
|
|
665
|
+
strokeLinecap: "round",
|
|
666
|
+
strokeLinejoin: "round",
|
|
667
|
+
strokeWidth: 2,
|
|
668
|
+
className: "lucide lucide-circle-plus-icon lucide-circle-plus",
|
|
669
|
+
viewBox: "0 0 24 24"
|
|
670
|
+
}, props), _circle || (_circle = /*#__PURE__*/React.createElement("circle", {
|
|
671
|
+
cx: 12,
|
|
672
|
+
cy: 12,
|
|
673
|
+
r: 10
|
|
674
|
+
})), _path || (_path = /*#__PURE__*/React.createElement("path", {
|
|
675
|
+
d: "M8 12h8M12 8v8"
|
|
676
|
+
})));
|
|
677
|
+
};
|
|
678
|
+
|
|
679
|
+
const constructInputClass = (disabled) => buildClassName('transition-all', 'block w-full rounded-lg px-3.5 py-2 text-base sm:text-sm/6', 'text-gray-900 outline dark:outline outline-1 -outline-offset-1', 'outline-gray-300 dark:outline-gray-600', 'focus:outline-blue-600 dark:focus:outline-blue-600 focus:outline-2 focus:-outline-offset-2', 'dark:border-gray-600 dark:placeholder-gray-500 placeholder:text-gray-400 dark:text-white', 'group-[.has-error]:outline-red-600 group-[.has-error]:focus:outline-red-600', '[&:has(:focus-visible)]:outline-2 [&:has(:focus-visible)]:outline-blue-600', 'group-[.has-error]:[&:has(:focus-visible)]:outline-red-600', disabled ? 'pointer-events-none bg-gray-100 dark:bg-gray-500' : 'bg-white dark:bg-gray-700');
|
|
680
|
+
const SelectBox = (props) => {
|
|
681
|
+
const { labelKey = 'label', valueKey = 'value', name, id = name, options, selected, label = null, labelWrapperClass = '', labelClass = '', labelHint = null, disabled = false, containerClass = '', onChange = () => { }, placeholder, dropdownContainerClass = 'z-20', multiple = false, maxSelection, immediate = true, showErrorMessage = true, error = null, async = false, searchable = true, required = false, allowAdd = false, addNewText = 'Create', onAdd = () => { }, allowClear = false, } = props;
|
|
682
|
+
const hasError = Boolean(error);
|
|
683
|
+
const [query, setQuery] = useState('');
|
|
684
|
+
const debouncedQuery = useDebounce(query, 500);
|
|
685
|
+
const [optionsLoading, setOptionsLoading] = useState(false);
|
|
686
|
+
const shouldShowTypeToSearch = async && !debouncedQuery && !options.length;
|
|
687
|
+
const inputClass = constructInputClass(disabled);
|
|
688
|
+
const inputRef = useRef(null);
|
|
689
|
+
const filteredOptions = query === '' || async
|
|
690
|
+
? options
|
|
691
|
+
: options.filter((option) => {
|
|
692
|
+
if (typeof option === 'string')
|
|
693
|
+
return option.toLowerCase().includes(query.toLowerCase());
|
|
694
|
+
return option[labelKey].toLowerCase().includes(query.toLowerCase());
|
|
695
|
+
});
|
|
696
|
+
const getDisplayValue = (option) => {
|
|
697
|
+
return typeof option === 'string' ? option : option[labelKey];
|
|
698
|
+
};
|
|
699
|
+
const getValue = (option) => {
|
|
700
|
+
return typeof option === 'string' ? option : option[valueKey];
|
|
701
|
+
};
|
|
702
|
+
const removeSelection = (idx) => {
|
|
703
|
+
if (!isArray(selected)) {
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
const nextSelectedValue = [...selected];
|
|
707
|
+
nextSelectedValue.splice(idx, 1);
|
|
708
|
+
onChange(nextSelectedValue);
|
|
709
|
+
};
|
|
710
|
+
const handleOnChange = (value) => {
|
|
711
|
+
let nextValue = !value ? (multiple ? [] : {}) : value;
|
|
712
|
+
if (multiple && isArray(selected)) {
|
|
713
|
+
if (maxSelection && selected.length >= maxSelection) {
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
onChange(nextValue);
|
|
718
|
+
setQuery('');
|
|
719
|
+
};
|
|
720
|
+
const handleSearch = async (searchString) => {
|
|
721
|
+
var _a;
|
|
722
|
+
try {
|
|
723
|
+
setOptionsLoading(true);
|
|
724
|
+
await ((_a = props.onSearch) === null || _a === void 0 ? void 0 : _a.call(props, searchString));
|
|
725
|
+
}
|
|
726
|
+
catch (error) {
|
|
727
|
+
console.error('Error loading options:', error);
|
|
728
|
+
}
|
|
729
|
+
finally {
|
|
730
|
+
setOptionsLoading(false);
|
|
731
|
+
}
|
|
732
|
+
};
|
|
733
|
+
useEffect(() => {
|
|
734
|
+
if (async && debouncedQuery) {
|
|
735
|
+
handleSearch(debouncedQuery);
|
|
736
|
+
}
|
|
737
|
+
}, [debouncedQuery, async]);
|
|
738
|
+
return (jsxs("div", { className: buildClassName('group space-y-2', hasError && 'has-error', containerClass), children: [label && (jsxs("div", { className: buildClassName('flex items-center justify-between', labelWrapperClass), children: [jsx(Label, { className: labelClass, htmlFor: id, "aria-required": required, children: label }), labelHint] })), jsxs(Combobox, { multiple: multiple, immediate: immediate, name: name, value: selected, onChange: handleOnChange, onClose: () => setQuery(''), disabled: disabled, children: [multiple ? (jsxs("div", { className: buildClassName(inputClass, 'flex flex-wrap gap-2 peer'), children: [isArray(selected) && (selected === null || selected === void 0 ? void 0 : selected.length) > 0 && (jsx(Fragment$1, { children: selected.map((option, idx) => (jsx(Badge, { theme: "secondary", removable: !disabled, onRemove: () => removeSelection(idx), children: getDisplayValue(option) }, getValue(option)))) })), jsx(ComboboxInput, { className: "outline-none flex-1", "aria-label": name, value: query, autoComplete: "off", placeholder: (selected === null || selected === void 0 ? void 0 : selected.length) ? '' : placeholder, onChange: (event) => setQuery(event.target.value), id: id })] })) : (jsxs("div", { className: "relative", children: [jsx(ComboboxInput, { "aria-label": name, displayValue: (option) => (option ? getDisplayValue(option) : null), autoComplete: "off", placeholder: placeholder, onChange: (event) => setQuery(event.target.value), className: inputClass, disabled: disabled, "data-disabled": disabled, id: id, readOnly: !searchable, ref: inputRef }), allowClear && !isEmpty(selected) && (jsx(Button, { size: "xs", iconOnly: true, theme: "secondary", variant: "plain", className: "group absolute inset-y-0 right-8 h-6 top-2", onClick: () => handleOnChange(multiple ? [] : null), disabled: disabled, children: jsx(SvgX, { className: "size-4 fill-white/60 group-data-[hover]:fill-white" }) })), jsx(ComboboxButton, { className: "group absolute inset-y-0 right-0 px-2.5", children: jsx(SvgChevronDown, { className: "size-4 fill-white/60 group-data-[hover]:fill-white" }) })] })), jsx(ComboboxOptions, { anchor: {
|
|
739
|
+
to: 'bottom',
|
|
740
|
+
gap: 5,
|
|
741
|
+
}, className: buildClassName('w-[var(--input-width)] rounded-lg border border-gray-200 dark:border-white/5 bg-white dark:bg-gray-800 p-1 [--anchor-gap:var(--spacing-1)]', '[--anchor-max-height:20rem]', 'origin-top border transition duration-200 ease-out data-[closed]:translate-y-[-25%] data-[closed]:opacity-0 data-[closed]:overflow-hidden', dropdownContainerClass), children: optionsLoading ? (jsx("div", { className: "flex items-center justify-center py-2 px-3 select-none", children: jsx(Loader, { size: "sm" }) })) : shouldShowTypeToSearch ? (jsx("div", { className: "flex items-center justify-between py-2 px-3 select-none", children: "Type to search..." })) : (jsxs(Fragment$1, { children: [filteredOptions.map((option) => (jsxs(ComboboxOption, { disabled: option.disabled, value: option, className: "group flex items-center justify-between gap-2 rounded-lg py-1.5 px-3 select-none data-[focus]:bg-black/3 dark:data-[focus]:bg-white/10 data-disabled:opacity-50 cursor-pointer data-disabled:pointer-events-none", children: [jsx("span", { className: "text-sm/6 dark:text-white", children: getDisplayValue(option) }), jsx(SvgCheck, { className: "invisible size-5 dark:fill-white group-data-[selected]:visible" })] }, getValue(option)))), filteredOptions.length === 0 && query && !optionsLoading && (jsxs("div", { className: "flex items-center gap-2 py-1.5 px-3 select-none text-gray-500 dark:text-gray-400", children: ["No results found for ", jsx("span", { className: "font-semibold", children: query })] })), allowAdd ? (jsxs("div", { role: "button", onClick: () => onAdd(query), className: "group flex items-center gap-2 rounded-lg py-1.5 px-3 cursor-pointer text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700", children: [jsx(SvgCirclePlus, { className: "size-4.5 text-blue-600" }), jsx(TextContent, { children: addNewText }), jsx(TextContent, { strong: true, children: query })] })) : null] })) })] }), showErrorMessage && error && (jsx("p", { className: "text-red-500 dark:text-red-500 text-sm", children: error }))] }));
|
|
742
|
+
};
|
|
743
|
+
|
|
744
|
+
const TEXT_ALIGN_CLASSES = {
|
|
745
|
+
left: 'text-left',
|
|
746
|
+
center: 'text-center',
|
|
747
|
+
right: 'text-right',
|
|
748
|
+
};
|
|
749
|
+
const TABLE_LAYOUT_CLASSES = {
|
|
750
|
+
fixed: 'table-fixed',
|
|
751
|
+
auto: 'table-auto',
|
|
752
|
+
};
|
|
753
|
+
const TableRowLoader = ({ colSize, rowSize }) => (jsx(Fragment$1, { children: [...Array(rowSize)].map((_, rowIndex) => (jsx(TableRow, { className: "animate-pulse", children: [...Array(colSize)].map((_, colIndex) => (jsx(TableCell, { children: jsx("div", { className: "flex items-center h-6", children: jsx("div", { className: "h-4 bg-gray-300 shimmer dark:bg-gray-700 rounded w-full" }) }) }, colIndex))) }, rowIndex))) }));
|
|
754
|
+
const Table = ({ children, layout = 'auto', className = '' }) => (jsx("table", { className: buildClassName('border-collapse table-fixed w-full divide-y divide-gray-200', TABLE_LAYOUT_CLASSES[layout], className), children: children }));
|
|
755
|
+
const TabelHead = ({ children, className = '', onSort }) => (jsx("thead", { className: buildClassName('text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400', className), children: jsx(TableRow, { className: "dark:hover:bg-gray-700", hoverable: false, children: React__default.Children.map(children, (child) => {
|
|
756
|
+
// Check if child is a valid React element
|
|
757
|
+
if (React__default.isValidElement(child)) {
|
|
758
|
+
// Type the child explicitly to ReactElement so TypeScript knows it supports onClick
|
|
759
|
+
return React__default.cloneElement(child, { onClick: onSort });
|
|
760
|
+
}
|
|
761
|
+
// Return child as-is if it's not a React element
|
|
762
|
+
return child;
|
|
763
|
+
}) }) }));
|
|
764
|
+
const TabelBody = ({ children, loading, colSize, rowSize = 5, className = '', }) => (jsx("tbody", { className: buildClassName('text-sm text-gray-700 dark:text-white divide-y divide-gray-200 dark:divide-gray-700', className), children: loading ? (jsx(TableRowLoader, { colSize: colSize, rowSize: rowSize })) : (jsx(Fragment$1, { children: React__default.Children.map(children, (child) => {
|
|
765
|
+
// Check if child is a valid React element
|
|
766
|
+
if (React__default.isValidElement(child)) {
|
|
767
|
+
// Type the child explicitly to ReactElement so TypeScript knows it supports onClick
|
|
768
|
+
return React__default.cloneElement(child);
|
|
769
|
+
}
|
|
770
|
+
// Return child as-is if it's not a React element
|
|
771
|
+
return child;
|
|
772
|
+
}) })) }));
|
|
773
|
+
const TabelFoot = ({ children }) => (jsx("tfoot", { children: React__default.Children.map(children, (child) => {
|
|
774
|
+
// Check if child is a valid React element
|
|
775
|
+
if (React__default.isValidElement(child)) {
|
|
776
|
+
// Type the child explicitly to ReactElement so TypeScript knows it supports onClick
|
|
777
|
+
return React__default.cloneElement(child);
|
|
778
|
+
}
|
|
779
|
+
// Return child as-is if it's not a React element
|
|
780
|
+
return child;
|
|
781
|
+
}) }));
|
|
782
|
+
const TableRow = ({ children, hoverable = true, className, ...props }) => (jsx("tr", { className: buildClassName('last:border-b border-gray-200 dark:border-gray-700 group h-full', className), ...props, children: children }));
|
|
783
|
+
const TableCell = ({ children, align = 'left', className = '', ...props }) => (jsx("td", { className: buildClassName('first:pl-4 last:pr-4 px-3 py-3 bg-white dark:bg-gray-800 group-hover:bg-gray-50 group-hover:dark:bg-gray-600 whitespace-normal', className, TEXT_ALIGN_CLASSES[align]), ...props, children: jsx("div", { className: "antialiased leading-normal", children: children }) }));
|
|
784
|
+
const TableHeaderCell = ({ children, align = 'left', className = '', ...props }) => (jsx("th", { className: buildClassName('first:pl-4 last:pr-4 px-3 py-3 tracking-wider whitespace-nowrap', 'text-gray-800 dark:text-gray-400', TEXT_ALIGN_CLASSES[align], className), ...props, children: jsx(BodyText, { as: "div", className: "block antialiased leading-none", children: children }) }));
|
|
785
|
+
const EmptyTableRow = ({ children, colSpan = 1 }) => (jsx("tr", { children: jsx(TableCell, { colSpan: colSpan, align: "center", children: jsx("div", { className: "p-8 space-y-3", children: children }) }) }));
|
|
786
|
+
|
|
787
|
+
const Recent = () => jsx("div", { children: "Recent" });
|
|
788
|
+
const Popular = () => jsx("div", { children: "Popular" });
|
|
789
|
+
const Trending = () => jsx("div", { children: "Trending" });
|
|
790
|
+
const categories = [
|
|
791
|
+
{
|
|
792
|
+
name: 'Recent',
|
|
793
|
+
component: Recent,
|
|
794
|
+
props: {},
|
|
795
|
+
},
|
|
796
|
+
{
|
|
797
|
+
name: 'Popular',
|
|
798
|
+
component: Popular,
|
|
799
|
+
props: {},
|
|
800
|
+
},
|
|
801
|
+
{
|
|
802
|
+
name: 'Trending',
|
|
803
|
+
component: Trending,
|
|
804
|
+
props: {},
|
|
805
|
+
},
|
|
806
|
+
];
|
|
807
|
+
const Tabs = () => {
|
|
808
|
+
return (jsx("div", { className: "flex w-full pt-4", children: jsx("div", { className: "w-full max-w-md", children: jsxs(TabGroup, { children: [jsx(TabList, { className: "flex gap-4", children: categories.map(({ name }) => (jsx(Tab, { className: buildClassName('rounded-full py-1 px-3 text-sm/6 font-semibold dark:text-white border border-transparent', 'data-[selected]:bg-blue-100 dark:data-[selected]:bg-white/10 data-[selected]:text-blue-500', 'data-[hover]:bg-blue-50 dark:data-[hover]:bg-white/5', 'data-[selected]:data-[hover]:bg-blue-100 dark:data-[selected]:data-[hover]:bg-white/10', 'focus:outline-none data-[focus]:outline-1 data-[focus]:outline-blue-800 dark:data-[focus]:outline-white', 'data-[selected]:border-blue-500'), children: name }, name))) }), jsx(TabPanels, { className: "mt-3", children: categories.map(({ name, component: Component, props }) => (jsx(TabPanel, { className: "rounded-xl bg-white/5 p-3", children: jsx(Component, { ...props }) }, name))) })] }) }) }));
|
|
809
|
+
};
|
|
810
|
+
|
|
811
|
+
const variantMap = {
|
|
812
|
+
primary: 'bg-blue-100 text-blue-600 border border-blue-200',
|
|
813
|
+
secondary: 'bg-gray-100 text-gray-600 border border-gray-200',
|
|
814
|
+
success: 'bg-green-100 text-green-600 border border-green-200',
|
|
815
|
+
warning: 'bg-orange-100 text-orange-600 border border-orange-200',
|
|
816
|
+
error: 'bg-red-100 text-red-600 border border-red-200',
|
|
817
|
+
};
|
|
818
|
+
const Tag = (props) => {
|
|
819
|
+
const { as: Element = 'span', text, className = '', onClose, variant = 'secondary', ...elemProps } = props;
|
|
820
|
+
return (jsxs(Element, { ...elemProps, className: buildClassName(className, 'px-1.5 py-0.5 text-sm/6 font-normal', variantMap[variant], 'rounded'), children: [jsx("span", { children: text }), onClose && jsx(SvgCircleX, { className: "size-3", onClick: () => onClose(), role: "button" })] }));
|
|
821
|
+
};
|
|
822
|
+
|
|
823
|
+
const Textarea = forwardRef((props, ref) => {
|
|
824
|
+
const { name, id = name, label = null, labelHint = null, className = '', labelClass = '', labelWrapperClass = '', containerClass = '', error, showErrorMessage = true, rightGroup = null, leftGroup = null, ...inputProps } = props;
|
|
825
|
+
const hasError = !isEmpty(error);
|
|
826
|
+
const hasRightGroup = rightGroup != null && isValidElement(rightGroup);
|
|
827
|
+
const hasLeftGroup = leftGroup != null && isValidElement(leftGroup);
|
|
828
|
+
return (jsxs("div", { className: buildClassName('group', hasError && 'has-error', containerClass), children: [label && (jsxs("div", { className: buildClassName('flex items-center justify-between mb-2', labelWrapperClass), children: [jsx(Label, { className: labelClass, htmlFor: id, children: label }), labelHint] })), jsxs("div", { className: "relative", children: [hasLeftGroup && (jsx("span", { className: "absolute top-0 h-full flex items-center justify-center w-10", children: leftGroup })), jsx("textarea", { ref: ref, ...inputProps, name: name, id: id, className: buildClassName('transition-all', 'block w-full rounded-lg bg-white px-3.5 py-2 text-base sm:text-sm/6', 'text-gray-900 outline dark:outline outline-1 -outline-offset-1', 'outline-gray-300 dark:outline-gray-600', 'focus:outline-blue-600 dark:focus:outline-blue-600 focus:outline-2 focus:-outline-offset-2', 'dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-500 placeholder:text-gray-400 dark:text-white', 'invalid:group-[.has-error]:outline-red-500', 'disabled:pointer-events-none disabled:bg-gray-100', 'dark:disabled:bg-gray-500', hasRightGroup ? 'pe-10' : '', hasLeftGroup ? 'ps-10' : '', className) }), hasRightGroup && (jsx("span", { className: "absolute end-0.75 top-0 h-full flex items-center justify-center", children: rightGroup }))] }), showErrorMessage && error && (jsx("p", { className: "mt-1 text-red-500 dark:text-red-500 text-sm", children: error }))] }));
|
|
829
|
+
});
|
|
830
|
+
|
|
831
|
+
const typeStyles = {
|
|
832
|
+
success: 'bg-green-500 text-white',
|
|
833
|
+
error: 'bg-red-500 text-white',
|
|
834
|
+
info: 'bg-blue-500 text-white',
|
|
835
|
+
warning: 'bg-yellow-400 text-black',
|
|
836
|
+
};
|
|
837
|
+
const Toast = ({ message, type, onClose }) => {
|
|
838
|
+
return (jsx(Transition, { appear: true, show: true, enter: "transform transition duration-300", enterFrom: "opacity-0 translate-x-4", enterTo: "opacity-100 translate-x-0", leave: "transition duration-200 ease-in", leaveFrom: "opacity-100", leaveTo: "opacity-0", children: jsxs("div", { className: `flex items-center justify-between rounded-lg px-4 py-3 shadow-lg min-w-[240px] ${typeStyles[type]}`, children: [jsx("span", { children: message }), jsx("button", { onClick: onClose, className: "ml-3 text-xl leading-none hover:opacity-75", "aria-label": "Close toast", children: jsx(SvgX, { className: "size-5" }) })] }) }));
|
|
839
|
+
};
|
|
840
|
+
|
|
841
|
+
const ToastContext = createContext(undefined);
|
|
842
|
+
const useToast = () => {
|
|
843
|
+
const context = useContext(ToastContext);
|
|
844
|
+
if (!context)
|
|
845
|
+
throw new Error('useToast must be used within ToastProvider');
|
|
846
|
+
return context;
|
|
847
|
+
};
|
|
848
|
+
const ToastProvider = ({ children }) => {
|
|
849
|
+
const [toasts, setToasts] = useState([]);
|
|
850
|
+
const showToast = (message, options) => {
|
|
851
|
+
var _a, _b, _c;
|
|
852
|
+
const id = Date.now();
|
|
853
|
+
const newToast = {
|
|
854
|
+
id,
|
|
855
|
+
message,
|
|
856
|
+
type: (_a = options === null || options === void 0 ? void 0 : options.type) !== null && _a !== void 0 ? _a : 'info',
|
|
857
|
+
duration: (_b = options === null || options === void 0 ? void 0 : options.duration) !== null && _b !== void 0 ? _b : 3000,
|
|
858
|
+
autoClose: (_c = options === null || options === void 0 ? void 0 : options.autoClose) !== null && _c !== void 0 ? _c : true,
|
|
859
|
+
};
|
|
860
|
+
setToasts((prev) => [...prev, newToast]);
|
|
861
|
+
if (newToast.autoClose) {
|
|
862
|
+
setTimeout(() => closeToast(id), newToast.duration);
|
|
863
|
+
}
|
|
864
|
+
};
|
|
865
|
+
const closeToast = (id) => {
|
|
866
|
+
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
867
|
+
};
|
|
868
|
+
return (jsxs(ToastContext.Provider, { value: { showToast, closeToast }, children: [children, jsx("div", { className: "fixed top-4 right-4 z-50 space-y-3", children: toasts.map((toast) => (jsx(Toast, { ...toast, onClose: () => closeToast(toast.id) }, toast.id))) })] }));
|
|
869
|
+
};
|
|
870
|
+
|
|
871
|
+
export { Alert, Badge, Banner, BodyText, Breadcrumb, Button, Card, Checkbox, CheckboxGroup, DOTS, DetailedInformation, Dot, Drawer, Dropdown, EmptyState, EmptyTableRow, HeadingText, Input, Label, Loader, PASSWORD_PLACEHOLDER, PASSWORD_TYPE, Pagination, PasswordInput, RadioButton, RadioButtonGroup, RadioSwitch, RangeInput, SelectBox, TabelBody, TabelFoot, TabelHead, Table, TableCell, TableHeaderCell, TableRow, Tabs, Tag, TextContent, Textarea, ToastProvider, buildClassName, isArray, isEmpty, useDebounce, usePagination, useToast };
|
|
872
|
+
//# sourceMappingURL=react-tailwind.es.js.map
|