@juv/codego-react-ui 1.1.3 → 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 +457 -424
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.global.js +1098 -1065
- package/dist/index.js +459 -426
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -125,9 +125,25 @@ var import_lucide_react = require("lucide-react");
|
|
|
125
125
|
// src/lib/utils.ts
|
|
126
126
|
var import_clsx = require("clsx");
|
|
127
127
|
var import_tailwind_merge = require("tailwind-merge");
|
|
128
|
+
var ReactDOM = __toESM(require("react-dom"), 1);
|
|
128
129
|
function cn(...inputs) {
|
|
129
130
|
return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
|
|
130
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
|
+
}
|
|
131
147
|
|
|
132
148
|
// src/components/ui/accordion.tsx
|
|
133
149
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -920,6 +936,8 @@ function ColorPicker({
|
|
|
920
936
|
const [opacity, setOpacity] = React7.useState(100);
|
|
921
937
|
const [recent, setRecent] = React7.useState([]);
|
|
922
938
|
const ref = React7.useRef(null);
|
|
939
|
+
const triggerRef = React7.useRef(null);
|
|
940
|
+
const [dropStyle, setDropStyle] = React7.useState({});
|
|
923
941
|
const color = controlled ?? internal;
|
|
924
942
|
React7.useEffect(() => {
|
|
925
943
|
setHex(color);
|
|
@@ -931,6 +949,19 @@ function ColorPicker({
|
|
|
931
949
|
document.addEventListener("mousedown", handler);
|
|
932
950
|
return () => document.removeEventListener("mousedown", handler);
|
|
933
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
|
+
}
|
|
934
965
|
function apply(c) {
|
|
935
966
|
if (!controlled) setInternal(c);
|
|
936
967
|
onChange?.(c);
|
|
@@ -945,9 +976,10 @@ function ColorPicker({
|
|
|
945
976
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
946
977
|
"button",
|
|
947
978
|
{
|
|
979
|
+
ref: triggerRef,
|
|
948
980
|
type: "button",
|
|
949
981
|
disabled,
|
|
950
|
-
onClick: () => setOpen(
|
|
982
|
+
onClick: () => open ? setOpen(false) : openPicker(),
|
|
951
983
|
className: cn(
|
|
952
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",
|
|
953
985
|
disabled && "opacity-50 cursor-not-allowed pointer-events-none"
|
|
@@ -958,7 +990,7 @@ function ColorPicker({
|
|
|
958
990
|
]
|
|
959
991
|
}
|
|
960
992
|
),
|
|
961
|
-
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: [
|
|
962
994
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
963
995
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
964
996
|
"input",
|
|
@@ -1013,10 +1045,7 @@ function ColorPicker({
|
|
|
1013
1045
|
apply(s);
|
|
1014
1046
|
setHex(s);
|
|
1015
1047
|
},
|
|
1016
|
-
className: cn(
|
|
1017
|
-
"h-6 w-6 rounded-md border transition-transform hover:scale-110",
|
|
1018
|
-
color === s ? "border-primary ring-1 ring-primary" : "border-border/60"
|
|
1019
|
-
),
|
|
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"),
|
|
1020
1049
|
style: { backgroundColor: s },
|
|
1021
1050
|
title: s
|
|
1022
1051
|
},
|
|
@@ -1040,7 +1069,7 @@ function ColorPicker({
|
|
|
1040
1069
|
s
|
|
1041
1070
|
)) })
|
|
1042
1071
|
] })
|
|
1043
|
-
] })
|
|
1072
|
+
] }) })
|
|
1044
1073
|
] });
|
|
1045
1074
|
}
|
|
1046
1075
|
|
|
@@ -1067,7 +1096,9 @@ function Combobox({
|
|
|
1067
1096
|
const [open, setOpen] = React8.useState(false);
|
|
1068
1097
|
const [query, setQuery] = React8.useState("");
|
|
1069
1098
|
const ref = React8.useRef(null);
|
|
1099
|
+
const triggerRef = React8.useRef(null);
|
|
1070
1100
|
const inputRef = React8.useRef(null);
|
|
1101
|
+
const [dropStyle, setDropStyle] = React8.useState({});
|
|
1071
1102
|
const selected = controlled ?? internal;
|
|
1072
1103
|
function update(val) {
|
|
1073
1104
|
if (!controlled) setInternal(val);
|
|
@@ -1091,6 +1122,20 @@ function Combobox({
|
|
|
1091
1122
|
e.stopPropagation();
|
|
1092
1123
|
update(multiple ? [] : "");
|
|
1093
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
|
+
};
|
|
1094
1139
|
React8.useEffect(() => {
|
|
1095
1140
|
function handler(e) {
|
|
1096
1141
|
if (ref.current && !ref.current.contains(e.target)) {
|
|
@@ -1104,13 +1149,10 @@ function Combobox({
|
|
|
1104
1149
|
React8.useEffect(() => {
|
|
1105
1150
|
if (open) setTimeout(() => inputRef.current?.focus(), 50);
|
|
1106
1151
|
}, [open]);
|
|
1107
|
-
const filtered = options.filter(
|
|
1108
|
-
(o) => o.label.toLowerCase().includes(query.toLowerCase())
|
|
1109
|
-
);
|
|
1152
|
+
const filtered = options.filter((o) => o.label.toLowerCase().includes(query.toLowerCase()));
|
|
1110
1153
|
const groups = Array.from(new Set(filtered.map((o) => o.group ?? ""))).filter(Boolean);
|
|
1111
1154
|
const ungrouped = filtered.filter((o) => !o.group);
|
|
1112
1155
|
const showCreate = creatable && query && !options.find((o) => o.label.toLowerCase() === query.toLowerCase());
|
|
1113
|
-
const selectedLabels = multiple ? selected.map((v) => options.find((o) => o.value === v)?.label ?? v) : options.find((o) => o.value === selected)?.label;
|
|
1114
1156
|
const hasValue = multiple ? selected.length > 0 : !!selected;
|
|
1115
1157
|
function renderOptions(opts) {
|
|
1116
1158
|
return opts.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
@@ -1138,9 +1180,10 @@ function Combobox({
|
|
|
1138
1180
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
1139
1181
|
"button",
|
|
1140
1182
|
{
|
|
1183
|
+
ref: triggerRef,
|
|
1141
1184
|
type: "button",
|
|
1142
1185
|
disabled,
|
|
1143
|
-
onClick: () => setOpen(
|
|
1186
|
+
onClick: () => open ? setOpen(false) : openDropdown(),
|
|
1144
1187
|
className: cn(
|
|
1145
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",
|
|
1146
1189
|
"hover:border-primary/40 focus:outline-none focus:ring-2 focus:ring-ring",
|
|
@@ -1148,7 +1191,7 @@ function Combobox({
|
|
|
1148
1191
|
disabled && "opacity-50 cursor-not-allowed pointer-events-none"
|
|
1149
1192
|
),
|
|
1150
1193
|
children: [
|
|
1151
|
-
/* @__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 }),
|
|
1152
1195
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "flex items-center gap-1 shrink-0", children: [
|
|
1153
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" }) }),
|
|
1154
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") })
|
|
@@ -1156,50 +1199,57 @@ function Combobox({
|
|
|
1156
1199
|
]
|
|
1157
1200
|
}
|
|
1158
1201
|
),
|
|
1159
|
-
open && /* @__PURE__ */ (0, import_jsx_runtime10.
|
|
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
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
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
|
+
) })
|
|
1203
1253
|
] });
|
|
1204
1254
|
}
|
|
1205
1255
|
|
|
@@ -2156,6 +2206,20 @@ function parseValue(value, mode) {
|
|
|
2156
2206
|
return null;
|
|
2157
2207
|
}
|
|
2158
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
|
+
}
|
|
2159
2223
|
function TimePicker({
|
|
2160
2224
|
selected,
|
|
2161
2225
|
disabledDateTimes,
|
|
@@ -2223,25 +2287,9 @@ function Calendar2({
|
|
|
2223
2287
|
const isDisabled = (d) => disabledDates?.includes((0, import_date_fns.format)(d, "yyyy-MM-dd")) ?? false;
|
|
2224
2288
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "p-3 select-none", children: [
|
|
2225
2289
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center justify-between mb-3", children: [
|
|
2226
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2227
|
-
"button",
|
|
2228
|
-
{
|
|
2229
|
-
type: "button",
|
|
2230
|
-
onClick: onPrevMonth,
|
|
2231
|
-
className: "p-1 rounded hover:bg-white/10 text-muted-foreground hover:text-foreground transition-colors",
|
|
2232
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react10.ChevronLeft, { size: 16 })
|
|
2233
|
-
}
|
|
2234
|
-
),
|
|
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 }) }),
|
|
2235
2291
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-sm font-semibold text-foreground", children: (0, import_date_fns.format)(month, "MMMM yyyy") }),
|
|
2236
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2237
|
-
"button",
|
|
2238
|
-
{
|
|
2239
|
-
type: "button",
|
|
2240
|
-
onClick: onNextMonth,
|
|
2241
|
-
className: "p-1 rounded hover:bg-white/10 text-muted-foreground hover:text-foreground transition-colors",
|
|
2242
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react10.ChevronRight, { size: 16 })
|
|
2243
|
-
}
|
|
2244
|
-
)
|
|
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 }) })
|
|
2245
2293
|
] }),
|
|
2246
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)) }),
|
|
2247
2295
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "grid grid-cols-7 gap-y-1", children: days.map((d, i) => {
|
|
@@ -2276,136 +2324,44 @@ function DatePickerPopup({
|
|
|
2276
2324
|
disabledDates,
|
|
2277
2325
|
disabledDateTimes,
|
|
2278
2326
|
onChange,
|
|
2279
|
-
onClose
|
|
2327
|
+
onClose,
|
|
2328
|
+
anchorEl
|
|
2280
2329
|
}) {
|
|
2281
2330
|
const parsed = parseValue(value, mode);
|
|
2282
2331
|
const [month, setMonth] = React13.useState(parsed ?? /* @__PURE__ */ new Date());
|
|
2283
2332
|
const [selected, setSelected] = React13.useState(parsed);
|
|
2284
|
-
const
|
|
2333
|
+
const anchorStyle = getAnchorStyle(anchorEl ?? null, mode === "dateTime");
|
|
2285
2334
|
const commit = (d) => {
|
|
2286
|
-
if (mode === "date")
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
onChange((0, import_date_fns.format)(d, "yyyy-MM-dd'T'HH:mm"));
|
|
2290
|
-
} else {
|
|
2291
|
-
onChange((0, import_date_fns.format)(d, "HH:mm"));
|
|
2292
|
-
}
|
|
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"));
|
|
2293
2338
|
setSelected(d);
|
|
2294
2339
|
};
|
|
2295
2340
|
const handleDayClick = (d) => {
|
|
2296
2341
|
const base = selected ?? /* @__PURE__ */ new Date();
|
|
2297
|
-
|
|
2298
|
-
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)));
|
|
2299
2343
|
};
|
|
2300
2344
|
const handleTimeChange = (h, m) => {
|
|
2301
|
-
|
|
2302
|
-
const merged = (0, import_date_fns.setMinutes)((0, import_date_fns.setHours)(base, h), m);
|
|
2303
|
-
commit(merged);
|
|
2345
|
+
commit((0, import_date_fns.setMinutes)((0, import_date_fns.setHours)(selected ?? /* @__PURE__ */ new Date(), h), m));
|
|
2304
2346
|
};
|
|
2305
2347
|
const datePrefix = selected ? (0, import_date_fns.format)(selected, "yyyy-MM-dd") : void 0;
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
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",
|
|
2309
2352
|
{
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
children:
|
|
2314
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex", children: [
|
|
2315
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex-1 min-w-[240px]", children: [
|
|
2316
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-xs font-medium text-muted-foreground px-3 pt-3 pb-1", children: "Date" }),
|
|
2317
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2318
|
-
Calendar2,
|
|
2319
|
-
{
|
|
2320
|
-
selected,
|
|
2321
|
-
month,
|
|
2322
|
-
disabledDates,
|
|
2323
|
-
onDayClick: handleDayClick,
|
|
2324
|
-
onPrevMonth: () => setMonth((m) => (0, import_date_fns.subMonths)(m, 1)),
|
|
2325
|
-
onNextMonth: () => setMonth((m) => (0, import_date_fns.addMonths)(m, 1))
|
|
2326
|
-
}
|
|
2327
|
-
)
|
|
2328
|
-
] }),
|
|
2329
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "w-px bg-white/10 my-3" }),
|
|
2330
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex-1 min-w-[140px] flex flex-col", children: [
|
|
2331
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-xs font-medium text-muted-foreground px-3 pt-3 pb-1", children: "Time" }),
|
|
2332
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex gap-2 px-3 pb-3 flex-1", children: [
|
|
2333
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex-1", children: [
|
|
2334
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-xs text-muted-foreground mb-1 text-center", children: "HH" }),
|
|
2335
|
-
/* @__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)(
|
|
2336
|
-
"button",
|
|
2337
|
-
{
|
|
2338
|
-
type: "button",
|
|
2339
|
-
disabled: MINUTES.every((m) => {
|
|
2340
|
-
if (!disabledDateTimes || !datePrefix) return false;
|
|
2341
|
-
return disabledDateTimes.includes(`${datePrefix}T${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`);
|
|
2342
|
-
}),
|
|
2343
|
-
onClick: () => handleTimeChange(h, selected ? (0, import_date_fns.getMinutes)(selected) : 0),
|
|
2344
|
-
className: cn(
|
|
2345
|
-
"text-xs rounded py-1 transition-colors",
|
|
2346
|
-
selected && (0, import_date_fns.getHours)(selected) === h ? "bg-primary text-primary-foreground" : "hover:bg-white/10 text-foreground",
|
|
2347
|
-
MINUTES.every((m) => {
|
|
2348
|
-
if (!disabledDateTimes || !datePrefix) return false;
|
|
2349
|
-
return disabledDateTimes.includes(`${datePrefix}T${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`);
|
|
2350
|
-
}) && "opacity-30 cursor-not-allowed line-through"
|
|
2351
|
-
),
|
|
2352
|
-
children: String(h).padStart(2, "0")
|
|
2353
|
-
},
|
|
2354
|
-
h
|
|
2355
|
-
)) })
|
|
2356
|
-
] }),
|
|
2357
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "w-12", children: [
|
|
2358
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-xs text-muted-foreground mb-1 text-center", children: "MM" }),
|
|
2359
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "grid grid-cols-1 gap-1 max-h-52 overflow-y-auto", children: MINUTES.map((m) => {
|
|
2360
|
-
const h = selected ? (0, import_date_fns.getHours)(selected) : 0;
|
|
2361
|
-
const isDisabled = disabledDateTimes && datePrefix ? disabledDateTimes.includes(`${datePrefix}T${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`) : false;
|
|
2362
|
-
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
2363
|
-
"button",
|
|
2364
|
-
{
|
|
2365
|
-
type: "button",
|
|
2366
|
-
disabled: isDisabled,
|
|
2367
|
-
onClick: () => handleTimeChange(h, m),
|
|
2368
|
-
className: cn(
|
|
2369
|
-
"text-xs rounded py-1 transition-colors",
|
|
2370
|
-
selected && (0, import_date_fns.getMinutes)(selected) === m ? "bg-primary text-primary-foreground" : "hover:bg-white/10 text-foreground",
|
|
2371
|
-
isDisabled && "opacity-30 cursor-not-allowed line-through"
|
|
2372
|
-
),
|
|
2373
|
-
children: [
|
|
2374
|
-
":",
|
|
2375
|
-
String(m).padStart(2, "0")
|
|
2376
|
-
]
|
|
2377
|
-
},
|
|
2378
|
-
m
|
|
2379
|
-
);
|
|
2380
|
-
}) })
|
|
2381
|
-
] })
|
|
2382
|
-
] })
|
|
2383
|
-
] })
|
|
2384
|
-
] }),
|
|
2385
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "border-t border-white/10 px-3 py-2 flex items-center justify-between", children: [
|
|
2386
|
-
/* @__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" }),
|
|
2387
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2388
|
-
"button",
|
|
2389
|
-
{
|
|
2390
|
-
type: "button",
|
|
2391
|
-
onClick: onClose,
|
|
2392
|
-
className: "text-xs rounded-lg bg-primary text-primary-foreground px-3 py-1 hover:opacity-90 transition-opacity",
|
|
2393
|
-
children: "Done"
|
|
2394
|
-
}
|
|
2395
|
-
)
|
|
2396
|
-
] })
|
|
2397
|
-
]
|
|
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"
|
|
2398
2357
|
}
|
|
2399
|
-
)
|
|
2400
|
-
}
|
|
2401
|
-
|
|
2402
|
-
"div",
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
style: { top: "100%", left: 0 },
|
|
2407
|
-
children: [
|
|
2408
|
-
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" }),
|
|
2409
2365
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2410
2366
|
Calendar2,
|
|
2411
2367
|
{
|
|
@@ -2416,46 +2372,91 @@ function DatePickerPopup({
|
|
|
2416
2372
|
onPrevMonth: () => setMonth((m) => (0, import_date_fns.subMonths)(m, 1)),
|
|
2417
2373
|
onNextMonth: () => setMonth((m) => (0, import_date_fns.addMonths)(m, 1))
|
|
2418
2374
|
}
|
|
2419
|
-
)
|
|
2420
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "border-t border-white/10 px-3 py-2 flex items-center justify-between", children: [
|
|
2421
|
-
/* @__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" }),
|
|
2422
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2423
|
-
"button",
|
|
2424
|
-
{
|
|
2425
|
-
type: "button",
|
|
2426
|
-
onClick: onClose,
|
|
2427
|
-
className: "text-xs rounded-lg bg-primary text-primary-foreground px-3 py-1 hover:opacity-90 transition-opacity",
|
|
2428
|
-
children: "Done"
|
|
2429
|
-
}
|
|
2430
|
-
)
|
|
2431
|
-
] })
|
|
2375
|
+
)
|
|
2432
2376
|
] }),
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
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
|
+
] })
|
|
2454
2426
|
] })
|
|
2455
2427
|
] })
|
|
2456
|
-
]
|
|
2457
|
-
|
|
2458
|
-
|
|
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
|
+
] }) });
|
|
2459
2460
|
}
|
|
2460
2461
|
|
|
2461
2462
|
// src/components/ui/date-range-picker.tsx
|
|
@@ -2493,6 +2494,8 @@ function DateRangePicker({
|
|
|
2493
2494
|
const [viewMonth, setViewMonth] = React14.useState(today.getMonth());
|
|
2494
2495
|
const [viewYear, setViewYear] = React14.useState(today.getFullYear());
|
|
2495
2496
|
const ref = React14.useRef(null);
|
|
2497
|
+
const triggerRef = React14.useRef(null);
|
|
2498
|
+
const [dropStyle, setDropStyle] = React14.useState({});
|
|
2496
2499
|
const range2 = controlled ?? internal;
|
|
2497
2500
|
React14.useEffect(() => {
|
|
2498
2501
|
function handler(e) {
|
|
@@ -2505,6 +2508,19 @@ function DateRangePicker({
|
|
|
2505
2508
|
if (!controlled) setInternal(r);
|
|
2506
2509
|
onChange?.(r);
|
|
2507
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
|
+
}
|
|
2508
2524
|
function selectDay(d) {
|
|
2509
2525
|
if (selecting === "from") {
|
|
2510
2526
|
update({ from: d, to: null });
|
|
@@ -2539,9 +2555,10 @@ function DateRangePicker({
|
|
|
2539
2555
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
2540
2556
|
"button",
|
|
2541
2557
|
{
|
|
2558
|
+
ref: triggerRef,
|
|
2542
2559
|
type: "button",
|
|
2543
2560
|
disabled,
|
|
2544
|
-
onClick: () => setOpen(
|
|
2561
|
+
onClick: () => open ? setOpen(false) : openPicker(),
|
|
2545
2562
|
className: cn(
|
|
2546
2563
|
"flex w-full items-center gap-2 rounded-xl border border-border bg-background px-3 py-2 text-sm transition-colors",
|
|
2547
2564
|
"hover:border-primary/40 focus:outline-none focus:ring-2 focus:ring-ring",
|
|
@@ -2567,25 +2584,41 @@ function DateRangePicker({
|
|
|
2567
2584
|
]
|
|
2568
2585
|
}
|
|
2569
2586
|
),
|
|
2570
|
-
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: [
|
|
2571
2588
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center justify-between mb-3", children: [
|
|
2572
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
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
|
+
),
|
|
2578
2603
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "text-sm font-semibold", children: [
|
|
2579
2604
|
MONTHS2[viewMonth],
|
|
2580
2605
|
" ",
|
|
2581
2606
|
viewYear
|
|
2582
2607
|
] }),
|
|
2583
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
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
|
+
)
|
|
2589
2622
|
] }),
|
|
2590
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)) }),
|
|
2591
2624
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "grid grid-cols-7 gap-y-0.5", children: days.map((d, i) => {
|
|
@@ -2620,7 +2653,7 @@ function DateRangePicker({
|
|
|
2620
2653
|
);
|
|
2621
2654
|
}) }),
|
|
2622
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" })
|
|
2623
|
-
] })
|
|
2656
|
+
] }) })
|
|
2624
2657
|
] });
|
|
2625
2658
|
}
|
|
2626
2659
|
|
|
@@ -2722,10 +2755,10 @@ function Drawer({
|
|
|
2722
2755
|
var React16 = __toESM(require("react"), 1);
|
|
2723
2756
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2724
2757
|
var widthMap = {
|
|
2725
|
-
sm:
|
|
2726
|
-
md:
|
|
2727
|
-
lg:
|
|
2728
|
-
auto:
|
|
2758
|
+
sm: 160,
|
|
2759
|
+
md: 224,
|
|
2760
|
+
lg: 288,
|
|
2761
|
+
auto: void 0
|
|
2729
2762
|
};
|
|
2730
2763
|
function Dropdown({
|
|
2731
2764
|
trigger,
|
|
@@ -2739,25 +2772,40 @@ function Dropdown({
|
|
|
2739
2772
|
className
|
|
2740
2773
|
}) {
|
|
2741
2774
|
const [isOpen, setIsOpen] = React16.useState(false);
|
|
2742
|
-
const
|
|
2743
|
-
const
|
|
2775
|
+
const triggerRef = React16.useRef(null);
|
|
2776
|
+
const [dropStyle, setDropStyle] = React16.useState({});
|
|
2777
|
+
const open = () => {
|
|
2744
2778
|
if (disabled) return;
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
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);
|
|
2748
2798
|
};
|
|
2749
2799
|
const close = () => {
|
|
2750
2800
|
setIsOpen(false);
|
|
2751
2801
|
onOpenChange?.(false);
|
|
2752
2802
|
};
|
|
2753
2803
|
React16.useEffect(() => {
|
|
2754
|
-
const handleClickOutside = (
|
|
2755
|
-
if (
|
|
2756
|
-
close();
|
|
2757
|
-
}
|
|
2804
|
+
const handleClickOutside = (e) => {
|
|
2805
|
+
if (triggerRef.current && !triggerRef.current.contains(e.target)) close();
|
|
2758
2806
|
};
|
|
2759
|
-
const handleKeyDown = (
|
|
2760
|
-
if (
|
|
2807
|
+
const handleKeyDown = (e) => {
|
|
2808
|
+
if (e.key === "Escape") close();
|
|
2761
2809
|
};
|
|
2762
2810
|
document.addEventListener("mousedown", handleClickOutside);
|
|
2763
2811
|
document.addEventListener("keydown", handleKeyDown);
|
|
@@ -2766,39 +2814,30 @@ function Dropdown({
|
|
|
2766
2814
|
document.removeEventListener("keydown", handleKeyDown);
|
|
2767
2815
|
};
|
|
2768
2816
|
}, [isOpen]);
|
|
2769
|
-
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: [
|
|
2770
2818
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2771
2819
|
"div",
|
|
2772
2820
|
{
|
|
2773
|
-
onClick:
|
|
2821
|
+
onClick: () => isOpen ? close() : open(),
|
|
2774
2822
|
"aria-expanded": isOpen,
|
|
2775
2823
|
"aria-haspopup": "true",
|
|
2776
2824
|
className: cn(disabled && "opacity-50 cursor-not-allowed pointer-events-none"),
|
|
2777
2825
|
children: trigger
|
|
2778
2826
|
}
|
|
2779
2827
|
),
|
|
2780
|
-
isOpen && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2828
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(FloatingPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2781
2829
|
"div",
|
|
2782
2830
|
{
|
|
2783
2831
|
className: cn(
|
|
2784
|
-
"
|
|
2832
|
+
"rounded-xl border border-white/10 bg-background/90 backdrop-blur-2xl text-popover-foreground",
|
|
2785
2833
|
"shadow-[0_8px_32px_rgba(0,0,0,0.35)] ring-1 ring-white/5",
|
|
2786
2834
|
"animate-in fade-in-0 zoom-in-95 duration-150",
|
|
2787
|
-
widthMap[width],
|
|
2788
|
-
placement === "top" ? "bottom-full mb-2" : "top-full mt-2",
|
|
2789
|
-
align === "right" ? "right-0" : align === "center" ? "left-1/2 -translate-x-1/2" : "left-0",
|
|
2790
2835
|
className
|
|
2791
2836
|
),
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
{
|
|
2795
|
-
className: "py-1.5",
|
|
2796
|
-
onClick: closeOnSelect ? close : void 0,
|
|
2797
|
-
children
|
|
2798
|
-
}
|
|
2799
|
-
)
|
|
2837
|
+
style: dropStyle,
|
|
2838
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "py-1.5", onClick: closeOnSelect ? close : void 0, children })
|
|
2800
2839
|
}
|
|
2801
|
-
)
|
|
2840
|
+
) })
|
|
2802
2841
|
] });
|
|
2803
2842
|
}
|
|
2804
2843
|
function DropdownItem({
|
|
@@ -2831,10 +2870,7 @@ function DropdownItem({
|
|
|
2831
2870
|
function DropdownSeparator({ className }) {
|
|
2832
2871
|
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: cn("my-1.5 h-px bg-white/8", className) });
|
|
2833
2872
|
}
|
|
2834
|
-
function DropdownLabel({
|
|
2835
|
-
children,
|
|
2836
|
-
className
|
|
2837
|
-
}) {
|
|
2873
|
+
function DropdownLabel({ children, className }) {
|
|
2838
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 });
|
|
2839
2875
|
}
|
|
2840
2876
|
|
|
@@ -3696,6 +3732,7 @@ var Input = React18.forwardRef(
|
|
|
3696
3732
|
value: internalValue,
|
|
3697
3733
|
disabledDates,
|
|
3698
3734
|
disabledDateTimes,
|
|
3735
|
+
anchorEl: containerRef.current,
|
|
3699
3736
|
onChange: (v) => {
|
|
3700
3737
|
setInternalValue(v);
|
|
3701
3738
|
setValidationError(null);
|
|
@@ -4087,30 +4124,43 @@ function Select({
|
|
|
4087
4124
|
const [search, setSearch] = React23.useState("");
|
|
4088
4125
|
const [isSearching, setIsSearching] = React23.useState(false);
|
|
4089
4126
|
const containerRef = React23.useRef(null);
|
|
4127
|
+
const triggerRef = React23.useRef(null);
|
|
4128
|
+
const [dropStyle, setDropStyle] = React23.useState({});
|
|
4090
4129
|
const getKey = (opt) => String(Object.keys(opt)[0]);
|
|
4091
4130
|
const getLabel = (opt) => Object.values(opt)[0];
|
|
4092
4131
|
const selectedValues = React23.useMemo(() => {
|
|
4093
|
-
if (multiple && Array.isArray(value))
|
|
4094
|
-
|
|
4095
|
-
} else if (typeof value === "string") {
|
|
4096
|
-
return [value];
|
|
4097
|
-
}
|
|
4132
|
+
if (multiple && Array.isArray(value)) return value;
|
|
4133
|
+
if (typeof value === "string") return [value];
|
|
4098
4134
|
return [];
|
|
4099
4135
|
}, [value, multiple]);
|
|
4100
|
-
const selectedOptions = React23.useMemo(
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
)
|
|
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
|
+
};
|
|
4106
4156
|
React23.useEffect(() => {
|
|
4107
|
-
const
|
|
4108
|
-
if (containerRef.current && !containerRef.current.contains(
|
|
4157
|
+
const handler = (e) => {
|
|
4158
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
4109
4159
|
setIsOpen(false);
|
|
4110
4160
|
}
|
|
4111
4161
|
};
|
|
4112
|
-
document.addEventListener("mousedown",
|
|
4113
|
-
return () => document.removeEventListener("mousedown",
|
|
4162
|
+
document.addEventListener("mousedown", handler);
|
|
4163
|
+
return () => document.removeEventListener("mousedown", handler);
|
|
4114
4164
|
}, []);
|
|
4115
4165
|
const handleSelect = (optionValue) => {
|
|
4116
4166
|
if (multiple) {
|
|
@@ -4124,10 +4174,7 @@ function Select({
|
|
|
4124
4174
|
};
|
|
4125
4175
|
const handleRemove = (optionValue, e) => {
|
|
4126
4176
|
e.stopPropagation();
|
|
4127
|
-
if (multiple)
|
|
4128
|
-
const newValues = selectedValues.filter((v) => v !== optionValue);
|
|
4129
|
-
onChange?.(newValues);
|
|
4130
|
-
}
|
|
4177
|
+
if (multiple) onChange?.(selectedValues.filter((v) => v !== optionValue));
|
|
4131
4178
|
};
|
|
4132
4179
|
const handleReorder = (fromIndex, toIndex) => {
|
|
4133
4180
|
if (!multiple || !reorderable || !Array.isArray(value)) return;
|
|
@@ -4141,16 +4188,13 @@ function Select({
|
|
|
4141
4188
|
e.dataTransfer.setData("text/plain", index.toString());
|
|
4142
4189
|
};
|
|
4143
4190
|
const handleDragOver = (e) => {
|
|
4144
|
-
if (
|
|
4145
|
-
e.preventDefault();
|
|
4191
|
+
if (reorderable) e.preventDefault();
|
|
4146
4192
|
};
|
|
4147
4193
|
const handleDrop = (e, toIndex) => {
|
|
4148
4194
|
if (!reorderable) return;
|
|
4149
4195
|
e.preventDefault();
|
|
4150
4196
|
const fromIndex = parseInt(e.dataTransfer.getData("text/plain"));
|
|
4151
|
-
if (fromIndex !== toIndex)
|
|
4152
|
-
handleReorder(fromIndex, toIndex);
|
|
4153
|
-
}
|
|
4197
|
+
if (fromIndex !== toIndex) handleReorder(fromIndex, toIndex);
|
|
4154
4198
|
};
|
|
4155
4199
|
if (native) {
|
|
4156
4200
|
if (multiple) {
|
|
@@ -4160,58 +4204,29 @@ function Select({
|
|
|
4160
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",
|
|
4161
4205
|
disabled && "opacity-50 pointer-events-none"
|
|
4162
4206
|
), children: [
|
|
4163
|
-
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)(
|
|
4164
|
-
|
|
4165
|
-
{
|
|
4166
|
-
|
|
4167
|
-
children: [
|
|
4168
|
-
getLabel(opt),
|
|
4169
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
4170
|
-
"button",
|
|
4171
|
-
{
|
|
4172
|
-
type: "button",
|
|
4173
|
-
disabled,
|
|
4174
|
-
onClick: () => onChange?.(selectedValues.filter((v) => v !== getKey(opt))),
|
|
4175
|
-
className: "hover:text-destructive",
|
|
4176
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react16.X, { className: "h-3 w-3" })
|
|
4177
|
-
}
|
|
4178
|
-
)
|
|
4179
|
-
]
|
|
4180
|
-
},
|
|
4181
|
-
getKey(opt)
|
|
4182
|
-
)) }),
|
|
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))) }),
|
|
4183
4211
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "max-h-48 overflow-y-auto p-1", children: options.map((option) => {
|
|
4184
4212
|
const checked = selectedValues.includes(getKey(option));
|
|
4185
|
-
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
4186
|
-
"
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
checked ?
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
checked,
|
|
4203
|
-
disabled,
|
|
4204
|
-
onChange: () => {
|
|
4205
|
-
const newValues = checked ? selectedValues.filter((v) => v !== getKey(option)) : [...selectedValues, getKey(option)];
|
|
4206
|
-
onChange?.(newValues);
|
|
4207
|
-
}
|
|
4208
|
-
}
|
|
4209
|
-
),
|
|
4210
|
-
getLabel(option)
|
|
4211
|
-
]
|
|
4212
|
-
},
|
|
4213
|
-
getKey(option)
|
|
4214
|
-
);
|
|
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));
|
|
4215
4230
|
}) })
|
|
4216
4231
|
] })
|
|
4217
4232
|
] });
|
|
@@ -4242,14 +4257,15 @@ function Select({
|
|
|
4242
4257
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
4243
4258
|
"button",
|
|
4244
4259
|
{
|
|
4260
|
+
ref: triggerRef,
|
|
4245
4261
|
type: "button",
|
|
4246
4262
|
className: cn(
|
|
4247
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",
|
|
4248
4264
|
multiple && selectedValues.length > 0 && "flex-wrap gap-1",
|
|
4249
|
-
|
|
4265
|
+
"pr-10",
|
|
4250
4266
|
disabled && "cursor-not-allowed opacity-50"
|
|
4251
4267
|
),
|
|
4252
|
-
onClick: () =>
|
|
4268
|
+
onClick: () => isOpen ? setIsOpen(false) : openDropdown(),
|
|
4253
4269
|
disabled,
|
|
4254
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)(
|
|
4255
4271
|
"span",
|
|
@@ -4258,22 +4274,11 @@ function Select({
|
|
|
4258
4274
|
onDragStart: (e) => handleDragStart(e, index),
|
|
4259
4275
|
onDragOver: handleDragOver,
|
|
4260
4276
|
onDrop: (e) => handleDrop(e, index),
|
|
4261
|
-
className: cn(
|
|
4262
|
-
"inline-flex items-center gap-1 rounded-sm bg-primary/15 text-primary px-2 py-1 text-xs",
|
|
4263
|
-
reorderable && "cursor-move"
|
|
4264
|
-
),
|
|
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"),
|
|
4265
4278
|
children: [
|
|
4266
4279
|
reorderable && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react16.GripVertical, { className: "h-3 w-3 opacity-50" }),
|
|
4267
4280
|
getLabel(option),
|
|
4268
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
4269
|
-
"button",
|
|
4270
|
-
{
|
|
4271
|
-
type: "button",
|
|
4272
|
-
onClick: (e) => handleRemove(getKey(option), e),
|
|
4273
|
-
className: "ml-1 hover:text-destructive",
|
|
4274
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react16.X, { className: "h-3 w-3" })
|
|
4275
|
-
}
|
|
4276
|
-
)
|
|
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" }) })
|
|
4277
4282
|
]
|
|
4278
4283
|
},
|
|
4279
4284
|
getKey(option)
|
|
@@ -4286,50 +4291,56 @@ function Select({
|
|
|
4286
4291
|
{
|
|
4287
4292
|
type: "button",
|
|
4288
4293
|
disabled,
|
|
4289
|
-
onClick: () =>
|
|
4294
|
+
onClick: () => isOpen ? setIsOpen(false) : openDropdown(),
|
|
4290
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",
|
|
4291
|
-
"aria-label": "Open options",
|
|
4292
4296
|
style: iconColor ? { color: iconColor } : void 0,
|
|
4293
4297
|
children: suffixIcon
|
|
4294
4298
|
}
|
|
4295
4299
|
),
|
|
4296
|
-
isOpen && /* @__PURE__ */ (0, import_jsx_runtime28.
|
|
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
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
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
|
+
) })
|
|
4333
4344
|
] })
|
|
4334
4345
|
] });
|
|
4335
4346
|
}
|
|
@@ -5172,7 +5183,7 @@ var import_lucide_react20 = require("lucide-react");
|
|
|
5172
5183
|
|
|
5173
5184
|
// src/components/ui/tooltip.tsx
|
|
5174
5185
|
var React28 = __toESM(require("react"), 1);
|
|
5175
|
-
var
|
|
5186
|
+
var ReactDOM2 = __toESM(require("react-dom"), 1);
|
|
5176
5187
|
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
5177
5188
|
function Tooltip({
|
|
5178
5189
|
content,
|
|
@@ -5227,7 +5238,7 @@ function Tooltip({
|
|
|
5227
5238
|
onBlur: () => setVisible(false),
|
|
5228
5239
|
children: [
|
|
5229
5240
|
children,
|
|
5230
|
-
visible &&
|
|
5241
|
+
visible && ReactDOM2.createPortal(
|
|
5231
5242
|
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
5232
5243
|
"div",
|
|
5233
5244
|
{
|
|
@@ -5502,16 +5513,28 @@ function PanelSidebarGroup({
|
|
|
5502
5513
|
// src/components/ui/popover.tsx
|
|
5503
5514
|
var React31 = __toESM(require("react"), 1);
|
|
5504
5515
|
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
};
|
|
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
|
+
}
|
|
5515
5538
|
function Popover({
|
|
5516
5539
|
trigger,
|
|
5517
5540
|
content,
|
|
@@ -5523,11 +5546,18 @@ function Popover({
|
|
|
5523
5546
|
}) {
|
|
5524
5547
|
const [internal, setInternal] = React31.useState(false);
|
|
5525
5548
|
const ref = React31.useRef(null);
|
|
5549
|
+
const [popStyle, setPopStyle] = React31.useState({});
|
|
5526
5550
|
const open = controlled ?? internal;
|
|
5527
5551
|
function setOpen(v) {
|
|
5528
5552
|
if (controlled === void 0) setInternal(v);
|
|
5529
5553
|
onOpenChange?.(v);
|
|
5530
5554
|
}
|
|
5555
|
+
function openPopover() {
|
|
5556
|
+
if (ref.current) {
|
|
5557
|
+
setPopStyle({ position: "fixed", zIndex: 9999, ...calcStyle(ref.current, placement) });
|
|
5558
|
+
}
|
|
5559
|
+
setOpen(true);
|
|
5560
|
+
}
|
|
5531
5561
|
React31.useEffect(() => {
|
|
5532
5562
|
if (triggerOn !== "click") return;
|
|
5533
5563
|
function handler(e) {
|
|
@@ -5536,14 +5566,17 @@ function Popover({
|
|
|
5536
5566
|
document.addEventListener("mousedown", handler);
|
|
5537
5567
|
return () => document.removeEventListener("mousedown", handler);
|
|
5538
5568
|
}, [triggerOn]);
|
|
5539
|
-
const hoverProps = triggerOn === "hover" ? { onMouseEnter:
|
|
5569
|
+
const hoverProps = triggerOn === "hover" ? { onMouseEnter: openPopover, onMouseLeave: () => setOpen(false) } : {};
|
|
5540
5570
|
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { ref, className: "relative inline-block", ...hoverProps, children: [
|
|
5541
|
-
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { onClick: () => triggerOn === "click" && setOpen(
|
|
5542
|
-
open && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
5543
|
-
"
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
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
|
+
) })
|
|
5547
5580
|
] });
|
|
5548
5581
|
}
|
|
5549
5582
|
|