@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 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((v) => !v),
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: "absolute z-50 mt-1 w-56 rounded-xl border border-border glass shadow-2xl p-3 space-y-3", children: [
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((v) => !v),
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 : selectedLabels || 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.jsxs)("div", { className: "absolute z-50 mt-1 w-full rounded-xl border border-border glass shadow-2xl overflow-hidden", children: [
1160
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-2 border-b border-border px-3 py-2", children: [
1161
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react5.Search, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
1162
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1163
- "input",
1164
- {
1165
- ref: inputRef,
1166
- value: query,
1167
- onChange: (e) => setQuery(e.target.value),
1168
- placeholder: searchPlaceholder,
1169
- className: "flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
1170
- }
1171
- )
1172
- ] }),
1173
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "overflow-y-auto p-1", style: { maxHeight }, children: [
1174
- showCreate && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1175
- "button",
1176
- {
1177
- type: "button",
1178
- onClick: () => {
1179
- toggle(query);
1180
- setQuery("");
1181
- },
1182
- className: "flex w-full items-center gap-2 px-3 py-2 text-sm rounded-lg hover:bg-accent text-primary",
1183
- children: [
1184
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react5.Plus, { className: "h-3.5 w-3.5" }),
1185
- 'Create "',
1186
- query,
1187
- '"'
1188
- ]
1189
- }
1190
- ),
1191
- groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
1192
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "px-3 py-1 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground", children: group }),
1193
- renderOptions(filtered.filter((o) => o.group === group))
1194
- ] }, group)),
1195
- renderOptions(ungrouped),
1196
- 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" })
1197
- ] }),
1198
- 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: [
1199
- options.find((o) => o.value === v)?.label ?? v,
1200
- /* @__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" }) })
1201
- ] }, v)) })
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 ref = React13.useRef(null);
2333
+ const anchorStyle = getAnchorStyle(anchorEl ?? null, mode === "dateTime");
2285
2334
  const commit = (d) => {
2286
- if (mode === "date") {
2287
- onChange((0, import_date_fns.format)(d, "yyyy-MM-dd"));
2288
- } else if (mode === "dateTime") {
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
- const merged = (0, import_date_fns.setMinutes)((0, import_date_fns.setHours)(d, (0, import_date_fns.getHours)(base)), (0, import_date_fns.getMinutes)(base));
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
- const base = selected ?? /* @__PURE__ */ new Date();
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
- if (mode === "dateTime") {
2307
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
2308
- "div",
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
- ref,
2311
- className: "absolute z-50 mt-1 rounded-xl border border-white/10 bg-card shadow-xl backdrop-blur-sm",
2312
- style: { top: "100%", left: 0 },
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
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
2402
- "div",
2403
- {
2404
- ref,
2405
- className: "absolute z-50 mt-1 rounded-xl border border-white/10 bg-card shadow-xl backdrop-blur-sm min-w-[260px]",
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
- mode === "time" && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
2434
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2435
- TimePicker,
2436
- {
2437
- selected,
2438
- disabledDateTimes,
2439
- datePrefix,
2440
- onChange: handleTimeChange
2441
- }
2442
- ),
2443
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "border-t border-white/10 px-3 py-2 flex items-center justify-between", children: [
2444
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-xs text-muted-foreground", children: selected ? (0, import_date_fns.format)(selected, "HH:mm") : "No time selected" }),
2445
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2446
- "button",
2447
- {
2448
- type: "button",
2449
- onClick: onClose,
2450
- className: "text-xs rounded-lg bg-primary text-primary-foreground px-3 py-1 hover:opacity-90 transition-opacity",
2451
- children: "Done"
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((v) => !v),
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: "absolute z-50 mt-1 rounded-xl border border-border glass shadow-2xl p-4 w-72", children: [
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)("button", { type: "button", onClick: () => {
2573
- if (viewMonth === 0) {
2574
- setViewMonth(11);
2575
- setViewYear((y) => y - 1);
2576
- } else setViewMonth((m) => m - 1);
2577
- }, className: "p-1 rounded-md hover:bg-accent transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react11.ChevronLeft, { className: "h-4 w-4" }) }),
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)("button", { type: "button", onClick: () => {
2584
- if (viewMonth === 11) {
2585
- setViewMonth(0);
2586
- setViewYear((y) => y + 1);
2587
- } else setViewMonth((m) => m + 1);
2588
- }, className: "p-1 rounded-md hover:bg-accent transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react11.ChevronRight, { className: "h-4 w-4" }) })
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: "w-40",
2726
- md: "w-56",
2727
- lg: "w-72",
2728
- auto: "w-auto min-w-[10rem]"
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 containerRef = React16.useRef(null);
2743
- const toggle = () => {
2775
+ const triggerRef = React16.useRef(null);
2776
+ const [dropStyle, setDropStyle] = React16.useState({});
2777
+ const open = () => {
2744
2778
  if (disabled) return;
2745
- const next = !isOpen;
2746
- setIsOpen(next);
2747
- onOpenChange?.(next);
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 = (event) => {
2755
- if (containerRef.current && !containerRef.current.contains(event.target)) {
2756
- close();
2757
- }
2804
+ const handleClickOutside = (e) => {
2805
+ if (triggerRef.current && !triggerRef.current.contains(e.target)) close();
2758
2806
  };
2759
- const handleKeyDown = (event) => {
2760
- if (event.key === "Escape") close();
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: containerRef, children: [
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: toggle,
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
- "absolute z-50 rounded-xl border border-white/10 bg-background/90 backdrop-blur-2xl text-popover-foreground",
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
- children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2793
- "div",
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
- return value;
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
- return options.filter((opt) => selectedValues.includes(getKey(opt)));
4102
- }, [options, selectedValues]);
4103
- const filteredOptions = searchable ? options.filter(
4104
- (opt) => getLabel(opt).toLowerCase().includes(search.toLowerCase())
4105
- ) : options;
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 handleClickOutside = (event) => {
4108
- if (containerRef.current && !containerRef.current.contains(event.target)) {
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", handleClickOutside);
4113
- return () => document.removeEventListener("mousedown", handleClickOutside);
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 (!reorderable) return;
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
- "span",
4165
- {
4166
- className: "inline-flex items-center gap-1 rounded-sm bg-primary/15 text-primary px-2 py-0.5 text-xs",
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
- "label",
4187
- {
4188
- className: cn(
4189
- "flex items-center gap-3 rounded-lg px-3 py-2 text-sm cursor-pointer transition-colors hover:bg-accent",
4190
- checked && "bg-primary/8 text-primary"
4191
- ),
4192
- children: [
4193
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: cn(
4194
- "flex h-4 w-4 shrink-0 items-center justify-center rounded border transition-colors",
4195
- checked ? "bg-primary border-primary text-primary-foreground" : "border-slate-900/30 bg-background/50"
4196
- ), children: checked && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react16.Check, { className: "h-3 w-3" }) }),
4197
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
4198
- "input",
4199
- {
4200
- type: "checkbox",
4201
- className: "sr-only",
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
- (suffixIcon || !suffixIcon) && "pr-10",
4265
+ "pr-10",
4250
4266
  disabled && "cursor-not-allowed opacity-50"
4251
4267
  ),
4252
- onClick: () => !disabled && setIsOpen(!isOpen),
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: () => !disabled && setIsOpen(!isOpen),
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.jsxs)("div", { className: "absolute z-50 mt-1 max-h-60 w-full overflow-auto rounded-md border border-white/10 bg-background/80 backdrop-blur-xl text-popover-foreground shadow-lg animate-in fade-in-80", children: [
4297
- 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: [
4298
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react16.Search, { className: "mr-2 h-4 w-4 shrink-0 opacity-50" }),
4299
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
4300
- "input",
4301
- {
4302
- className: "flex h-8 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
4303
- placeholder: searchingMessage,
4304
- value: search,
4305
- onChange: (e) => {
4306
- setSearch(e.target.value);
4307
- setIsSearching(true);
4308
- setTimeout(() => setIsSearching(false), 300);
4309
- },
4310
- onClick: (e) => e.stopPropagation()
4311
- }
4312
- )
4313
- ] }),
4314
- /* @__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: [
4315
- filteredOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
4316
- "div",
4317
- {
4318
- className: cn(
4319
- "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 data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
4320
- (multiple ? selectedValues.includes(getKey(option)) : value === getKey(option)) && "bg-accent text-accent-foreground"
4321
- ),
4322
- onClick: () => handleSelect(getKey(option)),
4323
- children: [
4324
- /* @__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" }) }),
4325
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "truncate", children: getLabel(option) })
4326
- ]
4327
- },
4328
- getKey(option)
4329
- )),
4330
- createOptionForm && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "border-t border-white/10 mt-1 pt-1", children: createOptionForm })
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 ReactDOM = __toESM(require("react-dom"), 1);
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 && ReactDOM.createPortal(
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
- var PLACEMENT_CLASSES = {
5506
- "top": "bottom-full left-1/2 -translate-x-1/2 mb-2",
5507
- "bottom": "top-full left-1/2 -translate-x-1/2 mt-2",
5508
- "left": "right-full top-1/2 -translate-y-1/2 mr-2",
5509
- "right": "left-full top-1/2 -translate-y-1/2 ml-2",
5510
- "top-start": "bottom-full left-0 mb-2",
5511
- "top-end": "bottom-full right-0 mb-2",
5512
- "bottom-start": "top-full left-0 mt-2",
5513
- "bottom-end": "top-full right-0 mt-2"
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: () => setOpen(true), onMouseLeave: () => setOpen(false) } : {};
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(!open), children: trigger }),
5542
- open && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: cn(
5543
- "absolute z-50 min-w-max rounded-xl border border-border glass shadow-2xl",
5544
- PLACEMENT_CLASSES[placement],
5545
- className
5546
- ), children: content })
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