@juv/codego-react-ui 1.1.2 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +536 -451
- package/dist/index.d.cts +29 -3
- package/dist/index.d.ts +29 -3
- package/dist/index.global.js +1176 -1094
- package/dist/index.js +535 -453
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -34,6 +34,7 @@ __export(index_exports, {
|
|
|
34
34
|
Badge: () => Badge,
|
|
35
35
|
Breadcrumb: () => Breadcrumb,
|
|
36
36
|
Button: () => Button,
|
|
37
|
+
COLOR_PALETTE: () => COLOR_PALETTE,
|
|
37
38
|
Calendar: () => Calendar,
|
|
38
39
|
Card: () => Card,
|
|
39
40
|
CardContent: () => CardContent,
|
|
@@ -103,6 +104,7 @@ __export(index_exports, {
|
|
|
103
104
|
Tabs: () => Tabs,
|
|
104
105
|
TagInput: () => TagInput,
|
|
105
106
|
Textarea: () => Textarea,
|
|
107
|
+
ThemeProvider: () => ThemeProvider,
|
|
106
108
|
Timeline: () => Timeline,
|
|
107
109
|
ToastProvider: () => ToastProvider,
|
|
108
110
|
ToggleSwitch: () => ToggleSwitch,
|
|
@@ -111,6 +113,7 @@ __export(index_exports, {
|
|
|
111
113
|
TreeView: () => TreeView,
|
|
112
114
|
Widget: () => Widget,
|
|
113
115
|
Wizard: () => Wizard,
|
|
116
|
+
useTheme: () => useTheme,
|
|
114
117
|
useToast: () => useToast
|
|
115
118
|
});
|
|
116
119
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -122,9 +125,25 @@ var import_lucide_react = require("lucide-react");
|
|
|
122
125
|
// src/lib/utils.ts
|
|
123
126
|
var import_clsx = require("clsx");
|
|
124
127
|
var import_tailwind_merge = require("tailwind-merge");
|
|
128
|
+
var ReactDOM = __toESM(require("react-dom"), 1);
|
|
125
129
|
function cn(...inputs) {
|
|
126
130
|
return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
|
|
127
131
|
}
|
|
132
|
+
function getPortalPosition(triggerEl, dropdownHeight = 300, preferredPlacement = "bottom") {
|
|
133
|
+
const r = triggerEl.getBoundingClientRect();
|
|
134
|
+
const spaceBelow = window.innerHeight - r.bottom;
|
|
135
|
+
const spaceAbove = r.top;
|
|
136
|
+
const placement = preferredPlacement === "bottom" && spaceBelow < dropdownHeight && spaceAbove > spaceBelow ? "top" : preferredPlacement;
|
|
137
|
+
return {
|
|
138
|
+
top: placement === "bottom" ? r.bottom + 4 : r.top - 4,
|
|
139
|
+
left: r.left,
|
|
140
|
+
width: r.width,
|
|
141
|
+
placement
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function FloatingPortal({ children }) {
|
|
145
|
+
return ReactDOM.createPortal(children, document.body);
|
|
146
|
+
}
|
|
128
147
|
|
|
129
148
|
// src/components/ui/accordion.tsx
|
|
130
149
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -917,6 +936,8 @@ function ColorPicker({
|
|
|
917
936
|
const [opacity, setOpacity] = React7.useState(100);
|
|
918
937
|
const [recent, setRecent] = React7.useState([]);
|
|
919
938
|
const ref = React7.useRef(null);
|
|
939
|
+
const triggerRef = React7.useRef(null);
|
|
940
|
+
const [dropStyle, setDropStyle] = React7.useState({});
|
|
920
941
|
const color = controlled ?? internal;
|
|
921
942
|
React7.useEffect(() => {
|
|
922
943
|
setHex(color);
|
|
@@ -928,6 +949,19 @@ function ColorPicker({
|
|
|
928
949
|
document.addEventListener("mousedown", handler);
|
|
929
950
|
return () => document.removeEventListener("mousedown", handler);
|
|
930
951
|
}, []);
|
|
952
|
+
function openPicker() {
|
|
953
|
+
if (triggerRef.current) {
|
|
954
|
+
const pos = getPortalPosition(triggerRef.current, 280);
|
|
955
|
+
setDropStyle({
|
|
956
|
+
position: "fixed",
|
|
957
|
+
top: pos.placement === "bottom" ? pos.top : void 0,
|
|
958
|
+
bottom: pos.placement === "top" ? window.innerHeight - pos.top : void 0,
|
|
959
|
+
left: pos.left,
|
|
960
|
+
zIndex: 9999
|
|
961
|
+
});
|
|
962
|
+
}
|
|
963
|
+
setOpen(true);
|
|
964
|
+
}
|
|
931
965
|
function apply(c) {
|
|
932
966
|
if (!controlled) setInternal(c);
|
|
933
967
|
onChange?.(c);
|
|
@@ -942,9 +976,10 @@ function ColorPicker({
|
|
|
942
976
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
943
977
|
"button",
|
|
944
978
|
{
|
|
979
|
+
ref: triggerRef,
|
|
945
980
|
type: "button",
|
|
946
981
|
disabled,
|
|
947
|
-
onClick: () => setOpen(
|
|
982
|
+
onClick: () => open ? setOpen(false) : openPicker(),
|
|
948
983
|
className: cn(
|
|
949
984
|
"flex items-center gap-2 h-9 px-3 rounded-xl border border-border bg-background text-sm transition-colors hover:border-primary/40 focus:outline-none focus:ring-2 focus:ring-ring",
|
|
950
985
|
disabled && "opacity-50 cursor-not-allowed pointer-events-none"
|
|
@@ -955,7 +990,7 @@ function ColorPicker({
|
|
|
955
990
|
]
|
|
956
991
|
}
|
|
957
992
|
),
|
|
958
|
-
open && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "
|
|
993
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(FloatingPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "w-56 rounded-xl border border-border glass shadow-2xl p-3 space-y-3", style: dropStyle, children: [
|
|
959
994
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
960
995
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
961
996
|
"input",
|
|
@@ -1010,10 +1045,7 @@ function ColorPicker({
|
|
|
1010
1045
|
apply(s);
|
|
1011
1046
|
setHex(s);
|
|
1012
1047
|
},
|
|
1013
|
-
className: cn(
|
|
1014
|
-
"h-6 w-6 rounded-md border transition-transform hover:scale-110",
|
|
1015
|
-
color === s ? "border-primary ring-1 ring-primary" : "border-border/60"
|
|
1016
|
-
),
|
|
1048
|
+
className: cn("h-6 w-6 rounded-md border transition-transform hover:scale-110", color === s ? "border-primary ring-1 ring-primary" : "border-border/60"),
|
|
1017
1049
|
style: { backgroundColor: s },
|
|
1018
1050
|
title: s
|
|
1019
1051
|
},
|
|
@@ -1037,7 +1069,7 @@ function ColorPicker({
|
|
|
1037
1069
|
s
|
|
1038
1070
|
)) })
|
|
1039
1071
|
] })
|
|
1040
|
-
] })
|
|
1072
|
+
] }) })
|
|
1041
1073
|
] });
|
|
1042
1074
|
}
|
|
1043
1075
|
|
|
@@ -1064,7 +1096,9 @@ function Combobox({
|
|
|
1064
1096
|
const [open, setOpen] = React8.useState(false);
|
|
1065
1097
|
const [query, setQuery] = React8.useState("");
|
|
1066
1098
|
const ref = React8.useRef(null);
|
|
1099
|
+
const triggerRef = React8.useRef(null);
|
|
1067
1100
|
const inputRef = React8.useRef(null);
|
|
1101
|
+
const [dropStyle, setDropStyle] = React8.useState({});
|
|
1068
1102
|
const selected = controlled ?? internal;
|
|
1069
1103
|
function update(val) {
|
|
1070
1104
|
if (!controlled) setInternal(val);
|
|
@@ -1088,6 +1122,20 @@ function Combobox({
|
|
|
1088
1122
|
e.stopPropagation();
|
|
1089
1123
|
update(multiple ? [] : "");
|
|
1090
1124
|
}
|
|
1125
|
+
const openDropdown = () => {
|
|
1126
|
+
if (triggerRef.current) {
|
|
1127
|
+
const pos = getPortalPosition(triggerRef.current, 300);
|
|
1128
|
+
setDropStyle({
|
|
1129
|
+
position: "fixed",
|
|
1130
|
+
top: pos.placement === "bottom" ? pos.top : void 0,
|
|
1131
|
+
bottom: pos.placement === "top" ? window.innerHeight - pos.top : void 0,
|
|
1132
|
+
left: pos.left,
|
|
1133
|
+
width: pos.width,
|
|
1134
|
+
zIndex: 9999
|
|
1135
|
+
});
|
|
1136
|
+
}
|
|
1137
|
+
setOpen(true);
|
|
1138
|
+
};
|
|
1091
1139
|
React8.useEffect(() => {
|
|
1092
1140
|
function handler(e) {
|
|
1093
1141
|
if (ref.current && !ref.current.contains(e.target)) {
|
|
@@ -1101,13 +1149,10 @@ function Combobox({
|
|
|
1101
1149
|
React8.useEffect(() => {
|
|
1102
1150
|
if (open) setTimeout(() => inputRef.current?.focus(), 50);
|
|
1103
1151
|
}, [open]);
|
|
1104
|
-
const filtered = options.filter(
|
|
1105
|
-
(o) => o.label.toLowerCase().includes(query.toLowerCase())
|
|
1106
|
-
);
|
|
1152
|
+
const filtered = options.filter((o) => o.label.toLowerCase().includes(query.toLowerCase()));
|
|
1107
1153
|
const groups = Array.from(new Set(filtered.map((o) => o.group ?? ""))).filter(Boolean);
|
|
1108
1154
|
const ungrouped = filtered.filter((o) => !o.group);
|
|
1109
1155
|
const showCreate = creatable && query && !options.find((o) => o.label.toLowerCase() === query.toLowerCase());
|
|
1110
|
-
const selectedLabels = multiple ? selected.map((v) => options.find((o) => o.value === v)?.label ?? v) : options.find((o) => o.value === selected)?.label;
|
|
1111
1156
|
const hasValue = multiple ? selected.length > 0 : !!selected;
|
|
1112
1157
|
function renderOptions(opts) {
|
|
1113
1158
|
return opts.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
@@ -1135,9 +1180,10 @@ function Combobox({
|
|
|
1135
1180
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
1136
1181
|
"button",
|
|
1137
1182
|
{
|
|
1183
|
+
ref: triggerRef,
|
|
1138
1184
|
type: "button",
|
|
1139
1185
|
disabled,
|
|
1140
|
-
onClick: () => setOpen(
|
|
1186
|
+
onClick: () => open ? setOpen(false) : openDropdown(),
|
|
1141
1187
|
className: cn(
|
|
1142
1188
|
"flex w-full items-center justify-between gap-2 rounded-xl border border-border bg-background px-3 py-2 text-sm transition-colors",
|
|
1143
1189
|
"hover:border-primary/40 focus:outline-none focus:ring-2 focus:ring-ring",
|
|
@@ -1145,7 +1191,7 @@ function Combobox({
|
|
|
1145
1191
|
disabled && "opacity-50 cursor-not-allowed pointer-events-none"
|
|
1146
1192
|
),
|
|
1147
1193
|
children: [
|
|
1148
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: cn("flex-1 truncate text-left", !hasValue && "text-muted-foreground"), children: multiple ? selected.length > 0 ? `${selected.length} selected` : placeholder :
|
|
1194
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: cn("flex-1 truncate text-left", !hasValue && "text-muted-foreground"), children: multiple ? selected.length > 0 ? `${selected.length} selected` : placeholder : options.find((o) => o.value === selected)?.label || placeholder }),
|
|
1149
1195
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "flex items-center gap-1 shrink-0", children: [
|
|
1150
1196
|
clearable && hasValue && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { onClick: clear, className: "text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react5.X, { className: "h-3.5 w-3.5" }) }),
|
|
1151
1197
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react5.ChevronDown, { className: cn("h-4 w-4 text-muted-foreground transition-transform", open && "rotate-180") })
|
|
@@ -1153,50 +1199,57 @@ function Combobox({
|
|
|
1153
1199
|
]
|
|
1154
1200
|
}
|
|
1155
1201
|
),
|
|
1156
|
-
open && /* @__PURE__ */ (0, import_jsx_runtime10.
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1202
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(FloatingPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
1203
|
+
"div",
|
|
1204
|
+
{
|
|
1205
|
+
className: "rounded-xl border border-border glass shadow-2xl overflow-hidden",
|
|
1206
|
+
style: dropStyle,
|
|
1207
|
+
children: [
|
|
1208
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-2 border-b border-border px-3 py-2", children: [
|
|
1209
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react5.Search, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
|
|
1210
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1211
|
+
"input",
|
|
1212
|
+
{
|
|
1213
|
+
ref: inputRef,
|
|
1214
|
+
value: query,
|
|
1215
|
+
onChange: (e) => setQuery(e.target.value),
|
|
1216
|
+
placeholder: searchPlaceholder,
|
|
1217
|
+
className: "flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
|
|
1218
|
+
}
|
|
1219
|
+
)
|
|
1220
|
+
] }),
|
|
1221
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "overflow-y-auto p-1", style: { maxHeight }, children: [
|
|
1222
|
+
showCreate && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
1223
|
+
"button",
|
|
1224
|
+
{
|
|
1225
|
+
type: "button",
|
|
1226
|
+
onClick: () => {
|
|
1227
|
+
toggle(query);
|
|
1228
|
+
setQuery("");
|
|
1229
|
+
},
|
|
1230
|
+
className: "flex w-full items-center gap-2 px-3 py-2 text-sm rounded-lg hover:bg-accent text-primary",
|
|
1231
|
+
children: [
|
|
1232
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react5.Plus, { className: "h-3.5 w-3.5" }),
|
|
1233
|
+
'Create "',
|
|
1234
|
+
query,
|
|
1235
|
+
'"'
|
|
1236
|
+
]
|
|
1237
|
+
}
|
|
1238
|
+
),
|
|
1239
|
+
groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
|
|
1240
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "px-3 py-1 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground", children: group }),
|
|
1241
|
+
renderOptions(filtered.filter((o) => o.group === group))
|
|
1242
|
+
] }, group)),
|
|
1243
|
+
renderOptions(ungrouped),
|
|
1244
|
+
filtered.length === 0 && !showCreate && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "No results" })
|
|
1245
|
+
] }),
|
|
1246
|
+
multiple && selected.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "border-t border-border px-3 py-2 flex flex-wrap gap-1", children: selected.map((v) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "inline-flex items-center gap-1 rounded-full bg-primary/15 text-primary text-xs px-2 py-0.5", children: [
|
|
1247
|
+
options.find((o) => o.value === v)?.label ?? v,
|
|
1248
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", onClick: () => toggle(v), className: "opacity-60 hover:opacity-100", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react5.X, { className: "h-3 w-3" }) })
|
|
1249
|
+
] }, v)) })
|
|
1250
|
+
]
|
|
1251
|
+
}
|
|
1252
|
+
) })
|
|
1200
1253
|
] });
|
|
1201
1254
|
}
|
|
1202
1255
|
|
|
@@ -1656,12 +1709,12 @@ function DonutChart({ data, color, height, showValues, unit }) {
|
|
|
1656
1709
|
const total = data.reduce((s, d) => s + d.value, 0) || 1;
|
|
1657
1710
|
const cx = 80, cy = height / 2, r = Math.min(cx, cy) - 10, inner = r * 0.58;
|
|
1658
1711
|
let angle = -Math.PI / 2;
|
|
1659
|
-
const
|
|
1712
|
+
const defaultColors = ["primary", "info", "success", "warning", "danger"];
|
|
1660
1713
|
const slices = data.map((d, i) => {
|
|
1661
1714
|
const sweep = d.value / total * 2 * Math.PI;
|
|
1662
1715
|
const start = angle;
|
|
1663
1716
|
angle += sweep;
|
|
1664
|
-
const c = d.color ??
|
|
1717
|
+
const c = d.color ?? defaultColors[i % defaultColors.length];
|
|
1665
1718
|
return { ...d, start, sweep, color: c };
|
|
1666
1719
|
});
|
|
1667
1720
|
const arc = (cx2, cy2, r2, start, end) => {
|
|
@@ -2153,6 +2206,20 @@ function parseValue(value, mode) {
|
|
|
2153
2206
|
return null;
|
|
2154
2207
|
}
|
|
2155
2208
|
}
|
|
2209
|
+
function getAnchorStyle(anchorEl, wide = false) {
|
|
2210
|
+
if (!anchorEl) return { position: "fixed", top: 0, left: 0, zIndex: 9999 };
|
|
2211
|
+
const r = anchorEl.getBoundingClientRect();
|
|
2212
|
+
const spaceBelow = window.innerHeight - r.bottom;
|
|
2213
|
+
const dropH = wide ? 320 : 300;
|
|
2214
|
+
const placement = spaceBelow < dropH && r.top > spaceBelow ? "top" : "bottom";
|
|
2215
|
+
return {
|
|
2216
|
+
position: "fixed",
|
|
2217
|
+
top: placement === "bottom" ? r.bottom + 4 : void 0,
|
|
2218
|
+
bottom: placement === "top" ? window.innerHeight - r.top + 4 : void 0,
|
|
2219
|
+
left: r.left,
|
|
2220
|
+
zIndex: 9999
|
|
2221
|
+
};
|
|
2222
|
+
}
|
|
2156
2223
|
function TimePicker({
|
|
2157
2224
|
selected,
|
|
2158
2225
|
disabledDateTimes,
|
|
@@ -2220,25 +2287,9 @@ function Calendar2({
|
|
|
2220
2287
|
const isDisabled = (d) => disabledDates?.includes((0, import_date_fns.format)(d, "yyyy-MM-dd")) ?? false;
|
|
2221
2288
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "p-3 select-none", children: [
|
|
2222
2289
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center justify-between mb-3", children: [
|
|
2223
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2224
|
-
"button",
|
|
2225
|
-
{
|
|
2226
|
-
type: "button",
|
|
2227
|
-
onClick: onPrevMonth,
|
|
2228
|
-
className: "p-1 rounded hover:bg-white/10 text-muted-foreground hover:text-foreground transition-colors",
|
|
2229
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react10.ChevronLeft, { size: 16 })
|
|
2230
|
-
}
|
|
2231
|
-
),
|
|
2290
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { type: "button", onClick: onPrevMonth, className: "p-1 rounded hover:bg-white/10 text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react10.ChevronLeft, { size: 16 }) }),
|
|
2232
2291
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-sm font-semibold text-foreground", children: (0, import_date_fns.format)(month, "MMMM yyyy") }),
|
|
2233
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2234
|
-
"button",
|
|
2235
|
-
{
|
|
2236
|
-
type: "button",
|
|
2237
|
-
onClick: onNextMonth,
|
|
2238
|
-
className: "p-1 rounded hover:bg-white/10 text-muted-foreground hover:text-foreground transition-colors",
|
|
2239
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react10.ChevronRight, { size: 16 })
|
|
2240
|
-
}
|
|
2241
|
-
)
|
|
2292
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { type: "button", onClick: onNextMonth, className: "p-1 rounded hover:bg-white/10 text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react10.ChevronRight, { size: 16 }) })
|
|
2242
2293
|
] }),
|
|
2243
2294
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "grid grid-cols-7 mb-1", children: DAYS2.map((d) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "text-center text-xs text-muted-foreground py-1", children: d }, d)) }),
|
|
2244
2295
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "grid grid-cols-7 gap-y-1", children: days.map((d, i) => {
|
|
@@ -2273,136 +2324,44 @@ function DatePickerPopup({
|
|
|
2273
2324
|
disabledDates,
|
|
2274
2325
|
disabledDateTimes,
|
|
2275
2326
|
onChange,
|
|
2276
|
-
onClose
|
|
2327
|
+
onClose,
|
|
2328
|
+
anchorEl
|
|
2277
2329
|
}) {
|
|
2278
2330
|
const parsed = parseValue(value, mode);
|
|
2279
2331
|
const [month, setMonth] = React13.useState(parsed ?? /* @__PURE__ */ new Date());
|
|
2280
2332
|
const [selected, setSelected] = React13.useState(parsed);
|
|
2281
|
-
const
|
|
2333
|
+
const anchorStyle = getAnchorStyle(anchorEl ?? null, mode === "dateTime");
|
|
2282
2334
|
const commit = (d) => {
|
|
2283
|
-
if (mode === "date")
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
onChange((0, import_date_fns.format)(d, "yyyy-MM-dd'T'HH:mm"));
|
|
2287
|
-
} else {
|
|
2288
|
-
onChange((0, import_date_fns.format)(d, "HH:mm"));
|
|
2289
|
-
}
|
|
2335
|
+
if (mode === "date") onChange((0, import_date_fns.format)(d, "yyyy-MM-dd"));
|
|
2336
|
+
else if (mode === "dateTime") onChange((0, import_date_fns.format)(d, "yyyy-MM-dd'T'HH:mm"));
|
|
2337
|
+
else onChange((0, import_date_fns.format)(d, "HH:mm"));
|
|
2290
2338
|
setSelected(d);
|
|
2291
2339
|
};
|
|
2292
2340
|
const handleDayClick = (d) => {
|
|
2293
2341
|
const base = selected ?? /* @__PURE__ */ new Date();
|
|
2294
|
-
|
|
2295
|
-
commit(merged);
|
|
2342
|
+
commit((0, import_date_fns.setMinutes)((0, import_date_fns.setHours)(d, (0, import_date_fns.getHours)(base)), (0, import_date_fns.getMinutes)(base)));
|
|
2296
2343
|
};
|
|
2297
2344
|
const handleTimeChange = (h, m) => {
|
|
2298
|
-
|
|
2299
|
-
const merged = (0, import_date_fns.setMinutes)((0, import_date_fns.setHours)(base, h), m);
|
|
2300
|
-
commit(merged);
|
|
2345
|
+
commit((0, import_date_fns.setMinutes)((0, import_date_fns.setHours)(selected ?? /* @__PURE__ */ new Date(), h), m));
|
|
2301
2346
|
};
|
|
2302
2347
|
const datePrefix = selected ? (0, import_date_fns.format)(selected, "yyyy-MM-dd") : void 0;
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2348
|
+
const footer = (label) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "border-t border-white/10 px-3 py-2 flex items-center justify-between", children: [
|
|
2349
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-xs text-muted-foreground", children: label }),
|
|
2350
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2351
|
+
"button",
|
|
2306
2352
|
{
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
children:
|
|
2311
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex", children: [
|
|
2312
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex-1 min-w-[240px]", children: [
|
|
2313
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-xs font-medium text-muted-foreground px-3 pt-3 pb-1", children: "Date" }),
|
|
2314
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2315
|
-
Calendar2,
|
|
2316
|
-
{
|
|
2317
|
-
selected,
|
|
2318
|
-
month,
|
|
2319
|
-
disabledDates,
|
|
2320
|
-
onDayClick: handleDayClick,
|
|
2321
|
-
onPrevMonth: () => setMonth((m) => (0, import_date_fns.subMonths)(m, 1)),
|
|
2322
|
-
onNextMonth: () => setMonth((m) => (0, import_date_fns.addMonths)(m, 1))
|
|
2323
|
-
}
|
|
2324
|
-
)
|
|
2325
|
-
] }),
|
|
2326
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "w-px bg-white/10 my-3" }),
|
|
2327
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex-1 min-w-[140px] flex flex-col", children: [
|
|
2328
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-xs font-medium text-muted-foreground px-3 pt-3 pb-1", children: "Time" }),
|
|
2329
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex gap-2 px-3 pb-3 flex-1", children: [
|
|
2330
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex-1", children: [
|
|
2331
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-xs text-muted-foreground mb-1 text-center", children: "HH" }),
|
|
2332
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "grid grid-cols-1 gap-1 max-h-52 overflow-y-auto", children: HOURS.map((h) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2333
|
-
"button",
|
|
2334
|
-
{
|
|
2335
|
-
type: "button",
|
|
2336
|
-
disabled: MINUTES.every((m) => {
|
|
2337
|
-
if (!disabledDateTimes || !datePrefix) return false;
|
|
2338
|
-
return disabledDateTimes.includes(`${datePrefix}T${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`);
|
|
2339
|
-
}),
|
|
2340
|
-
onClick: () => handleTimeChange(h, selected ? (0, import_date_fns.getMinutes)(selected) : 0),
|
|
2341
|
-
className: cn(
|
|
2342
|
-
"text-xs rounded py-1 transition-colors",
|
|
2343
|
-
selected && (0, import_date_fns.getHours)(selected) === h ? "bg-primary text-primary-foreground" : "hover:bg-white/10 text-foreground",
|
|
2344
|
-
MINUTES.every((m) => {
|
|
2345
|
-
if (!disabledDateTimes || !datePrefix) return false;
|
|
2346
|
-
return disabledDateTimes.includes(`${datePrefix}T${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`);
|
|
2347
|
-
}) && "opacity-30 cursor-not-allowed line-through"
|
|
2348
|
-
),
|
|
2349
|
-
children: String(h).padStart(2, "0")
|
|
2350
|
-
},
|
|
2351
|
-
h
|
|
2352
|
-
)) })
|
|
2353
|
-
] }),
|
|
2354
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "w-12", children: [
|
|
2355
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-xs text-muted-foreground mb-1 text-center", children: "MM" }),
|
|
2356
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "grid grid-cols-1 gap-1 max-h-52 overflow-y-auto", children: MINUTES.map((m) => {
|
|
2357
|
-
const h = selected ? (0, import_date_fns.getHours)(selected) : 0;
|
|
2358
|
-
const isDisabled = disabledDateTimes && datePrefix ? disabledDateTimes.includes(`${datePrefix}T${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`) : false;
|
|
2359
|
-
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
2360
|
-
"button",
|
|
2361
|
-
{
|
|
2362
|
-
type: "button",
|
|
2363
|
-
disabled: isDisabled,
|
|
2364
|
-
onClick: () => handleTimeChange(h, m),
|
|
2365
|
-
className: cn(
|
|
2366
|
-
"text-xs rounded py-1 transition-colors",
|
|
2367
|
-
selected && (0, import_date_fns.getMinutes)(selected) === m ? "bg-primary text-primary-foreground" : "hover:bg-white/10 text-foreground",
|
|
2368
|
-
isDisabled && "opacity-30 cursor-not-allowed line-through"
|
|
2369
|
-
),
|
|
2370
|
-
children: [
|
|
2371
|
-
":",
|
|
2372
|
-
String(m).padStart(2, "0")
|
|
2373
|
-
]
|
|
2374
|
-
},
|
|
2375
|
-
m
|
|
2376
|
-
);
|
|
2377
|
-
}) })
|
|
2378
|
-
] })
|
|
2379
|
-
] })
|
|
2380
|
-
] })
|
|
2381
|
-
] }),
|
|
2382
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "border-t border-white/10 px-3 py-2 flex items-center justify-between", children: [
|
|
2383
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-xs text-muted-foreground", children: selected ? (0, import_date_fns.format)(selected, "MMM d, yyyy HH:mm") : "No date selected" }),
|
|
2384
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2385
|
-
"button",
|
|
2386
|
-
{
|
|
2387
|
-
type: "button",
|
|
2388
|
-
onClick: onClose,
|
|
2389
|
-
className: "text-xs rounded-lg bg-primary text-primary-foreground px-3 py-1 hover:opacity-90 transition-opacity",
|
|
2390
|
-
children: "Done"
|
|
2391
|
-
}
|
|
2392
|
-
)
|
|
2393
|
-
] })
|
|
2394
|
-
]
|
|
2353
|
+
type: "button",
|
|
2354
|
+
onClick: onClose,
|
|
2355
|
+
className: "text-xs rounded-lg bg-primary text-primary-foreground px-3 py-1 hover:opacity-90 transition-opacity",
|
|
2356
|
+
children: "Done"
|
|
2395
2357
|
}
|
|
2396
|
-
)
|
|
2397
|
-
}
|
|
2398
|
-
|
|
2399
|
-
"div",
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
style: { top: "100%", left: 0 },
|
|
2404
|
-
children: [
|
|
2405
|
-
mode === "date" && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
2358
|
+
)
|
|
2359
|
+
] });
|
|
2360
|
+
if (mode === "dateTime") {
|
|
2361
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(FloatingPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "rounded-xl border border-white/10 bg-card shadow-xl backdrop-blur-sm", style: anchorStyle, children: [
|
|
2362
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex", children: [
|
|
2363
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex-1 min-w-[240px]", children: [
|
|
2364
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-xs font-medium text-muted-foreground px-3 pt-3 pb-1", children: "Date" }),
|
|
2406
2365
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2407
2366
|
Calendar2,
|
|
2408
2367
|
{
|
|
@@ -2413,46 +2372,91 @@ function DatePickerPopup({
|
|
|
2413
2372
|
onPrevMonth: () => setMonth((m) => (0, import_date_fns.subMonths)(m, 1)),
|
|
2414
2373
|
onNextMonth: () => setMonth((m) => (0, import_date_fns.addMonths)(m, 1))
|
|
2415
2374
|
}
|
|
2416
|
-
)
|
|
2417
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "border-t border-white/10 px-3 py-2 flex items-center justify-between", children: [
|
|
2418
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-xs text-muted-foreground", children: selected ? (0, import_date_fns.format)(selected, "MMM d, yyyy") : "No date selected" }),
|
|
2419
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2420
|
-
"button",
|
|
2421
|
-
{
|
|
2422
|
-
type: "button",
|
|
2423
|
-
onClick: onClose,
|
|
2424
|
-
className: "text-xs rounded-lg bg-primary text-primary-foreground px-3 py-1 hover:opacity-90 transition-opacity",
|
|
2425
|
-
children: "Done"
|
|
2426
|
-
}
|
|
2427
|
-
)
|
|
2428
|
-
] })
|
|
2375
|
+
)
|
|
2429
2376
|
] }),
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2377
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "w-px bg-white/10 my-3" }),
|
|
2378
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex-1 min-w-[140px] flex flex-col", children: [
|
|
2379
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-xs font-medium text-muted-foreground px-3 pt-3 pb-1", children: "Time" }),
|
|
2380
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex gap-2 px-3 pb-3 flex-1", children: [
|
|
2381
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex-1", children: [
|
|
2382
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-xs text-muted-foreground mb-1 text-center", children: "HH" }),
|
|
2383
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "grid grid-cols-1 gap-1 max-h-52 overflow-y-auto", children: HOURS.map((h) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2384
|
+
"button",
|
|
2385
|
+
{
|
|
2386
|
+
type: "button",
|
|
2387
|
+
disabled: MINUTES.every((m) => {
|
|
2388
|
+
if (!disabledDateTimes || !datePrefix) return false;
|
|
2389
|
+
return disabledDateTimes.includes(`${datePrefix}T${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`);
|
|
2390
|
+
}),
|
|
2391
|
+
onClick: () => handleTimeChange(h, selected ? (0, import_date_fns.getMinutes)(selected) : 0),
|
|
2392
|
+
className: cn(
|
|
2393
|
+
"text-xs rounded py-1 transition-colors",
|
|
2394
|
+
selected && (0, import_date_fns.getHours)(selected) === h ? "bg-primary text-primary-foreground" : "hover:bg-white/10 text-foreground"
|
|
2395
|
+
),
|
|
2396
|
+
children: String(h).padStart(2, "0")
|
|
2397
|
+
},
|
|
2398
|
+
h
|
|
2399
|
+
)) })
|
|
2400
|
+
] }),
|
|
2401
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "w-12", children: [
|
|
2402
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-xs text-muted-foreground mb-1 text-center", children: "MM" }),
|
|
2403
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "grid grid-cols-1 gap-1 max-h-52 overflow-y-auto", children: MINUTES.map((m) => {
|
|
2404
|
+
const h = selected ? (0, import_date_fns.getHours)(selected) : 0;
|
|
2405
|
+
const dis = disabledDateTimes && datePrefix ? disabledDateTimes.includes(`${datePrefix}T${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`) : false;
|
|
2406
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
2407
|
+
"button",
|
|
2408
|
+
{
|
|
2409
|
+
type: "button",
|
|
2410
|
+
disabled: dis,
|
|
2411
|
+
onClick: () => handleTimeChange(h, m),
|
|
2412
|
+
className: cn(
|
|
2413
|
+
"text-xs rounded py-1 transition-colors",
|
|
2414
|
+
selected && (0, import_date_fns.getMinutes)(selected) === m ? "bg-primary text-primary-foreground" : "hover:bg-white/10 text-foreground",
|
|
2415
|
+
dis && "opacity-30 cursor-not-allowed line-through"
|
|
2416
|
+
),
|
|
2417
|
+
children: [
|
|
2418
|
+
":",
|
|
2419
|
+
String(m).padStart(2, "0")
|
|
2420
|
+
]
|
|
2421
|
+
},
|
|
2422
|
+
m
|
|
2423
|
+
);
|
|
2424
|
+
}) })
|
|
2425
|
+
] })
|
|
2451
2426
|
] })
|
|
2452
2427
|
] })
|
|
2453
|
-
]
|
|
2454
|
-
|
|
2455
|
-
|
|
2428
|
+
] }),
|
|
2429
|
+
footer(selected ? (0, import_date_fns.format)(selected, "MMM d, yyyy HH:mm") : "No date selected")
|
|
2430
|
+
] }) });
|
|
2431
|
+
}
|
|
2432
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(FloatingPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "rounded-xl border border-white/10 bg-card shadow-xl backdrop-blur-sm min-w-[260px]", style: anchorStyle, children: [
|
|
2433
|
+
mode === "date" && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
2434
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2435
|
+
Calendar2,
|
|
2436
|
+
{
|
|
2437
|
+
selected,
|
|
2438
|
+
month,
|
|
2439
|
+
disabledDates,
|
|
2440
|
+
onDayClick: handleDayClick,
|
|
2441
|
+
onPrevMonth: () => setMonth((m) => (0, import_date_fns.subMonths)(m, 1)),
|
|
2442
|
+
onNextMonth: () => setMonth((m) => (0, import_date_fns.addMonths)(m, 1))
|
|
2443
|
+
}
|
|
2444
|
+
),
|
|
2445
|
+
footer(selected ? (0, import_date_fns.format)(selected, "MMM d, yyyy") : "No date selected")
|
|
2446
|
+
] }),
|
|
2447
|
+
mode === "time" && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
2448
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2449
|
+
TimePicker,
|
|
2450
|
+
{
|
|
2451
|
+
selected,
|
|
2452
|
+
disabledDateTimes,
|
|
2453
|
+
datePrefix,
|
|
2454
|
+
onChange: handleTimeChange
|
|
2455
|
+
}
|
|
2456
|
+
),
|
|
2457
|
+
footer(selected ? (0, import_date_fns.format)(selected, "HH:mm") : "No time selected")
|
|
2458
|
+
] })
|
|
2459
|
+
] }) });
|
|
2456
2460
|
}
|
|
2457
2461
|
|
|
2458
2462
|
// src/components/ui/date-range-picker.tsx
|
|
@@ -2490,6 +2494,8 @@ function DateRangePicker({
|
|
|
2490
2494
|
const [viewMonth, setViewMonth] = React14.useState(today.getMonth());
|
|
2491
2495
|
const [viewYear, setViewYear] = React14.useState(today.getFullYear());
|
|
2492
2496
|
const ref = React14.useRef(null);
|
|
2497
|
+
const triggerRef = React14.useRef(null);
|
|
2498
|
+
const [dropStyle, setDropStyle] = React14.useState({});
|
|
2493
2499
|
const range2 = controlled ?? internal;
|
|
2494
2500
|
React14.useEffect(() => {
|
|
2495
2501
|
function handler(e) {
|
|
@@ -2502,6 +2508,19 @@ function DateRangePicker({
|
|
|
2502
2508
|
if (!controlled) setInternal(r);
|
|
2503
2509
|
onChange?.(r);
|
|
2504
2510
|
}
|
|
2511
|
+
function openPicker() {
|
|
2512
|
+
if (triggerRef.current) {
|
|
2513
|
+
const pos = getPortalPosition(triggerRef.current, 340);
|
|
2514
|
+
setDropStyle({
|
|
2515
|
+
position: "fixed",
|
|
2516
|
+
top: pos.placement === "bottom" ? pos.top : void 0,
|
|
2517
|
+
bottom: pos.placement === "top" ? window.innerHeight - pos.top : void 0,
|
|
2518
|
+
left: pos.left,
|
|
2519
|
+
zIndex: 9999
|
|
2520
|
+
});
|
|
2521
|
+
}
|
|
2522
|
+
setOpen(true);
|
|
2523
|
+
}
|
|
2505
2524
|
function selectDay(d) {
|
|
2506
2525
|
if (selecting === "from") {
|
|
2507
2526
|
update({ from: d, to: null });
|
|
@@ -2536,9 +2555,10 @@ function DateRangePicker({
|
|
|
2536
2555
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
2537
2556
|
"button",
|
|
2538
2557
|
{
|
|
2558
|
+
ref: triggerRef,
|
|
2539
2559
|
type: "button",
|
|
2540
2560
|
disabled,
|
|
2541
|
-
onClick: () => setOpen(
|
|
2561
|
+
onClick: () => open ? setOpen(false) : openPicker(),
|
|
2542
2562
|
className: cn(
|
|
2543
2563
|
"flex w-full items-center gap-2 rounded-xl border border-border bg-background px-3 py-2 text-sm transition-colors",
|
|
2544
2564
|
"hover:border-primary/40 focus:outline-none focus:ring-2 focus:ring-ring",
|
|
@@ -2564,25 +2584,41 @@ function DateRangePicker({
|
|
|
2564
2584
|
]
|
|
2565
2585
|
}
|
|
2566
2586
|
),
|
|
2567
|
-
open && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "
|
|
2587
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(FloatingPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "rounded-xl border border-border glass shadow-2xl p-4 w-72", style: dropStyle, children: [
|
|
2568
2588
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center justify-between mb-3", children: [
|
|
2569
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2589
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2590
|
+
"button",
|
|
2591
|
+
{
|
|
2592
|
+
type: "button",
|
|
2593
|
+
onClick: () => {
|
|
2594
|
+
if (viewMonth === 0) {
|
|
2595
|
+
setViewMonth(11);
|
|
2596
|
+
setViewYear((y) => y - 1);
|
|
2597
|
+
} else setViewMonth((m) => m - 1);
|
|
2598
|
+
},
|
|
2599
|
+
className: "p-1 rounded-md hover:bg-accent transition-colors",
|
|
2600
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react11.ChevronLeft, { className: "h-4 w-4" })
|
|
2601
|
+
}
|
|
2602
|
+
),
|
|
2575
2603
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "text-sm font-semibold", children: [
|
|
2576
2604
|
MONTHS2[viewMonth],
|
|
2577
2605
|
" ",
|
|
2578
2606
|
viewYear
|
|
2579
2607
|
] }),
|
|
2580
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2608
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2609
|
+
"button",
|
|
2610
|
+
{
|
|
2611
|
+
type: "button",
|
|
2612
|
+
onClick: () => {
|
|
2613
|
+
if (viewMonth === 11) {
|
|
2614
|
+
setViewMonth(0);
|
|
2615
|
+
setViewYear((y) => y + 1);
|
|
2616
|
+
} else setViewMonth((m) => m + 1);
|
|
2617
|
+
},
|
|
2618
|
+
className: "p-1 rounded-md hover:bg-accent transition-colors",
|
|
2619
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react11.ChevronRight, { className: "h-4 w-4" })
|
|
2620
|
+
}
|
|
2621
|
+
)
|
|
2586
2622
|
] }),
|
|
2587
2623
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "grid grid-cols-7 mb-1", children: DAYS3.map((d) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "text-center text-[10px] font-semibold text-muted-foreground py-1", children: d }, d)) }),
|
|
2588
2624
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "grid grid-cols-7 gap-y-0.5", children: days.map((d, i) => {
|
|
@@ -2617,7 +2653,7 @@ function DateRangePicker({
|
|
|
2617
2653
|
);
|
|
2618
2654
|
}) }),
|
|
2619
2655
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "mt-3 text-center text-xs text-muted-foreground", children: selecting === "from" ? "Select start date" : "Select end date" })
|
|
2620
|
-
] })
|
|
2656
|
+
] }) })
|
|
2621
2657
|
] });
|
|
2622
2658
|
}
|
|
2623
2659
|
|
|
@@ -2719,10 +2755,10 @@ function Drawer({
|
|
|
2719
2755
|
var React16 = __toESM(require("react"), 1);
|
|
2720
2756
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2721
2757
|
var widthMap = {
|
|
2722
|
-
sm:
|
|
2723
|
-
md:
|
|
2724
|
-
lg:
|
|
2725
|
-
auto:
|
|
2758
|
+
sm: 160,
|
|
2759
|
+
md: 224,
|
|
2760
|
+
lg: 288,
|
|
2761
|
+
auto: void 0
|
|
2726
2762
|
};
|
|
2727
2763
|
function Dropdown({
|
|
2728
2764
|
trigger,
|
|
@@ -2736,25 +2772,40 @@ function Dropdown({
|
|
|
2736
2772
|
className
|
|
2737
2773
|
}) {
|
|
2738
2774
|
const [isOpen, setIsOpen] = React16.useState(false);
|
|
2739
|
-
const
|
|
2740
|
-
const
|
|
2775
|
+
const triggerRef = React16.useRef(null);
|
|
2776
|
+
const [dropStyle, setDropStyle] = React16.useState({});
|
|
2777
|
+
const open = () => {
|
|
2741
2778
|
if (disabled) return;
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2779
|
+
if (triggerRef.current) {
|
|
2780
|
+
const r = triggerRef.current.getBoundingClientRect();
|
|
2781
|
+
const pos = getPortalPosition(triggerRef.current, 320, placement);
|
|
2782
|
+
const w = widthMap[width];
|
|
2783
|
+
let left = r.left;
|
|
2784
|
+
if (align === "right") left = r.right - (w ?? r.width);
|
|
2785
|
+
if (align === "center") left = r.left + r.width / 2 - (w ?? r.width) / 2;
|
|
2786
|
+
setDropStyle({
|
|
2787
|
+
position: "fixed",
|
|
2788
|
+
top: pos.placement === "bottom" ? pos.top : void 0,
|
|
2789
|
+
bottom: pos.placement === "top" ? window.innerHeight - r.top + 4 : void 0,
|
|
2790
|
+
left,
|
|
2791
|
+
width: w,
|
|
2792
|
+
minWidth: w ? void 0 : "10rem",
|
|
2793
|
+
zIndex: 9999
|
|
2794
|
+
});
|
|
2795
|
+
}
|
|
2796
|
+
setIsOpen(true);
|
|
2797
|
+
onOpenChange?.(true);
|
|
2745
2798
|
};
|
|
2746
2799
|
const close = () => {
|
|
2747
2800
|
setIsOpen(false);
|
|
2748
2801
|
onOpenChange?.(false);
|
|
2749
2802
|
};
|
|
2750
2803
|
React16.useEffect(() => {
|
|
2751
|
-
const handleClickOutside = (
|
|
2752
|
-
if (
|
|
2753
|
-
close();
|
|
2754
|
-
}
|
|
2804
|
+
const handleClickOutside = (e) => {
|
|
2805
|
+
if (triggerRef.current && !triggerRef.current.contains(e.target)) close();
|
|
2755
2806
|
};
|
|
2756
|
-
const handleKeyDown = (
|
|
2757
|
-
if (
|
|
2807
|
+
const handleKeyDown = (e) => {
|
|
2808
|
+
if (e.key === "Escape") close();
|
|
2758
2809
|
};
|
|
2759
2810
|
document.addEventListener("mousedown", handleClickOutside);
|
|
2760
2811
|
document.addEventListener("keydown", handleKeyDown);
|
|
@@ -2763,39 +2814,30 @@ function Dropdown({
|
|
|
2763
2814
|
document.removeEventListener("keydown", handleKeyDown);
|
|
2764
2815
|
};
|
|
2765
2816
|
}, [isOpen]);
|
|
2766
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "relative inline-block text-left", ref:
|
|
2817
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "relative inline-block text-left", ref: triggerRef, children: [
|
|
2767
2818
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2768
2819
|
"div",
|
|
2769
2820
|
{
|
|
2770
|
-
onClick:
|
|
2821
|
+
onClick: () => isOpen ? close() : open(),
|
|
2771
2822
|
"aria-expanded": isOpen,
|
|
2772
2823
|
"aria-haspopup": "true",
|
|
2773
2824
|
className: cn(disabled && "opacity-50 cursor-not-allowed pointer-events-none"),
|
|
2774
2825
|
children: trigger
|
|
2775
2826
|
}
|
|
2776
2827
|
),
|
|
2777
|
-
isOpen && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2828
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(FloatingPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2778
2829
|
"div",
|
|
2779
2830
|
{
|
|
2780
2831
|
className: cn(
|
|
2781
|
-
"
|
|
2832
|
+
"rounded-xl border border-white/10 bg-background/90 backdrop-blur-2xl text-popover-foreground",
|
|
2782
2833
|
"shadow-[0_8px_32px_rgba(0,0,0,0.35)] ring-1 ring-white/5",
|
|
2783
2834
|
"animate-in fade-in-0 zoom-in-95 duration-150",
|
|
2784
|
-
widthMap[width],
|
|
2785
|
-
placement === "top" ? "bottom-full mb-2" : "top-full mt-2",
|
|
2786
|
-
align === "right" ? "right-0" : align === "center" ? "left-1/2 -translate-x-1/2" : "left-0",
|
|
2787
2835
|
className
|
|
2788
2836
|
),
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
{
|
|
2792
|
-
className: "py-1.5",
|
|
2793
|
-
onClick: closeOnSelect ? close : void 0,
|
|
2794
|
-
children
|
|
2795
|
-
}
|
|
2796
|
-
)
|
|
2837
|
+
style: dropStyle,
|
|
2838
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "py-1.5", onClick: closeOnSelect ? close : void 0, children })
|
|
2797
2839
|
}
|
|
2798
|
-
)
|
|
2840
|
+
) })
|
|
2799
2841
|
] });
|
|
2800
2842
|
}
|
|
2801
2843
|
function DropdownItem({
|
|
@@ -2828,10 +2870,7 @@ function DropdownItem({
|
|
|
2828
2870
|
function DropdownSeparator({ className }) {
|
|
2829
2871
|
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: cn("my-1.5 h-px bg-white/8", className) });
|
|
2830
2872
|
}
|
|
2831
|
-
function DropdownLabel({
|
|
2832
|
-
children,
|
|
2833
|
-
className
|
|
2834
|
-
}) {
|
|
2873
|
+
function DropdownLabel({ children, className }) {
|
|
2835
2874
|
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: cn("px-3.5 py-1.5 text-xs font-semibold uppercase tracking-wider text-muted-foreground/60", className), children });
|
|
2836
2875
|
}
|
|
2837
2876
|
|
|
@@ -3693,6 +3732,7 @@ var Input = React18.forwardRef(
|
|
|
3693
3732
|
value: internalValue,
|
|
3694
3733
|
disabledDates,
|
|
3695
3734
|
disabledDateTimes,
|
|
3735
|
+
anchorEl: containerRef.current,
|
|
3696
3736
|
onChange: (v) => {
|
|
3697
3737
|
setInternalValue(v);
|
|
3698
3738
|
setValidationError(null);
|
|
@@ -4084,30 +4124,43 @@ function Select({
|
|
|
4084
4124
|
const [search, setSearch] = React23.useState("");
|
|
4085
4125
|
const [isSearching, setIsSearching] = React23.useState(false);
|
|
4086
4126
|
const containerRef = React23.useRef(null);
|
|
4127
|
+
const triggerRef = React23.useRef(null);
|
|
4128
|
+
const [dropStyle, setDropStyle] = React23.useState({});
|
|
4087
4129
|
const getKey = (opt) => String(Object.keys(opt)[0]);
|
|
4088
4130
|
const getLabel = (opt) => Object.values(opt)[0];
|
|
4089
4131
|
const selectedValues = React23.useMemo(() => {
|
|
4090
|
-
if (multiple && Array.isArray(value))
|
|
4091
|
-
|
|
4092
|
-
} else if (typeof value === "string") {
|
|
4093
|
-
return [value];
|
|
4094
|
-
}
|
|
4132
|
+
if (multiple && Array.isArray(value)) return value;
|
|
4133
|
+
if (typeof value === "string") return [value];
|
|
4095
4134
|
return [];
|
|
4096
4135
|
}, [value, multiple]);
|
|
4097
|
-
const selectedOptions = React23.useMemo(
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
)
|
|
4136
|
+
const selectedOptions = React23.useMemo(
|
|
4137
|
+
() => options.filter((opt) => selectedValues.includes(getKey(opt))),
|
|
4138
|
+
[options, selectedValues]
|
|
4139
|
+
);
|
|
4140
|
+
const filteredOptions = searchable ? options.filter((opt) => getLabel(opt).toLowerCase().includes(search.toLowerCase())) : options;
|
|
4141
|
+
const openDropdown = () => {
|
|
4142
|
+
if (disabled) return;
|
|
4143
|
+
if (triggerRef.current) {
|
|
4144
|
+
const pos = getPortalPosition(triggerRef.current, 260);
|
|
4145
|
+
setDropStyle({
|
|
4146
|
+
position: "fixed",
|
|
4147
|
+
top: pos.placement === "bottom" ? pos.top : void 0,
|
|
4148
|
+
bottom: pos.placement === "top" ? window.innerHeight - pos.top : void 0,
|
|
4149
|
+
left: pos.left,
|
|
4150
|
+
width: pos.width,
|
|
4151
|
+
zIndex: 9999
|
|
4152
|
+
});
|
|
4153
|
+
}
|
|
4154
|
+
setIsOpen(true);
|
|
4155
|
+
};
|
|
4103
4156
|
React23.useEffect(() => {
|
|
4104
|
-
const
|
|
4105
|
-
if (containerRef.current && !containerRef.current.contains(
|
|
4157
|
+
const handler = (e) => {
|
|
4158
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
4106
4159
|
setIsOpen(false);
|
|
4107
4160
|
}
|
|
4108
4161
|
};
|
|
4109
|
-
document.addEventListener("mousedown",
|
|
4110
|
-
return () => document.removeEventListener("mousedown",
|
|
4162
|
+
document.addEventListener("mousedown", handler);
|
|
4163
|
+
return () => document.removeEventListener("mousedown", handler);
|
|
4111
4164
|
}, []);
|
|
4112
4165
|
const handleSelect = (optionValue) => {
|
|
4113
4166
|
if (multiple) {
|
|
@@ -4121,10 +4174,7 @@ function Select({
|
|
|
4121
4174
|
};
|
|
4122
4175
|
const handleRemove = (optionValue, e) => {
|
|
4123
4176
|
e.stopPropagation();
|
|
4124
|
-
if (multiple)
|
|
4125
|
-
const newValues = selectedValues.filter((v) => v !== optionValue);
|
|
4126
|
-
onChange?.(newValues);
|
|
4127
|
-
}
|
|
4177
|
+
if (multiple) onChange?.(selectedValues.filter((v) => v !== optionValue));
|
|
4128
4178
|
};
|
|
4129
4179
|
const handleReorder = (fromIndex, toIndex) => {
|
|
4130
4180
|
if (!multiple || !reorderable || !Array.isArray(value)) return;
|
|
@@ -4138,16 +4188,13 @@ function Select({
|
|
|
4138
4188
|
e.dataTransfer.setData("text/plain", index.toString());
|
|
4139
4189
|
};
|
|
4140
4190
|
const handleDragOver = (e) => {
|
|
4141
|
-
if (
|
|
4142
|
-
e.preventDefault();
|
|
4191
|
+
if (reorderable) e.preventDefault();
|
|
4143
4192
|
};
|
|
4144
4193
|
const handleDrop = (e, toIndex) => {
|
|
4145
4194
|
if (!reorderable) return;
|
|
4146
4195
|
e.preventDefault();
|
|
4147
4196
|
const fromIndex = parseInt(e.dataTransfer.getData("text/plain"));
|
|
4148
|
-
if (fromIndex !== toIndex)
|
|
4149
|
-
handleReorder(fromIndex, toIndex);
|
|
4150
|
-
}
|
|
4197
|
+
if (fromIndex !== toIndex) handleReorder(fromIndex, toIndex);
|
|
4151
4198
|
};
|
|
4152
4199
|
if (native) {
|
|
4153
4200
|
if (multiple) {
|
|
@@ -4157,58 +4204,29 @@ function Select({
|
|
|
4157
4204
|
"w-full rounded-xl border border-slate-900/30 bg-background/50 backdrop-blur-sm overflow-hidden ring-offset-background focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
|
|
4158
4205
|
disabled && "opacity-50 pointer-events-none"
|
|
4159
4206
|
), children: [
|
|
4160
|
-
selectedValues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "flex flex-wrap gap-1 px-3 pt-2 pb-1 border-b border-slate-900/10", children: selectedOptions.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
4161
|
-
|
|
4162
|
-
{
|
|
4163
|
-
|
|
4164
|
-
children: [
|
|
4165
|
-
getLabel(opt),
|
|
4166
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
4167
|
-
"button",
|
|
4168
|
-
{
|
|
4169
|
-
type: "button",
|
|
4170
|
-
disabled,
|
|
4171
|
-
onClick: () => onChange?.(selectedValues.filter((v) => v !== getKey(opt))),
|
|
4172
|
-
className: "hover:text-destructive",
|
|
4173
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react16.X, { className: "h-3 w-3" })
|
|
4174
|
-
}
|
|
4175
|
-
)
|
|
4176
|
-
]
|
|
4177
|
-
},
|
|
4178
|
-
getKey(opt)
|
|
4179
|
-
)) }),
|
|
4207
|
+
selectedValues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "flex flex-wrap gap-1 px-3 pt-2 pb-1 border-b border-slate-900/10", children: selectedOptions.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "inline-flex items-center gap-1 rounded-sm bg-primary/15 text-primary px-2 py-0.5 text-xs", children: [
|
|
4208
|
+
getLabel(opt),
|
|
4209
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { type: "button", disabled, onClick: () => onChange?.(selectedValues.filter((v) => v !== getKey(opt))), className: "hover:text-destructive", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react16.X, { className: "h-3 w-3" }) })
|
|
4210
|
+
] }, getKey(opt))) }),
|
|
4180
4211
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "max-h-48 overflow-y-auto p-1", children: options.map((option) => {
|
|
4181
4212
|
const checked = selectedValues.includes(getKey(option));
|
|
4182
|
-
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
4183
|
-
"
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
checked ?
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
checked,
|
|
4200
|
-
disabled,
|
|
4201
|
-
onChange: () => {
|
|
4202
|
-
const newValues = checked ? selectedValues.filter((v) => v !== getKey(option)) : [...selectedValues, getKey(option)];
|
|
4203
|
-
onChange?.(newValues);
|
|
4204
|
-
}
|
|
4205
|
-
}
|
|
4206
|
-
),
|
|
4207
|
-
getLabel(option)
|
|
4208
|
-
]
|
|
4209
|
-
},
|
|
4210
|
-
getKey(option)
|
|
4211
|
-
);
|
|
4213
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: cn("flex items-center gap-3 rounded-lg px-3 py-2 text-sm cursor-pointer transition-colors hover:bg-accent", checked && "bg-primary/8 text-primary"), children: [
|
|
4214
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: cn("flex h-4 w-4 shrink-0 items-center justify-center rounded border transition-colors", checked ? "bg-primary border-primary text-primary-foreground" : "border-slate-900/30 bg-background/50"), children: checked && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react16.Check, { className: "h-3 w-3" }) }),
|
|
4215
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
4216
|
+
"input",
|
|
4217
|
+
{
|
|
4218
|
+
type: "checkbox",
|
|
4219
|
+
className: "sr-only",
|
|
4220
|
+
checked,
|
|
4221
|
+
disabled,
|
|
4222
|
+
onChange: () => {
|
|
4223
|
+
const newValues = checked ? selectedValues.filter((v) => v !== getKey(option)) : [...selectedValues, getKey(option)];
|
|
4224
|
+
onChange?.(newValues);
|
|
4225
|
+
}
|
|
4226
|
+
}
|
|
4227
|
+
),
|
|
4228
|
+
getLabel(option)
|
|
4229
|
+
] }, getKey(option));
|
|
4212
4230
|
}) })
|
|
4213
4231
|
] })
|
|
4214
4232
|
] });
|
|
@@ -4239,14 +4257,15 @@ function Select({
|
|
|
4239
4257
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
4240
4258
|
"button",
|
|
4241
4259
|
{
|
|
4260
|
+
ref: triggerRef,
|
|
4242
4261
|
type: "button",
|
|
4243
4262
|
className: cn(
|
|
4244
4263
|
"relative flex w-full items-center min-h-[2.5rem] rounded-xl border border-slate-900/30 bg-background/50 backdrop-blur-sm px-4 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 transition-colors hover:bg-background/80",
|
|
4245
4264
|
multiple && selectedValues.length > 0 && "flex-wrap gap-1",
|
|
4246
|
-
|
|
4265
|
+
"pr-10",
|
|
4247
4266
|
disabled && "cursor-not-allowed opacity-50"
|
|
4248
4267
|
),
|
|
4249
|
-
onClick: () =>
|
|
4268
|
+
onClick: () => isOpen ? setIsOpen(false) : openDropdown(),
|
|
4250
4269
|
disabled,
|
|
4251
4270
|
children: multiple && selectedOptions.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "flex flex-wrap gap-1 flex-1 min-w-0", children: selectedOptions.map((option, index) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
4252
4271
|
"span",
|
|
@@ -4255,22 +4274,11 @@ function Select({
|
|
|
4255
4274
|
onDragStart: (e) => handleDragStart(e, index),
|
|
4256
4275
|
onDragOver: handleDragOver,
|
|
4257
4276
|
onDrop: (e) => handleDrop(e, index),
|
|
4258
|
-
className: cn(
|
|
4259
|
-
"inline-flex items-center gap-1 rounded-sm bg-primary/15 text-primary px-2 py-1 text-xs",
|
|
4260
|
-
reorderable && "cursor-move"
|
|
4261
|
-
),
|
|
4277
|
+
className: cn("inline-flex items-center gap-1 rounded-sm bg-primary/15 text-primary px-2 py-1 text-xs", reorderable && "cursor-move"),
|
|
4262
4278
|
children: [
|
|
4263
4279
|
reorderable && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react16.GripVertical, { className: "h-3 w-3 opacity-50" }),
|
|
4264
4280
|
getLabel(option),
|
|
4265
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
4266
|
-
"button",
|
|
4267
|
-
{
|
|
4268
|
-
type: "button",
|
|
4269
|
-
onClick: (e) => handleRemove(getKey(option), e),
|
|
4270
|
-
className: "ml-1 hover:text-destructive",
|
|
4271
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react16.X, { className: "h-3 w-3" })
|
|
4272
|
-
}
|
|
4273
|
-
)
|
|
4281
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { type: "button", onClick: (e) => handleRemove(getKey(option), e), className: "ml-1 hover:text-destructive", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react16.X, { className: "h-3 w-3" }) })
|
|
4274
4282
|
]
|
|
4275
4283
|
},
|
|
4276
4284
|
getKey(option)
|
|
@@ -4283,50 +4291,56 @@ function Select({
|
|
|
4283
4291
|
{
|
|
4284
4292
|
type: "button",
|
|
4285
4293
|
disabled,
|
|
4286
|
-
onClick: () =>
|
|
4294
|
+
onClick: () => isOpen ? setIsOpen(false) : openDropdown(),
|
|
4287
4295
|
className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors z-10 disabled:opacity-50",
|
|
4288
|
-
"aria-label": "Open options",
|
|
4289
4296
|
style: iconColor ? { color: iconColor } : void 0,
|
|
4290
4297
|
children: suffixIcon
|
|
4291
4298
|
}
|
|
4292
4299
|
),
|
|
4293
|
-
isOpen && /* @__PURE__ */ (0, import_jsx_runtime28.
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4300
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(FloatingPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
4301
|
+
"div",
|
|
4302
|
+
{
|
|
4303
|
+
className: "max-h-60 overflow-auto rounded-md border border-white/10 bg-background/80 backdrop-blur-xl text-popover-foreground shadow-lg animate-in fade-in-80",
|
|
4304
|
+
style: dropStyle,
|
|
4305
|
+
children: [
|
|
4306
|
+
searchable && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "sticky top-0 z-10 flex items-center border-b border-white/10 bg-background/90 px-3 py-2", children: [
|
|
4307
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react16.Search, { className: "mr-2 h-4 w-4 shrink-0 opacity-50" }),
|
|
4308
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
4309
|
+
"input",
|
|
4310
|
+
{
|
|
4311
|
+
className: "flex h-8 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground",
|
|
4312
|
+
placeholder: searchingMessage,
|
|
4313
|
+
value: search,
|
|
4314
|
+
onChange: (e) => {
|
|
4315
|
+
setSearch(e.target.value);
|
|
4316
|
+
setIsSearching(true);
|
|
4317
|
+
setTimeout(() => setIsSearching(false), 300);
|
|
4318
|
+
},
|
|
4319
|
+
onClick: (e) => e.stopPropagation()
|
|
4320
|
+
}
|
|
4321
|
+
)
|
|
4322
|
+
] }),
|
|
4323
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "p-1", children: isSearching ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "py-6 text-center text-sm text-muted-foreground", children: loadingMessage }) : filteredOptions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "py-6 text-center text-sm text-muted-foreground", children: search ? noSearchResultsMessage : "No options available." }) : /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
4324
|
+
filteredOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
4325
|
+
"div",
|
|
4326
|
+
{
|
|
4327
|
+
className: cn(
|
|
4328
|
+
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none hover:bg-accent hover:text-accent-foreground",
|
|
4329
|
+
(multiple ? selectedValues.includes(getKey(option)) : value === getKey(option)) && "bg-accent text-accent-foreground"
|
|
4330
|
+
),
|
|
4331
|
+
onClick: () => handleSelect(getKey(option)),
|
|
4332
|
+
children: [
|
|
4333
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: (multiple ? selectedValues.includes(getKey(option)) : value === getKey(option)) && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react16.Check, { className: "h-4 w-4" }) }),
|
|
4334
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "truncate", children: getLabel(option) })
|
|
4335
|
+
]
|
|
4336
|
+
},
|
|
4337
|
+
getKey(option)
|
|
4338
|
+
)),
|
|
4339
|
+
createOptionForm && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "border-t border-white/10 mt-1 pt-1", children: createOptionForm })
|
|
4340
|
+
] }) })
|
|
4341
|
+
]
|
|
4342
|
+
}
|
|
4343
|
+
) })
|
|
4330
4344
|
] })
|
|
4331
4345
|
] });
|
|
4332
4346
|
}
|
|
@@ -5169,7 +5183,7 @@ var import_lucide_react20 = require("lucide-react");
|
|
|
5169
5183
|
|
|
5170
5184
|
// src/components/ui/tooltip.tsx
|
|
5171
5185
|
var React28 = __toESM(require("react"), 1);
|
|
5172
|
-
var
|
|
5186
|
+
var ReactDOM2 = __toESM(require("react-dom"), 1);
|
|
5173
5187
|
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
5174
5188
|
function Tooltip({
|
|
5175
5189
|
content,
|
|
@@ -5224,7 +5238,7 @@ function Tooltip({
|
|
|
5224
5238
|
onBlur: () => setVisible(false),
|
|
5225
5239
|
children: [
|
|
5226
5240
|
children,
|
|
5227
|
-
visible &&
|
|
5241
|
+
visible && ReactDOM2.createPortal(
|
|
5228
5242
|
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
5229
5243
|
"div",
|
|
5230
5244
|
{
|
|
@@ -5247,24 +5261,36 @@ function Tooltip({
|
|
|
5247
5261
|
|
|
5248
5262
|
// src/components/theme-provider.tsx
|
|
5249
5263
|
var import_react = require("react");
|
|
5264
|
+
|
|
5265
|
+
// src/components/conf/settingConfig.json
|
|
5266
|
+
var settingConfig_default = {
|
|
5267
|
+
theme: "dark",
|
|
5268
|
+
fontSize: "16px",
|
|
5269
|
+
fontFamily: '"Space Grotesk", "Inter", sans-serif',
|
|
5270
|
+
colors: {
|
|
5271
|
+
primary: "#8b5cf6",
|
|
5272
|
+
primaryHover: "#7c3aed",
|
|
5273
|
+
secondary: "#171717",
|
|
5274
|
+
secondaryHover: "#262626",
|
|
5275
|
+
info: "#3b82f6",
|
|
5276
|
+
infoHover: "#2563eb",
|
|
5277
|
+
warning: "#f59e0b",
|
|
5278
|
+
warningHover: "#d97706",
|
|
5279
|
+
danger: "#ef4444",
|
|
5280
|
+
dangerHover: "#dc2626"
|
|
5281
|
+
}
|
|
5282
|
+
};
|
|
5283
|
+
|
|
5284
|
+
// src/components/theme-provider.tsx
|
|
5250
5285
|
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
5251
|
-
var
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
info: "#3b82f6",
|
|
5257
|
-
infoHover: "#2563eb",
|
|
5258
|
-
warning: "#f59e0b",
|
|
5259
|
-
warningHover: "#d97706",
|
|
5260
|
-
danger: "#ef4444",
|
|
5261
|
-
dangerHover: "#dc2626"
|
|
5286
|
+
var configDefaults = {
|
|
5287
|
+
theme: settingConfig_default.theme,
|
|
5288
|
+
fontSize: settingConfig_default.fontSize,
|
|
5289
|
+
fontFamily: settingConfig_default.fontFamily,
|
|
5290
|
+
colors: settingConfig_default.colors
|
|
5262
5291
|
};
|
|
5263
5292
|
var initialState = {
|
|
5264
|
-
|
|
5265
|
-
colors: defaultColors,
|
|
5266
|
-
fontSize: "16px",
|
|
5267
|
-
fontFamily: '"Space Grotesk", "Inter", sans-serif',
|
|
5293
|
+
...configDefaults,
|
|
5268
5294
|
setTheme: () => null,
|
|
5269
5295
|
setColors: () => null,
|
|
5270
5296
|
setFontSize: () => null,
|
|
@@ -5274,26 +5300,60 @@ var initialState = {
|
|
|
5274
5300
|
var ThemeProviderContext = (0, import_react.createContext)(initialState);
|
|
5275
5301
|
var COLOR_PALETTE = [
|
|
5276
5302
|
{ base: "#6366f1", hover: "#4f46e5" },
|
|
5277
|
-
// Indigo
|
|
5278
5303
|
{ base: "#8b5cf6", hover: "#7c3aed" },
|
|
5279
|
-
// Violet
|
|
5280
5304
|
{ base: "#3b82f6", hover: "#2563eb" },
|
|
5281
|
-
// Blue
|
|
5282
5305
|
{ base: "#10b981", hover: "#059669" },
|
|
5283
|
-
// Emerald
|
|
5284
5306
|
{ base: "#22c55e", hover: "#16a34a" },
|
|
5285
|
-
// Green
|
|
5286
5307
|
{ base: "#eab308", hover: "#ca8a04" },
|
|
5287
|
-
// Yellow
|
|
5288
5308
|
{ base: "#f59e0b", hover: "#d97706" },
|
|
5289
|
-
// Amber
|
|
5290
5309
|
{ base: "#f97316", hover: "#ea580c" },
|
|
5291
|
-
// Orange
|
|
5292
5310
|
{ base: "#ef4444", hover: "#dc2626" },
|
|
5293
|
-
// Red
|
|
5294
5311
|
{ base: "#ec4899", hover: "#db2777" }
|
|
5295
|
-
// Pink
|
|
5296
5312
|
];
|
|
5313
|
+
function ThemeProvider({
|
|
5314
|
+
children,
|
|
5315
|
+
storageKey = "codego-ui-theme-settings",
|
|
5316
|
+
...props
|
|
5317
|
+
}) {
|
|
5318
|
+
const [settings, setSettings] = (0, import_react.useState)(() => {
|
|
5319
|
+
try {
|
|
5320
|
+
const stored = localStorage.getItem(storageKey);
|
|
5321
|
+
if (stored) return { ...configDefaults, ...JSON.parse(stored) };
|
|
5322
|
+
} catch {
|
|
5323
|
+
}
|
|
5324
|
+
return configDefaults;
|
|
5325
|
+
});
|
|
5326
|
+
(0, import_react.useEffect)(() => {
|
|
5327
|
+
localStorage.setItem(storageKey, JSON.stringify(settings));
|
|
5328
|
+
}, [settings, storageKey]);
|
|
5329
|
+
(0, import_react.useEffect)(() => {
|
|
5330
|
+
const root = window.document.documentElement;
|
|
5331
|
+
root.classList.remove("light", "dark");
|
|
5332
|
+
const resolved = settings.theme === "system" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : settings.theme;
|
|
5333
|
+
root.classList.add(resolved);
|
|
5334
|
+
root.style.setProperty("--primary", settings.colors.primary);
|
|
5335
|
+
root.style.setProperty("--primary-hover", settings.colors.primaryHover);
|
|
5336
|
+
root.style.setProperty("--secondary", settings.colors.secondary);
|
|
5337
|
+
root.style.setProperty("--secondary-hover", settings.colors.secondaryHover);
|
|
5338
|
+
root.style.setProperty("--info", settings.colors.info);
|
|
5339
|
+
root.style.setProperty("--info-hover", settings.colors.infoHover);
|
|
5340
|
+
root.style.setProperty("--warning", settings.colors.warning);
|
|
5341
|
+
root.style.setProperty("--warning-hover", settings.colors.warningHover);
|
|
5342
|
+
root.style.setProperty("--danger", settings.colors.danger);
|
|
5343
|
+
root.style.setProperty("--danger-hover", settings.colors.dangerHover);
|
|
5344
|
+
root.style.setProperty("font-size", settings.fontSize);
|
|
5345
|
+
root.style.setProperty("--font-sans", settings.fontFamily);
|
|
5346
|
+
}, [settings]);
|
|
5347
|
+
const value = {
|
|
5348
|
+
...settings,
|
|
5349
|
+
setTheme: (theme) => setSettings((s) => ({ ...s, theme })),
|
|
5350
|
+
setColors: (colors) => setSettings((s) => ({ ...s, colors: { ...s.colors, ...colors } })),
|
|
5351
|
+
setFontSize: (fontSize) => setSettings((s) => ({ ...s, fontSize })),
|
|
5352
|
+
setFontFamily: (fontFamily) => setSettings((s) => ({ ...s, fontFamily })),
|
|
5353
|
+
resetSettings: () => setSettings(configDefaults)
|
|
5354
|
+
};
|
|
5355
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ThemeProviderContext.Provider, { ...props, value, children });
|
|
5356
|
+
}
|
|
5297
5357
|
var useTheme = () => {
|
|
5298
5358
|
const context = (0, import_react.useContext)(ThemeProviderContext);
|
|
5299
5359
|
if (context === void 0)
|
|
@@ -5453,16 +5513,28 @@ function PanelSidebarGroup({
|
|
|
5453
5513
|
// src/components/ui/popover.tsx
|
|
5454
5514
|
var React31 = __toESM(require("react"), 1);
|
|
5455
5515
|
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
|
|
5465
|
-
};
|
|
5516
|
+
function calcStyle(triggerEl, placement) {
|
|
5517
|
+
const r = triggerEl.getBoundingClientRect();
|
|
5518
|
+
const GAP = 8;
|
|
5519
|
+
switch (placement) {
|
|
5520
|
+
case "bottom":
|
|
5521
|
+
return { top: r.bottom + GAP, left: r.left + r.width / 2, transform: "translateX(-50%)" };
|
|
5522
|
+
case "bottom-start":
|
|
5523
|
+
return { top: r.bottom + GAP, left: r.left };
|
|
5524
|
+
case "bottom-end":
|
|
5525
|
+
return { top: r.bottom + GAP, left: r.right, transform: "translateX(-100%)" };
|
|
5526
|
+
case "top":
|
|
5527
|
+
return { top: r.top - GAP, left: r.left + r.width / 2, transform: "translate(-50%, -100%)" };
|
|
5528
|
+
case "top-start":
|
|
5529
|
+
return { top: r.top - GAP, left: r.left, transform: "translateY(-100%)" };
|
|
5530
|
+
case "top-end":
|
|
5531
|
+
return { top: r.top - GAP, left: r.right, transform: "translate(-100%, -100%)" };
|
|
5532
|
+
case "left":
|
|
5533
|
+
return { top: r.top + r.height / 2, left: r.left - GAP, transform: "translate(-100%, -50%)" };
|
|
5534
|
+
case "right":
|
|
5535
|
+
return { top: r.top + r.height / 2, left: r.right + GAP, transform: "translateY(-50%)" };
|
|
5536
|
+
}
|
|
5537
|
+
}
|
|
5466
5538
|
function Popover({
|
|
5467
5539
|
trigger,
|
|
5468
5540
|
content,
|
|
@@ -5474,11 +5546,18 @@ function Popover({
|
|
|
5474
5546
|
}) {
|
|
5475
5547
|
const [internal, setInternal] = React31.useState(false);
|
|
5476
5548
|
const ref = React31.useRef(null);
|
|
5549
|
+
const [popStyle, setPopStyle] = React31.useState({});
|
|
5477
5550
|
const open = controlled ?? internal;
|
|
5478
5551
|
function setOpen(v) {
|
|
5479
5552
|
if (controlled === void 0) setInternal(v);
|
|
5480
5553
|
onOpenChange?.(v);
|
|
5481
5554
|
}
|
|
5555
|
+
function openPopover() {
|
|
5556
|
+
if (ref.current) {
|
|
5557
|
+
setPopStyle({ position: "fixed", zIndex: 9999, ...calcStyle(ref.current, placement) });
|
|
5558
|
+
}
|
|
5559
|
+
setOpen(true);
|
|
5560
|
+
}
|
|
5482
5561
|
React31.useEffect(() => {
|
|
5483
5562
|
if (triggerOn !== "click") return;
|
|
5484
5563
|
function handler(e) {
|
|
@@ -5487,14 +5566,17 @@ function Popover({
|
|
|
5487
5566
|
document.addEventListener("mousedown", handler);
|
|
5488
5567
|
return () => document.removeEventListener("mousedown", handler);
|
|
5489
5568
|
}, [triggerOn]);
|
|
5490
|
-
const hoverProps = triggerOn === "hover" ? { onMouseEnter:
|
|
5569
|
+
const hoverProps = triggerOn === "hover" ? { onMouseEnter: openPopover, onMouseLeave: () => setOpen(false) } : {};
|
|
5491
5570
|
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { ref, className: "relative inline-block", ...hoverProps, children: [
|
|
5492
|
-
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { onClick: () => triggerOn === "click" && setOpen(
|
|
5493
|
-
open && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
5494
|
-
"
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5571
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { onClick: () => triggerOn === "click" && (open ? setOpen(false) : openPopover()), children: trigger }),
|
|
5572
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(FloatingPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
5573
|
+
"div",
|
|
5574
|
+
{
|
|
5575
|
+
className: cn("min-w-max rounded-xl border border-border glass shadow-2xl", className),
|
|
5576
|
+
style: popStyle,
|
|
5577
|
+
children: content
|
|
5578
|
+
}
|
|
5579
|
+
) })
|
|
5498
5580
|
] });
|
|
5499
5581
|
}
|
|
5500
5582
|
|
|
@@ -7956,6 +8038,7 @@ function Wizard({
|
|
|
7956
8038
|
Badge,
|
|
7957
8039
|
Breadcrumb,
|
|
7958
8040
|
Button,
|
|
8041
|
+
COLOR_PALETTE,
|
|
7959
8042
|
Calendar,
|
|
7960
8043
|
Card,
|
|
7961
8044
|
CardContent,
|
|
@@ -8025,6 +8108,7 @@ function Wizard({
|
|
|
8025
8108
|
Tabs,
|
|
8026
8109
|
TagInput,
|
|
8027
8110
|
Textarea,
|
|
8111
|
+
ThemeProvider,
|
|
8028
8112
|
Timeline,
|
|
8029
8113
|
ToastProvider,
|
|
8030
8114
|
ToggleSwitch,
|
|
@@ -8033,5 +8117,6 @@ function Wizard({
|
|
|
8033
8117
|
TreeView,
|
|
8034
8118
|
Widget,
|
|
8035
8119
|
Wizard,
|
|
8120
|
+
useTheme,
|
|
8036
8121
|
useToast
|
|
8037
8122
|
});
|