@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.js
CHANGED
|
@@ -5,9 +5,25 @@ import { ChevronDown } from "lucide-react";
|
|
|
5
5
|
// src/lib/utils.ts
|
|
6
6
|
import { clsx } from "clsx";
|
|
7
7
|
import { twMerge } from "tailwind-merge";
|
|
8
|
+
import * as ReactDOM from "react-dom";
|
|
8
9
|
function cn(...inputs) {
|
|
9
10
|
return twMerge(clsx(inputs));
|
|
10
11
|
}
|
|
12
|
+
function getPortalPosition(triggerEl, dropdownHeight = 300, preferredPlacement = "bottom") {
|
|
13
|
+
const r = triggerEl.getBoundingClientRect();
|
|
14
|
+
const spaceBelow = window.innerHeight - r.bottom;
|
|
15
|
+
const spaceAbove = r.top;
|
|
16
|
+
const placement = preferredPlacement === "bottom" && spaceBelow < dropdownHeight && spaceAbove > spaceBelow ? "top" : preferredPlacement;
|
|
17
|
+
return {
|
|
18
|
+
top: placement === "bottom" ? r.bottom + 4 : r.top - 4,
|
|
19
|
+
left: r.left,
|
|
20
|
+
width: r.width,
|
|
21
|
+
placement
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function FloatingPortal({ children }) {
|
|
25
|
+
return ReactDOM.createPortal(children, document.body);
|
|
26
|
+
}
|
|
11
27
|
|
|
12
28
|
// src/components/ui/accordion.tsx
|
|
13
29
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -800,6 +816,8 @@ function ColorPicker({
|
|
|
800
816
|
const [opacity, setOpacity] = React7.useState(100);
|
|
801
817
|
const [recent, setRecent] = React7.useState([]);
|
|
802
818
|
const ref = React7.useRef(null);
|
|
819
|
+
const triggerRef = React7.useRef(null);
|
|
820
|
+
const [dropStyle, setDropStyle] = React7.useState({});
|
|
803
821
|
const color = controlled ?? internal;
|
|
804
822
|
React7.useEffect(() => {
|
|
805
823
|
setHex(color);
|
|
@@ -811,6 +829,19 @@ function ColorPicker({
|
|
|
811
829
|
document.addEventListener("mousedown", handler);
|
|
812
830
|
return () => document.removeEventListener("mousedown", handler);
|
|
813
831
|
}, []);
|
|
832
|
+
function openPicker() {
|
|
833
|
+
if (triggerRef.current) {
|
|
834
|
+
const pos = getPortalPosition(triggerRef.current, 280);
|
|
835
|
+
setDropStyle({
|
|
836
|
+
position: "fixed",
|
|
837
|
+
top: pos.placement === "bottom" ? pos.top : void 0,
|
|
838
|
+
bottom: pos.placement === "top" ? window.innerHeight - pos.top : void 0,
|
|
839
|
+
left: pos.left,
|
|
840
|
+
zIndex: 9999
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
setOpen(true);
|
|
844
|
+
}
|
|
814
845
|
function apply(c) {
|
|
815
846
|
if (!controlled) setInternal(c);
|
|
816
847
|
onChange?.(c);
|
|
@@ -825,9 +856,10 @@ function ColorPicker({
|
|
|
825
856
|
/* @__PURE__ */ jsxs8(
|
|
826
857
|
"button",
|
|
827
858
|
{
|
|
859
|
+
ref: triggerRef,
|
|
828
860
|
type: "button",
|
|
829
861
|
disabled,
|
|
830
|
-
onClick: () => setOpen(
|
|
862
|
+
onClick: () => open ? setOpen(false) : openPicker(),
|
|
831
863
|
className: cn(
|
|
832
864
|
"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",
|
|
833
865
|
disabled && "opacity-50 cursor-not-allowed pointer-events-none"
|
|
@@ -838,7 +870,7 @@ function ColorPicker({
|
|
|
838
870
|
]
|
|
839
871
|
}
|
|
840
872
|
),
|
|
841
|
-
open && /* @__PURE__ */ jsxs8("div", { className: "
|
|
873
|
+
open && /* @__PURE__ */ jsx9(FloatingPortal, { children: /* @__PURE__ */ jsxs8("div", { className: "w-56 rounded-xl border border-border glass shadow-2xl p-3 space-y-3", style: dropStyle, children: [
|
|
842
874
|
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
|
|
843
875
|
/* @__PURE__ */ jsx9(
|
|
844
876
|
"input",
|
|
@@ -893,10 +925,7 @@ function ColorPicker({
|
|
|
893
925
|
apply(s);
|
|
894
926
|
setHex(s);
|
|
895
927
|
},
|
|
896
|
-
className: cn(
|
|
897
|
-
"h-6 w-6 rounded-md border transition-transform hover:scale-110",
|
|
898
|
-
color === s ? "border-primary ring-1 ring-primary" : "border-border/60"
|
|
899
|
-
),
|
|
928
|
+
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"),
|
|
900
929
|
style: { backgroundColor: s },
|
|
901
930
|
title: s
|
|
902
931
|
},
|
|
@@ -920,7 +949,7 @@ function ColorPicker({
|
|
|
920
949
|
s
|
|
921
950
|
)) })
|
|
922
951
|
] })
|
|
923
|
-
] })
|
|
952
|
+
] }) })
|
|
924
953
|
] });
|
|
925
954
|
}
|
|
926
955
|
|
|
@@ -947,7 +976,9 @@ function Combobox({
|
|
|
947
976
|
const [open, setOpen] = React8.useState(false);
|
|
948
977
|
const [query, setQuery] = React8.useState("");
|
|
949
978
|
const ref = React8.useRef(null);
|
|
979
|
+
const triggerRef = React8.useRef(null);
|
|
950
980
|
const inputRef = React8.useRef(null);
|
|
981
|
+
const [dropStyle, setDropStyle] = React8.useState({});
|
|
951
982
|
const selected = controlled ?? internal;
|
|
952
983
|
function update(val) {
|
|
953
984
|
if (!controlled) setInternal(val);
|
|
@@ -971,6 +1002,20 @@ function Combobox({
|
|
|
971
1002
|
e.stopPropagation();
|
|
972
1003
|
update(multiple ? [] : "");
|
|
973
1004
|
}
|
|
1005
|
+
const openDropdown = () => {
|
|
1006
|
+
if (triggerRef.current) {
|
|
1007
|
+
const pos = getPortalPosition(triggerRef.current, 300);
|
|
1008
|
+
setDropStyle({
|
|
1009
|
+
position: "fixed",
|
|
1010
|
+
top: pos.placement === "bottom" ? pos.top : void 0,
|
|
1011
|
+
bottom: pos.placement === "top" ? window.innerHeight - pos.top : void 0,
|
|
1012
|
+
left: pos.left,
|
|
1013
|
+
width: pos.width,
|
|
1014
|
+
zIndex: 9999
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
setOpen(true);
|
|
1018
|
+
};
|
|
974
1019
|
React8.useEffect(() => {
|
|
975
1020
|
function handler(e) {
|
|
976
1021
|
if (ref.current && !ref.current.contains(e.target)) {
|
|
@@ -984,13 +1029,10 @@ function Combobox({
|
|
|
984
1029
|
React8.useEffect(() => {
|
|
985
1030
|
if (open) setTimeout(() => inputRef.current?.focus(), 50);
|
|
986
1031
|
}, [open]);
|
|
987
|
-
const filtered = options.filter(
|
|
988
|
-
(o) => o.label.toLowerCase().includes(query.toLowerCase())
|
|
989
|
-
);
|
|
1032
|
+
const filtered = options.filter((o) => o.label.toLowerCase().includes(query.toLowerCase()));
|
|
990
1033
|
const groups = Array.from(new Set(filtered.map((o) => o.group ?? ""))).filter(Boolean);
|
|
991
1034
|
const ungrouped = filtered.filter((o) => !o.group);
|
|
992
1035
|
const showCreate = creatable && query && !options.find((o) => o.label.toLowerCase() === query.toLowerCase());
|
|
993
|
-
const selectedLabels = multiple ? selected.map((v) => options.find((o) => o.value === v)?.label ?? v) : options.find((o) => o.value === selected)?.label;
|
|
994
1036
|
const hasValue = multiple ? selected.length > 0 : !!selected;
|
|
995
1037
|
function renderOptions(opts) {
|
|
996
1038
|
return opts.map((opt) => /* @__PURE__ */ jsxs9(
|
|
@@ -1018,9 +1060,10 @@ function Combobox({
|
|
|
1018
1060
|
/* @__PURE__ */ jsxs9(
|
|
1019
1061
|
"button",
|
|
1020
1062
|
{
|
|
1063
|
+
ref: triggerRef,
|
|
1021
1064
|
type: "button",
|
|
1022
1065
|
disabled,
|
|
1023
|
-
onClick: () => setOpen(
|
|
1066
|
+
onClick: () => open ? setOpen(false) : openDropdown(),
|
|
1024
1067
|
className: cn(
|
|
1025
1068
|
"flex w-full items-center justify-between gap-2 rounded-xl border border-border bg-background px-3 py-2 text-sm transition-colors",
|
|
1026
1069
|
"hover:border-primary/40 focus:outline-none focus:ring-2 focus:ring-ring",
|
|
@@ -1028,7 +1071,7 @@ function Combobox({
|
|
|
1028
1071
|
disabled && "opacity-50 cursor-not-allowed pointer-events-none"
|
|
1029
1072
|
),
|
|
1030
1073
|
children: [
|
|
1031
|
-
/* @__PURE__ */ jsx10("span", { className: cn("flex-1 truncate text-left", !hasValue && "text-muted-foreground"), children: multiple ? selected.length > 0 ? `${selected.length} selected` : placeholder :
|
|
1074
|
+
/* @__PURE__ */ jsx10("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 }),
|
|
1032
1075
|
/* @__PURE__ */ jsxs9("span", { className: "flex items-center gap-1 shrink-0", children: [
|
|
1033
1076
|
clearable && hasValue && /* @__PURE__ */ jsx10("span", { onClick: clear, className: "text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ jsx10(X2, { className: "h-3.5 w-3.5" }) }),
|
|
1034
1077
|
/* @__PURE__ */ jsx10(ChevronDown2, { className: cn("h-4 w-4 text-muted-foreground transition-transform", open && "rotate-180") })
|
|
@@ -1036,50 +1079,57 @@ function Combobox({
|
|
|
1036
1079
|
]
|
|
1037
1080
|
}
|
|
1038
1081
|
),
|
|
1039
|
-
open && /* @__PURE__ */
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1082
|
+
open && /* @__PURE__ */ jsx10(FloatingPortal, { children: /* @__PURE__ */ jsxs9(
|
|
1083
|
+
"div",
|
|
1084
|
+
{
|
|
1085
|
+
className: "rounded-xl border border-border glass shadow-2xl overflow-hidden",
|
|
1086
|
+
style: dropStyle,
|
|
1087
|
+
children: [
|
|
1088
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2 border-b border-border px-3 py-2", children: [
|
|
1089
|
+
/* @__PURE__ */ jsx10(Search, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
|
|
1090
|
+
/* @__PURE__ */ jsx10(
|
|
1091
|
+
"input",
|
|
1092
|
+
{
|
|
1093
|
+
ref: inputRef,
|
|
1094
|
+
value: query,
|
|
1095
|
+
onChange: (e) => setQuery(e.target.value),
|
|
1096
|
+
placeholder: searchPlaceholder,
|
|
1097
|
+
className: "flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
|
|
1098
|
+
}
|
|
1099
|
+
)
|
|
1100
|
+
] }),
|
|
1101
|
+
/* @__PURE__ */ jsxs9("div", { className: "overflow-y-auto p-1", style: { maxHeight }, children: [
|
|
1102
|
+
showCreate && /* @__PURE__ */ jsxs9(
|
|
1103
|
+
"button",
|
|
1104
|
+
{
|
|
1105
|
+
type: "button",
|
|
1106
|
+
onClick: () => {
|
|
1107
|
+
toggle(query);
|
|
1108
|
+
setQuery("");
|
|
1109
|
+
},
|
|
1110
|
+
className: "flex w-full items-center gap-2 px-3 py-2 text-sm rounded-lg hover:bg-accent text-primary",
|
|
1111
|
+
children: [
|
|
1112
|
+
/* @__PURE__ */ jsx10(Plus, { className: "h-3.5 w-3.5" }),
|
|
1113
|
+
'Create "',
|
|
1114
|
+
query,
|
|
1115
|
+
'"'
|
|
1116
|
+
]
|
|
1117
|
+
}
|
|
1118
|
+
),
|
|
1119
|
+
groups.map((group) => /* @__PURE__ */ jsxs9("div", { children: [
|
|
1120
|
+
/* @__PURE__ */ jsx10("p", { className: "px-3 py-1 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground", children: group }),
|
|
1121
|
+
renderOptions(filtered.filter((o) => o.group === group))
|
|
1122
|
+
] }, group)),
|
|
1123
|
+
renderOptions(ungrouped),
|
|
1124
|
+
filtered.length === 0 && !showCreate && /* @__PURE__ */ jsx10("p", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "No results" })
|
|
1125
|
+
] }),
|
|
1126
|
+
multiple && selected.length > 0 && /* @__PURE__ */ jsx10("div", { className: "border-t border-border px-3 py-2 flex flex-wrap gap-1", children: selected.map((v) => /* @__PURE__ */ jsxs9("span", { className: "inline-flex items-center gap-1 rounded-full bg-primary/15 text-primary text-xs px-2 py-0.5", children: [
|
|
1127
|
+
options.find((o) => o.value === v)?.label ?? v,
|
|
1128
|
+
/* @__PURE__ */ jsx10("button", { type: "button", onClick: () => toggle(v), className: "opacity-60 hover:opacity-100", children: /* @__PURE__ */ jsx10(X2, { className: "h-3 w-3" }) })
|
|
1129
|
+
] }, v)) })
|
|
1130
|
+
]
|
|
1131
|
+
}
|
|
1132
|
+
) })
|
|
1083
1133
|
] });
|
|
1084
1134
|
}
|
|
1085
1135
|
|
|
@@ -2053,6 +2103,20 @@ function parseValue(value, mode) {
|
|
|
2053
2103
|
return null;
|
|
2054
2104
|
}
|
|
2055
2105
|
}
|
|
2106
|
+
function getAnchorStyle(anchorEl, wide = false) {
|
|
2107
|
+
if (!anchorEl) return { position: "fixed", top: 0, left: 0, zIndex: 9999 };
|
|
2108
|
+
const r = anchorEl.getBoundingClientRect();
|
|
2109
|
+
const spaceBelow = window.innerHeight - r.bottom;
|
|
2110
|
+
const dropH = wide ? 320 : 300;
|
|
2111
|
+
const placement = spaceBelow < dropH && r.top > spaceBelow ? "top" : "bottom";
|
|
2112
|
+
return {
|
|
2113
|
+
position: "fixed",
|
|
2114
|
+
top: placement === "bottom" ? r.bottom + 4 : void 0,
|
|
2115
|
+
bottom: placement === "top" ? window.innerHeight - r.top + 4 : void 0,
|
|
2116
|
+
left: r.left,
|
|
2117
|
+
zIndex: 9999
|
|
2118
|
+
};
|
|
2119
|
+
}
|
|
2056
2120
|
function TimePicker({
|
|
2057
2121
|
selected,
|
|
2058
2122
|
disabledDateTimes,
|
|
@@ -2120,25 +2184,9 @@ function Calendar2({
|
|
|
2120
2184
|
const isDisabled = (d) => disabledDates?.includes(format(d, "yyyy-MM-dd")) ?? false;
|
|
2121
2185
|
return /* @__PURE__ */ jsxs15("div", { className: "p-3 select-none", children: [
|
|
2122
2186
|
/* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-between mb-3", children: [
|
|
2123
|
-
/* @__PURE__ */ jsx16(
|
|
2124
|
-
"button",
|
|
2125
|
-
{
|
|
2126
|
-
type: "button",
|
|
2127
|
-
onClick: onPrevMonth,
|
|
2128
|
-
className: "p-1 rounded hover:bg-white/10 text-muted-foreground hover:text-foreground transition-colors",
|
|
2129
|
-
children: /* @__PURE__ */ jsx16(ChevronLeft3, { size: 16 })
|
|
2130
|
-
}
|
|
2131
|
-
),
|
|
2187
|
+
/* @__PURE__ */ jsx16("button", { type: "button", onClick: onPrevMonth, className: "p-1 rounded hover:bg-white/10 text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ jsx16(ChevronLeft3, { size: 16 }) }),
|
|
2132
2188
|
/* @__PURE__ */ jsx16("span", { className: "text-sm font-semibold text-foreground", children: format(month, "MMMM yyyy") }),
|
|
2133
|
-
/* @__PURE__ */ jsx16(
|
|
2134
|
-
"button",
|
|
2135
|
-
{
|
|
2136
|
-
type: "button",
|
|
2137
|
-
onClick: onNextMonth,
|
|
2138
|
-
className: "p-1 rounded hover:bg-white/10 text-muted-foreground hover:text-foreground transition-colors",
|
|
2139
|
-
children: /* @__PURE__ */ jsx16(ChevronRight5, { size: 16 })
|
|
2140
|
-
}
|
|
2141
|
-
)
|
|
2189
|
+
/* @__PURE__ */ jsx16("button", { type: "button", onClick: onNextMonth, className: "p-1 rounded hover:bg-white/10 text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ jsx16(ChevronRight5, { size: 16 }) })
|
|
2142
2190
|
] }),
|
|
2143
2191
|
/* @__PURE__ */ jsx16("div", { className: "grid grid-cols-7 mb-1", children: DAYS2.map((d) => /* @__PURE__ */ jsx16("div", { className: "text-center text-xs text-muted-foreground py-1", children: d }, d)) }),
|
|
2144
2192
|
/* @__PURE__ */ jsx16("div", { className: "grid grid-cols-7 gap-y-1", children: days.map((d, i) => {
|
|
@@ -2173,136 +2221,44 @@ function DatePickerPopup({
|
|
|
2173
2221
|
disabledDates,
|
|
2174
2222
|
disabledDateTimes,
|
|
2175
2223
|
onChange,
|
|
2176
|
-
onClose
|
|
2224
|
+
onClose,
|
|
2225
|
+
anchorEl
|
|
2177
2226
|
}) {
|
|
2178
2227
|
const parsed = parseValue(value, mode);
|
|
2179
2228
|
const [month, setMonth] = React13.useState(parsed ?? /* @__PURE__ */ new Date());
|
|
2180
2229
|
const [selected, setSelected] = React13.useState(parsed);
|
|
2181
|
-
const
|
|
2230
|
+
const anchorStyle = getAnchorStyle(anchorEl ?? null, mode === "dateTime");
|
|
2182
2231
|
const commit = (d) => {
|
|
2183
|
-
if (mode === "date")
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
onChange(format(d, "yyyy-MM-dd'T'HH:mm"));
|
|
2187
|
-
} else {
|
|
2188
|
-
onChange(format(d, "HH:mm"));
|
|
2189
|
-
}
|
|
2232
|
+
if (mode === "date") onChange(format(d, "yyyy-MM-dd"));
|
|
2233
|
+
else if (mode === "dateTime") onChange(format(d, "yyyy-MM-dd'T'HH:mm"));
|
|
2234
|
+
else onChange(format(d, "HH:mm"));
|
|
2190
2235
|
setSelected(d);
|
|
2191
2236
|
};
|
|
2192
2237
|
const handleDayClick = (d) => {
|
|
2193
2238
|
const base = selected ?? /* @__PURE__ */ new Date();
|
|
2194
|
-
|
|
2195
|
-
commit(merged);
|
|
2239
|
+
commit(setMinutes(setHours(d, getHours(base)), getMinutes(base)));
|
|
2196
2240
|
};
|
|
2197
2241
|
const handleTimeChange = (h, m) => {
|
|
2198
|
-
|
|
2199
|
-
const merged = setMinutes(setHours(base, h), m);
|
|
2200
|
-
commit(merged);
|
|
2242
|
+
commit(setMinutes(setHours(selected ?? /* @__PURE__ */ new Date(), h), m));
|
|
2201
2243
|
};
|
|
2202
2244
|
const datePrefix = selected ? format(selected, "yyyy-MM-dd") : void 0;
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2245
|
+
const footer = (label) => /* @__PURE__ */ jsxs15("div", { className: "border-t border-white/10 px-3 py-2 flex items-center justify-between", children: [
|
|
2246
|
+
/* @__PURE__ */ jsx16("span", { className: "text-xs text-muted-foreground", children: label }),
|
|
2247
|
+
/* @__PURE__ */ jsx16(
|
|
2248
|
+
"button",
|
|
2206
2249
|
{
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
children:
|
|
2211
|
-
/* @__PURE__ */ jsxs15("div", { className: "flex", children: [
|
|
2212
|
-
/* @__PURE__ */ jsxs15("div", { className: "flex-1 min-w-[240px]", children: [
|
|
2213
|
-
/* @__PURE__ */ jsx16("p", { className: "text-xs font-medium text-muted-foreground px-3 pt-3 pb-1", children: "Date" }),
|
|
2214
|
-
/* @__PURE__ */ jsx16(
|
|
2215
|
-
Calendar2,
|
|
2216
|
-
{
|
|
2217
|
-
selected,
|
|
2218
|
-
month,
|
|
2219
|
-
disabledDates,
|
|
2220
|
-
onDayClick: handleDayClick,
|
|
2221
|
-
onPrevMonth: () => setMonth((m) => subMonths(m, 1)),
|
|
2222
|
-
onNextMonth: () => setMonth((m) => addMonths(m, 1))
|
|
2223
|
-
}
|
|
2224
|
-
)
|
|
2225
|
-
] }),
|
|
2226
|
-
/* @__PURE__ */ jsx16("div", { className: "w-px bg-white/10 my-3" }),
|
|
2227
|
-
/* @__PURE__ */ jsxs15("div", { className: "flex-1 min-w-[140px] flex flex-col", children: [
|
|
2228
|
-
/* @__PURE__ */ jsx16("p", { className: "text-xs font-medium text-muted-foreground px-3 pt-3 pb-1", children: "Time" }),
|
|
2229
|
-
/* @__PURE__ */ jsxs15("div", { className: "flex gap-2 px-3 pb-3 flex-1", children: [
|
|
2230
|
-
/* @__PURE__ */ jsxs15("div", { className: "flex-1", children: [
|
|
2231
|
-
/* @__PURE__ */ jsx16("p", { className: "text-xs text-muted-foreground mb-1 text-center", children: "HH" }),
|
|
2232
|
-
/* @__PURE__ */ jsx16("div", { className: "grid grid-cols-1 gap-1 max-h-52 overflow-y-auto", children: HOURS.map((h) => /* @__PURE__ */ jsx16(
|
|
2233
|
-
"button",
|
|
2234
|
-
{
|
|
2235
|
-
type: "button",
|
|
2236
|
-
disabled: MINUTES.every((m) => {
|
|
2237
|
-
if (!disabledDateTimes || !datePrefix) return false;
|
|
2238
|
-
return disabledDateTimes.includes(`${datePrefix}T${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`);
|
|
2239
|
-
}),
|
|
2240
|
-
onClick: () => handleTimeChange(h, selected ? getMinutes(selected) : 0),
|
|
2241
|
-
className: cn(
|
|
2242
|
-
"text-xs rounded py-1 transition-colors",
|
|
2243
|
-
selected && getHours(selected) === h ? "bg-primary text-primary-foreground" : "hover:bg-white/10 text-foreground",
|
|
2244
|
-
MINUTES.every((m) => {
|
|
2245
|
-
if (!disabledDateTimes || !datePrefix) return false;
|
|
2246
|
-
return disabledDateTimes.includes(`${datePrefix}T${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`);
|
|
2247
|
-
}) && "opacity-30 cursor-not-allowed line-through"
|
|
2248
|
-
),
|
|
2249
|
-
children: String(h).padStart(2, "0")
|
|
2250
|
-
},
|
|
2251
|
-
h
|
|
2252
|
-
)) })
|
|
2253
|
-
] }),
|
|
2254
|
-
/* @__PURE__ */ jsxs15("div", { className: "w-12", children: [
|
|
2255
|
-
/* @__PURE__ */ jsx16("p", { className: "text-xs text-muted-foreground mb-1 text-center", children: "MM" }),
|
|
2256
|
-
/* @__PURE__ */ jsx16("div", { className: "grid grid-cols-1 gap-1 max-h-52 overflow-y-auto", children: MINUTES.map((m) => {
|
|
2257
|
-
const h = selected ? getHours(selected) : 0;
|
|
2258
|
-
const isDisabled = disabledDateTimes && datePrefix ? disabledDateTimes.includes(`${datePrefix}T${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`) : false;
|
|
2259
|
-
return /* @__PURE__ */ jsxs15(
|
|
2260
|
-
"button",
|
|
2261
|
-
{
|
|
2262
|
-
type: "button",
|
|
2263
|
-
disabled: isDisabled,
|
|
2264
|
-
onClick: () => handleTimeChange(h, m),
|
|
2265
|
-
className: cn(
|
|
2266
|
-
"text-xs rounded py-1 transition-colors",
|
|
2267
|
-
selected && getMinutes(selected) === m ? "bg-primary text-primary-foreground" : "hover:bg-white/10 text-foreground",
|
|
2268
|
-
isDisabled && "opacity-30 cursor-not-allowed line-through"
|
|
2269
|
-
),
|
|
2270
|
-
children: [
|
|
2271
|
-
":",
|
|
2272
|
-
String(m).padStart(2, "0")
|
|
2273
|
-
]
|
|
2274
|
-
},
|
|
2275
|
-
m
|
|
2276
|
-
);
|
|
2277
|
-
}) })
|
|
2278
|
-
] })
|
|
2279
|
-
] })
|
|
2280
|
-
] })
|
|
2281
|
-
] }),
|
|
2282
|
-
/* @__PURE__ */ jsxs15("div", { className: "border-t border-white/10 px-3 py-2 flex items-center justify-between", children: [
|
|
2283
|
-
/* @__PURE__ */ jsx16("span", { className: "text-xs text-muted-foreground", children: selected ? format(selected, "MMM d, yyyy HH:mm") : "No date selected" }),
|
|
2284
|
-
/* @__PURE__ */ jsx16(
|
|
2285
|
-
"button",
|
|
2286
|
-
{
|
|
2287
|
-
type: "button",
|
|
2288
|
-
onClick: onClose,
|
|
2289
|
-
className: "text-xs rounded-lg bg-primary text-primary-foreground px-3 py-1 hover:opacity-90 transition-opacity",
|
|
2290
|
-
children: "Done"
|
|
2291
|
-
}
|
|
2292
|
-
)
|
|
2293
|
-
] })
|
|
2294
|
-
]
|
|
2250
|
+
type: "button",
|
|
2251
|
+
onClick: onClose,
|
|
2252
|
+
className: "text-xs rounded-lg bg-primary text-primary-foreground px-3 py-1 hover:opacity-90 transition-opacity",
|
|
2253
|
+
children: "Done"
|
|
2295
2254
|
}
|
|
2296
|
-
)
|
|
2297
|
-
}
|
|
2298
|
-
|
|
2299
|
-
"div",
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
style: { top: "100%", left: 0 },
|
|
2304
|
-
children: [
|
|
2305
|
-
mode === "date" && /* @__PURE__ */ jsxs15(Fragment3, { children: [
|
|
2255
|
+
)
|
|
2256
|
+
] });
|
|
2257
|
+
if (mode === "dateTime") {
|
|
2258
|
+
return /* @__PURE__ */ jsx16(FloatingPortal, { children: /* @__PURE__ */ jsxs15("div", { className: "rounded-xl border border-white/10 bg-card shadow-xl backdrop-blur-sm", style: anchorStyle, children: [
|
|
2259
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex", children: [
|
|
2260
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex-1 min-w-[240px]", children: [
|
|
2261
|
+
/* @__PURE__ */ jsx16("p", { className: "text-xs font-medium text-muted-foreground px-3 pt-3 pb-1", children: "Date" }),
|
|
2306
2262
|
/* @__PURE__ */ jsx16(
|
|
2307
2263
|
Calendar2,
|
|
2308
2264
|
{
|
|
@@ -2313,46 +2269,91 @@ function DatePickerPopup({
|
|
|
2313
2269
|
onPrevMonth: () => setMonth((m) => subMonths(m, 1)),
|
|
2314
2270
|
onNextMonth: () => setMonth((m) => addMonths(m, 1))
|
|
2315
2271
|
}
|
|
2316
|
-
)
|
|
2317
|
-
/* @__PURE__ */ jsxs15("div", { className: "border-t border-white/10 px-3 py-2 flex items-center justify-between", children: [
|
|
2318
|
-
/* @__PURE__ */ jsx16("span", { className: "text-xs text-muted-foreground", children: selected ? format(selected, "MMM d, yyyy") : "No date selected" }),
|
|
2319
|
-
/* @__PURE__ */ jsx16(
|
|
2320
|
-
"button",
|
|
2321
|
-
{
|
|
2322
|
-
type: "button",
|
|
2323
|
-
onClick: onClose,
|
|
2324
|
-
className: "text-xs rounded-lg bg-primary text-primary-foreground px-3 py-1 hover:opacity-90 transition-opacity",
|
|
2325
|
-
children: "Done"
|
|
2326
|
-
}
|
|
2327
|
-
)
|
|
2328
|
-
] })
|
|
2272
|
+
)
|
|
2329
2273
|
] }),
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2274
|
+
/* @__PURE__ */ jsx16("div", { className: "w-px bg-white/10 my-3" }),
|
|
2275
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex-1 min-w-[140px] flex flex-col", children: [
|
|
2276
|
+
/* @__PURE__ */ jsx16("p", { className: "text-xs font-medium text-muted-foreground px-3 pt-3 pb-1", children: "Time" }),
|
|
2277
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex gap-2 px-3 pb-3 flex-1", children: [
|
|
2278
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex-1", children: [
|
|
2279
|
+
/* @__PURE__ */ jsx16("p", { className: "text-xs text-muted-foreground mb-1 text-center", children: "HH" }),
|
|
2280
|
+
/* @__PURE__ */ jsx16("div", { className: "grid grid-cols-1 gap-1 max-h-52 overflow-y-auto", children: HOURS.map((h) => /* @__PURE__ */ jsx16(
|
|
2281
|
+
"button",
|
|
2282
|
+
{
|
|
2283
|
+
type: "button",
|
|
2284
|
+
disabled: MINUTES.every((m) => {
|
|
2285
|
+
if (!disabledDateTimes || !datePrefix) return false;
|
|
2286
|
+
return disabledDateTimes.includes(`${datePrefix}T${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`);
|
|
2287
|
+
}),
|
|
2288
|
+
onClick: () => handleTimeChange(h, selected ? getMinutes(selected) : 0),
|
|
2289
|
+
className: cn(
|
|
2290
|
+
"text-xs rounded py-1 transition-colors",
|
|
2291
|
+
selected && getHours(selected) === h ? "bg-primary text-primary-foreground" : "hover:bg-white/10 text-foreground"
|
|
2292
|
+
),
|
|
2293
|
+
children: String(h).padStart(2, "0")
|
|
2294
|
+
},
|
|
2295
|
+
h
|
|
2296
|
+
)) })
|
|
2297
|
+
] }),
|
|
2298
|
+
/* @__PURE__ */ jsxs15("div", { className: "w-12", children: [
|
|
2299
|
+
/* @__PURE__ */ jsx16("p", { className: "text-xs text-muted-foreground mb-1 text-center", children: "MM" }),
|
|
2300
|
+
/* @__PURE__ */ jsx16("div", { className: "grid grid-cols-1 gap-1 max-h-52 overflow-y-auto", children: MINUTES.map((m) => {
|
|
2301
|
+
const h = selected ? getHours(selected) : 0;
|
|
2302
|
+
const dis = disabledDateTimes && datePrefix ? disabledDateTimes.includes(`${datePrefix}T${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`) : false;
|
|
2303
|
+
return /* @__PURE__ */ jsxs15(
|
|
2304
|
+
"button",
|
|
2305
|
+
{
|
|
2306
|
+
type: "button",
|
|
2307
|
+
disabled: dis,
|
|
2308
|
+
onClick: () => handleTimeChange(h, m),
|
|
2309
|
+
className: cn(
|
|
2310
|
+
"text-xs rounded py-1 transition-colors",
|
|
2311
|
+
selected && getMinutes(selected) === m ? "bg-primary text-primary-foreground" : "hover:bg-white/10 text-foreground",
|
|
2312
|
+
dis && "opacity-30 cursor-not-allowed line-through"
|
|
2313
|
+
),
|
|
2314
|
+
children: [
|
|
2315
|
+
":",
|
|
2316
|
+
String(m).padStart(2, "0")
|
|
2317
|
+
]
|
|
2318
|
+
},
|
|
2319
|
+
m
|
|
2320
|
+
);
|
|
2321
|
+
}) })
|
|
2322
|
+
] })
|
|
2351
2323
|
] })
|
|
2352
2324
|
] })
|
|
2353
|
-
]
|
|
2354
|
-
|
|
2355
|
-
|
|
2325
|
+
] }),
|
|
2326
|
+
footer(selected ? format(selected, "MMM d, yyyy HH:mm") : "No date selected")
|
|
2327
|
+
] }) });
|
|
2328
|
+
}
|
|
2329
|
+
return /* @__PURE__ */ jsx16(FloatingPortal, { children: /* @__PURE__ */ jsxs15("div", { className: "rounded-xl border border-white/10 bg-card shadow-xl backdrop-blur-sm min-w-[260px]", style: anchorStyle, children: [
|
|
2330
|
+
mode === "date" && /* @__PURE__ */ jsxs15(Fragment3, { children: [
|
|
2331
|
+
/* @__PURE__ */ jsx16(
|
|
2332
|
+
Calendar2,
|
|
2333
|
+
{
|
|
2334
|
+
selected,
|
|
2335
|
+
month,
|
|
2336
|
+
disabledDates,
|
|
2337
|
+
onDayClick: handleDayClick,
|
|
2338
|
+
onPrevMonth: () => setMonth((m) => subMonths(m, 1)),
|
|
2339
|
+
onNextMonth: () => setMonth((m) => addMonths(m, 1))
|
|
2340
|
+
}
|
|
2341
|
+
),
|
|
2342
|
+
footer(selected ? format(selected, "MMM d, yyyy") : "No date selected")
|
|
2343
|
+
] }),
|
|
2344
|
+
mode === "time" && /* @__PURE__ */ jsxs15(Fragment3, { children: [
|
|
2345
|
+
/* @__PURE__ */ jsx16(
|
|
2346
|
+
TimePicker,
|
|
2347
|
+
{
|
|
2348
|
+
selected,
|
|
2349
|
+
disabledDateTimes,
|
|
2350
|
+
datePrefix,
|
|
2351
|
+
onChange: handleTimeChange
|
|
2352
|
+
}
|
|
2353
|
+
),
|
|
2354
|
+
footer(selected ? format(selected, "HH:mm") : "No time selected")
|
|
2355
|
+
] })
|
|
2356
|
+
] }) });
|
|
2356
2357
|
}
|
|
2357
2358
|
|
|
2358
2359
|
// src/components/ui/date-range-picker.tsx
|
|
@@ -2390,6 +2391,8 @@ function DateRangePicker({
|
|
|
2390
2391
|
const [viewMonth, setViewMonth] = React14.useState(today.getMonth());
|
|
2391
2392
|
const [viewYear, setViewYear] = React14.useState(today.getFullYear());
|
|
2392
2393
|
const ref = React14.useRef(null);
|
|
2394
|
+
const triggerRef = React14.useRef(null);
|
|
2395
|
+
const [dropStyle, setDropStyle] = React14.useState({});
|
|
2393
2396
|
const range2 = controlled ?? internal;
|
|
2394
2397
|
React14.useEffect(() => {
|
|
2395
2398
|
function handler(e) {
|
|
@@ -2402,6 +2405,19 @@ function DateRangePicker({
|
|
|
2402
2405
|
if (!controlled) setInternal(r);
|
|
2403
2406
|
onChange?.(r);
|
|
2404
2407
|
}
|
|
2408
|
+
function openPicker() {
|
|
2409
|
+
if (triggerRef.current) {
|
|
2410
|
+
const pos = getPortalPosition(triggerRef.current, 340);
|
|
2411
|
+
setDropStyle({
|
|
2412
|
+
position: "fixed",
|
|
2413
|
+
top: pos.placement === "bottom" ? pos.top : void 0,
|
|
2414
|
+
bottom: pos.placement === "top" ? window.innerHeight - pos.top : void 0,
|
|
2415
|
+
left: pos.left,
|
|
2416
|
+
zIndex: 9999
|
|
2417
|
+
});
|
|
2418
|
+
}
|
|
2419
|
+
setOpen(true);
|
|
2420
|
+
}
|
|
2405
2421
|
function selectDay(d) {
|
|
2406
2422
|
if (selecting === "from") {
|
|
2407
2423
|
update({ from: d, to: null });
|
|
@@ -2436,9 +2452,10 @@ function DateRangePicker({
|
|
|
2436
2452
|
/* @__PURE__ */ jsxs16(
|
|
2437
2453
|
"button",
|
|
2438
2454
|
{
|
|
2455
|
+
ref: triggerRef,
|
|
2439
2456
|
type: "button",
|
|
2440
2457
|
disabled,
|
|
2441
|
-
onClick: () => setOpen(
|
|
2458
|
+
onClick: () => open ? setOpen(false) : openPicker(),
|
|
2442
2459
|
className: cn(
|
|
2443
2460
|
"flex w-full items-center gap-2 rounded-xl border border-border bg-background px-3 py-2 text-sm transition-colors",
|
|
2444
2461
|
"hover:border-primary/40 focus:outline-none focus:ring-2 focus:ring-ring",
|
|
@@ -2464,25 +2481,41 @@ function DateRangePicker({
|
|
|
2464
2481
|
]
|
|
2465
2482
|
}
|
|
2466
2483
|
),
|
|
2467
|
-
open && /* @__PURE__ */ jsxs16("div", { className: "
|
|
2484
|
+
open && /* @__PURE__ */ jsx17(FloatingPortal, { children: /* @__PURE__ */ jsxs16("div", { className: "rounded-xl border border-border glass shadow-2xl p-4 w-72", style: dropStyle, children: [
|
|
2468
2485
|
/* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-between mb-3", children: [
|
|
2469
|
-
/* @__PURE__ */ jsx17(
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2486
|
+
/* @__PURE__ */ jsx17(
|
|
2487
|
+
"button",
|
|
2488
|
+
{
|
|
2489
|
+
type: "button",
|
|
2490
|
+
onClick: () => {
|
|
2491
|
+
if (viewMonth === 0) {
|
|
2492
|
+
setViewMonth(11);
|
|
2493
|
+
setViewYear((y) => y - 1);
|
|
2494
|
+
} else setViewMonth((m) => m - 1);
|
|
2495
|
+
},
|
|
2496
|
+
className: "p-1 rounded-md hover:bg-accent transition-colors",
|
|
2497
|
+
children: /* @__PURE__ */ jsx17(ChevronLeft4, { className: "h-4 w-4" })
|
|
2498
|
+
}
|
|
2499
|
+
),
|
|
2475
2500
|
/* @__PURE__ */ jsxs16("span", { className: "text-sm font-semibold", children: [
|
|
2476
2501
|
MONTHS2[viewMonth],
|
|
2477
2502
|
" ",
|
|
2478
2503
|
viewYear
|
|
2479
2504
|
] }),
|
|
2480
|
-
/* @__PURE__ */ jsx17(
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2505
|
+
/* @__PURE__ */ jsx17(
|
|
2506
|
+
"button",
|
|
2507
|
+
{
|
|
2508
|
+
type: "button",
|
|
2509
|
+
onClick: () => {
|
|
2510
|
+
if (viewMonth === 11) {
|
|
2511
|
+
setViewMonth(0);
|
|
2512
|
+
setViewYear((y) => y + 1);
|
|
2513
|
+
} else setViewMonth((m) => m + 1);
|
|
2514
|
+
},
|
|
2515
|
+
className: "p-1 rounded-md hover:bg-accent transition-colors",
|
|
2516
|
+
children: /* @__PURE__ */ jsx17(ChevronRight6, { className: "h-4 w-4" })
|
|
2517
|
+
}
|
|
2518
|
+
)
|
|
2486
2519
|
] }),
|
|
2487
2520
|
/* @__PURE__ */ jsx17("div", { className: "grid grid-cols-7 mb-1", children: DAYS3.map((d) => /* @__PURE__ */ jsx17("div", { className: "text-center text-[10px] font-semibold text-muted-foreground py-1", children: d }, d)) }),
|
|
2488
2521
|
/* @__PURE__ */ jsx17("div", { className: "grid grid-cols-7 gap-y-0.5", children: days.map((d, i) => {
|
|
@@ -2517,7 +2550,7 @@ function DateRangePicker({
|
|
|
2517
2550
|
);
|
|
2518
2551
|
}) }),
|
|
2519
2552
|
/* @__PURE__ */ jsx17("p", { className: "mt-3 text-center text-xs text-muted-foreground", children: selecting === "from" ? "Select start date" : "Select end date" })
|
|
2520
|
-
] })
|
|
2553
|
+
] }) })
|
|
2521
2554
|
] });
|
|
2522
2555
|
}
|
|
2523
2556
|
|
|
@@ -2619,10 +2652,10 @@ function Drawer({
|
|
|
2619
2652
|
import * as React16 from "react";
|
|
2620
2653
|
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2621
2654
|
var widthMap = {
|
|
2622
|
-
sm:
|
|
2623
|
-
md:
|
|
2624
|
-
lg:
|
|
2625
|
-
auto:
|
|
2655
|
+
sm: 160,
|
|
2656
|
+
md: 224,
|
|
2657
|
+
lg: 288,
|
|
2658
|
+
auto: void 0
|
|
2626
2659
|
};
|
|
2627
2660
|
function Dropdown({
|
|
2628
2661
|
trigger,
|
|
@@ -2636,25 +2669,40 @@ function Dropdown({
|
|
|
2636
2669
|
className
|
|
2637
2670
|
}) {
|
|
2638
2671
|
const [isOpen, setIsOpen] = React16.useState(false);
|
|
2639
|
-
const
|
|
2640
|
-
const
|
|
2672
|
+
const triggerRef = React16.useRef(null);
|
|
2673
|
+
const [dropStyle, setDropStyle] = React16.useState({});
|
|
2674
|
+
const open = () => {
|
|
2641
2675
|
if (disabled) return;
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2676
|
+
if (triggerRef.current) {
|
|
2677
|
+
const r = triggerRef.current.getBoundingClientRect();
|
|
2678
|
+
const pos = getPortalPosition(triggerRef.current, 320, placement);
|
|
2679
|
+
const w = widthMap[width];
|
|
2680
|
+
let left = r.left;
|
|
2681
|
+
if (align === "right") left = r.right - (w ?? r.width);
|
|
2682
|
+
if (align === "center") left = r.left + r.width / 2 - (w ?? r.width) / 2;
|
|
2683
|
+
setDropStyle({
|
|
2684
|
+
position: "fixed",
|
|
2685
|
+
top: pos.placement === "bottom" ? pos.top : void 0,
|
|
2686
|
+
bottom: pos.placement === "top" ? window.innerHeight - r.top + 4 : void 0,
|
|
2687
|
+
left,
|
|
2688
|
+
width: w,
|
|
2689
|
+
minWidth: w ? void 0 : "10rem",
|
|
2690
|
+
zIndex: 9999
|
|
2691
|
+
});
|
|
2692
|
+
}
|
|
2693
|
+
setIsOpen(true);
|
|
2694
|
+
onOpenChange?.(true);
|
|
2645
2695
|
};
|
|
2646
2696
|
const close = () => {
|
|
2647
2697
|
setIsOpen(false);
|
|
2648
2698
|
onOpenChange?.(false);
|
|
2649
2699
|
};
|
|
2650
2700
|
React16.useEffect(() => {
|
|
2651
|
-
const handleClickOutside = (
|
|
2652
|
-
if (
|
|
2653
|
-
close();
|
|
2654
|
-
}
|
|
2701
|
+
const handleClickOutside = (e) => {
|
|
2702
|
+
if (triggerRef.current && !triggerRef.current.contains(e.target)) close();
|
|
2655
2703
|
};
|
|
2656
|
-
const handleKeyDown = (
|
|
2657
|
-
if (
|
|
2704
|
+
const handleKeyDown = (e) => {
|
|
2705
|
+
if (e.key === "Escape") close();
|
|
2658
2706
|
};
|
|
2659
2707
|
document.addEventListener("mousedown", handleClickOutside);
|
|
2660
2708
|
document.addEventListener("keydown", handleKeyDown);
|
|
@@ -2663,39 +2711,30 @@ function Dropdown({
|
|
|
2663
2711
|
document.removeEventListener("keydown", handleKeyDown);
|
|
2664
2712
|
};
|
|
2665
2713
|
}, [isOpen]);
|
|
2666
|
-
return /* @__PURE__ */ jsxs18("div", { className: "relative inline-block text-left", ref:
|
|
2714
|
+
return /* @__PURE__ */ jsxs18("div", { className: "relative inline-block text-left", ref: triggerRef, children: [
|
|
2667
2715
|
/* @__PURE__ */ jsx19(
|
|
2668
2716
|
"div",
|
|
2669
2717
|
{
|
|
2670
|
-
onClick:
|
|
2718
|
+
onClick: () => isOpen ? close() : open(),
|
|
2671
2719
|
"aria-expanded": isOpen,
|
|
2672
2720
|
"aria-haspopup": "true",
|
|
2673
2721
|
className: cn(disabled && "opacity-50 cursor-not-allowed pointer-events-none"),
|
|
2674
2722
|
children: trigger
|
|
2675
2723
|
}
|
|
2676
2724
|
),
|
|
2677
|
-
isOpen && /* @__PURE__ */ jsx19(
|
|
2725
|
+
isOpen && /* @__PURE__ */ jsx19(FloatingPortal, { children: /* @__PURE__ */ jsx19(
|
|
2678
2726
|
"div",
|
|
2679
2727
|
{
|
|
2680
2728
|
className: cn(
|
|
2681
|
-
"
|
|
2729
|
+
"rounded-xl border border-white/10 bg-background/90 backdrop-blur-2xl text-popover-foreground",
|
|
2682
2730
|
"shadow-[0_8px_32px_rgba(0,0,0,0.35)] ring-1 ring-white/5",
|
|
2683
2731
|
"animate-in fade-in-0 zoom-in-95 duration-150",
|
|
2684
|
-
widthMap[width],
|
|
2685
|
-
placement === "top" ? "bottom-full mb-2" : "top-full mt-2",
|
|
2686
|
-
align === "right" ? "right-0" : align === "center" ? "left-1/2 -translate-x-1/2" : "left-0",
|
|
2687
2732
|
className
|
|
2688
2733
|
),
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
{
|
|
2692
|
-
className: "py-1.5",
|
|
2693
|
-
onClick: closeOnSelect ? close : void 0,
|
|
2694
|
-
children
|
|
2695
|
-
}
|
|
2696
|
-
)
|
|
2734
|
+
style: dropStyle,
|
|
2735
|
+
children: /* @__PURE__ */ jsx19("div", { className: "py-1.5", onClick: closeOnSelect ? close : void 0, children })
|
|
2697
2736
|
}
|
|
2698
|
-
)
|
|
2737
|
+
) })
|
|
2699
2738
|
] });
|
|
2700
2739
|
}
|
|
2701
2740
|
function DropdownItem({
|
|
@@ -2728,10 +2767,7 @@ function DropdownItem({
|
|
|
2728
2767
|
function DropdownSeparator({ className }) {
|
|
2729
2768
|
return /* @__PURE__ */ jsx19("div", { className: cn("my-1.5 h-px bg-white/8", className) });
|
|
2730
2769
|
}
|
|
2731
|
-
function DropdownLabel({
|
|
2732
|
-
children,
|
|
2733
|
-
className
|
|
2734
|
-
}) {
|
|
2770
|
+
function DropdownLabel({ children, className }) {
|
|
2735
2771
|
return /* @__PURE__ */ jsx19("p", { className: cn("px-3.5 py-1.5 text-xs font-semibold uppercase tracking-wider text-muted-foreground/60", className), children });
|
|
2736
2772
|
}
|
|
2737
2773
|
|
|
@@ -3593,6 +3629,7 @@ var Input = React18.forwardRef(
|
|
|
3593
3629
|
value: internalValue,
|
|
3594
3630
|
disabledDates,
|
|
3595
3631
|
disabledDateTimes,
|
|
3632
|
+
anchorEl: containerRef.current,
|
|
3596
3633
|
onChange: (v) => {
|
|
3597
3634
|
setInternalValue(v);
|
|
3598
3635
|
setValidationError(null);
|
|
@@ -3984,30 +4021,43 @@ function Select({
|
|
|
3984
4021
|
const [search, setSearch] = React23.useState("");
|
|
3985
4022
|
const [isSearching, setIsSearching] = React23.useState(false);
|
|
3986
4023
|
const containerRef = React23.useRef(null);
|
|
4024
|
+
const triggerRef = React23.useRef(null);
|
|
4025
|
+
const [dropStyle, setDropStyle] = React23.useState({});
|
|
3987
4026
|
const getKey = (opt) => String(Object.keys(opt)[0]);
|
|
3988
4027
|
const getLabel = (opt) => Object.values(opt)[0];
|
|
3989
4028
|
const selectedValues = React23.useMemo(() => {
|
|
3990
|
-
if (multiple && Array.isArray(value))
|
|
3991
|
-
|
|
3992
|
-
} else if (typeof value === "string") {
|
|
3993
|
-
return [value];
|
|
3994
|
-
}
|
|
4029
|
+
if (multiple && Array.isArray(value)) return value;
|
|
4030
|
+
if (typeof value === "string") return [value];
|
|
3995
4031
|
return [];
|
|
3996
4032
|
}, [value, multiple]);
|
|
3997
|
-
const selectedOptions = React23.useMemo(
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
)
|
|
4033
|
+
const selectedOptions = React23.useMemo(
|
|
4034
|
+
() => options.filter((opt) => selectedValues.includes(getKey(opt))),
|
|
4035
|
+
[options, selectedValues]
|
|
4036
|
+
);
|
|
4037
|
+
const filteredOptions = searchable ? options.filter((opt) => getLabel(opt).toLowerCase().includes(search.toLowerCase())) : options;
|
|
4038
|
+
const openDropdown = () => {
|
|
4039
|
+
if (disabled) return;
|
|
4040
|
+
if (triggerRef.current) {
|
|
4041
|
+
const pos = getPortalPosition(triggerRef.current, 260);
|
|
4042
|
+
setDropStyle({
|
|
4043
|
+
position: "fixed",
|
|
4044
|
+
top: pos.placement === "bottom" ? pos.top : void 0,
|
|
4045
|
+
bottom: pos.placement === "top" ? window.innerHeight - pos.top : void 0,
|
|
4046
|
+
left: pos.left,
|
|
4047
|
+
width: pos.width,
|
|
4048
|
+
zIndex: 9999
|
|
4049
|
+
});
|
|
4050
|
+
}
|
|
4051
|
+
setIsOpen(true);
|
|
4052
|
+
};
|
|
4003
4053
|
React23.useEffect(() => {
|
|
4004
|
-
const
|
|
4005
|
-
if (containerRef.current && !containerRef.current.contains(
|
|
4054
|
+
const handler = (e) => {
|
|
4055
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
4006
4056
|
setIsOpen(false);
|
|
4007
4057
|
}
|
|
4008
4058
|
};
|
|
4009
|
-
document.addEventListener("mousedown",
|
|
4010
|
-
return () => document.removeEventListener("mousedown",
|
|
4059
|
+
document.addEventListener("mousedown", handler);
|
|
4060
|
+
return () => document.removeEventListener("mousedown", handler);
|
|
4011
4061
|
}, []);
|
|
4012
4062
|
const handleSelect = (optionValue) => {
|
|
4013
4063
|
if (multiple) {
|
|
@@ -4021,10 +4071,7 @@ function Select({
|
|
|
4021
4071
|
};
|
|
4022
4072
|
const handleRemove = (optionValue, e) => {
|
|
4023
4073
|
e.stopPropagation();
|
|
4024
|
-
if (multiple)
|
|
4025
|
-
const newValues = selectedValues.filter((v) => v !== optionValue);
|
|
4026
|
-
onChange?.(newValues);
|
|
4027
|
-
}
|
|
4074
|
+
if (multiple) onChange?.(selectedValues.filter((v) => v !== optionValue));
|
|
4028
4075
|
};
|
|
4029
4076
|
const handleReorder = (fromIndex, toIndex) => {
|
|
4030
4077
|
if (!multiple || !reorderable || !Array.isArray(value)) return;
|
|
@@ -4038,16 +4085,13 @@ function Select({
|
|
|
4038
4085
|
e.dataTransfer.setData("text/plain", index.toString());
|
|
4039
4086
|
};
|
|
4040
4087
|
const handleDragOver = (e) => {
|
|
4041
|
-
if (
|
|
4042
|
-
e.preventDefault();
|
|
4088
|
+
if (reorderable) e.preventDefault();
|
|
4043
4089
|
};
|
|
4044
4090
|
const handleDrop = (e, toIndex) => {
|
|
4045
4091
|
if (!reorderable) return;
|
|
4046
4092
|
e.preventDefault();
|
|
4047
4093
|
const fromIndex = parseInt(e.dataTransfer.getData("text/plain"));
|
|
4048
|
-
if (fromIndex !== toIndex)
|
|
4049
|
-
handleReorder(fromIndex, toIndex);
|
|
4050
|
-
}
|
|
4094
|
+
if (fromIndex !== toIndex) handleReorder(fromIndex, toIndex);
|
|
4051
4095
|
};
|
|
4052
4096
|
if (native) {
|
|
4053
4097
|
if (multiple) {
|
|
@@ -4057,58 +4101,29 @@ function Select({
|
|
|
4057
4101
|
"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",
|
|
4058
4102
|
disabled && "opacity-50 pointer-events-none"
|
|
4059
4103
|
), children: [
|
|
4060
|
-
selectedValues.length > 0 && /* @__PURE__ */ jsx28("div", { className: "flex flex-wrap gap-1 px-3 pt-2 pb-1 border-b border-slate-900/10", children: selectedOptions.map((opt) => /* @__PURE__ */ jsxs24(
|
|
4061
|
-
|
|
4062
|
-
{
|
|
4063
|
-
|
|
4064
|
-
children: [
|
|
4065
|
-
getLabel(opt),
|
|
4066
|
-
/* @__PURE__ */ jsx28(
|
|
4067
|
-
"button",
|
|
4068
|
-
{
|
|
4069
|
-
type: "button",
|
|
4070
|
-
disabled,
|
|
4071
|
-
onClick: () => onChange?.(selectedValues.filter((v) => v !== getKey(opt))),
|
|
4072
|
-
className: "hover:text-destructive",
|
|
4073
|
-
children: /* @__PURE__ */ jsx28(X7, { className: "h-3 w-3" })
|
|
4074
|
-
}
|
|
4075
|
-
)
|
|
4076
|
-
]
|
|
4077
|
-
},
|
|
4078
|
-
getKey(opt)
|
|
4079
|
-
)) }),
|
|
4104
|
+
selectedValues.length > 0 && /* @__PURE__ */ jsx28("div", { className: "flex flex-wrap gap-1 px-3 pt-2 pb-1 border-b border-slate-900/10", children: selectedOptions.map((opt) => /* @__PURE__ */ jsxs24("span", { className: "inline-flex items-center gap-1 rounded-sm bg-primary/15 text-primary px-2 py-0.5 text-xs", children: [
|
|
4105
|
+
getLabel(opt),
|
|
4106
|
+
/* @__PURE__ */ jsx28("button", { type: "button", disabled, onClick: () => onChange?.(selectedValues.filter((v) => v !== getKey(opt))), className: "hover:text-destructive", children: /* @__PURE__ */ jsx28(X7, { className: "h-3 w-3" }) })
|
|
4107
|
+
] }, getKey(opt))) }),
|
|
4080
4108
|
/* @__PURE__ */ jsx28("div", { className: "max-h-48 overflow-y-auto p-1", children: options.map((option) => {
|
|
4081
4109
|
const checked = selectedValues.includes(getKey(option));
|
|
4082
|
-
return /* @__PURE__ */ jsxs24(
|
|
4083
|
-
"
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
checked ?
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
checked,
|
|
4100
|
-
disabled,
|
|
4101
|
-
onChange: () => {
|
|
4102
|
-
const newValues = checked ? selectedValues.filter((v) => v !== getKey(option)) : [...selectedValues, getKey(option)];
|
|
4103
|
-
onChange?.(newValues);
|
|
4104
|
-
}
|
|
4105
|
-
}
|
|
4106
|
-
),
|
|
4107
|
-
getLabel(option)
|
|
4108
|
-
]
|
|
4109
|
-
},
|
|
4110
|
-
getKey(option)
|
|
4111
|
-
);
|
|
4110
|
+
return /* @__PURE__ */ jsxs24("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: [
|
|
4111
|
+
/* @__PURE__ */ jsx28("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__ */ jsx28(Check5, { className: "h-3 w-3" }) }),
|
|
4112
|
+
/* @__PURE__ */ jsx28(
|
|
4113
|
+
"input",
|
|
4114
|
+
{
|
|
4115
|
+
type: "checkbox",
|
|
4116
|
+
className: "sr-only",
|
|
4117
|
+
checked,
|
|
4118
|
+
disabled,
|
|
4119
|
+
onChange: () => {
|
|
4120
|
+
const newValues = checked ? selectedValues.filter((v) => v !== getKey(option)) : [...selectedValues, getKey(option)];
|
|
4121
|
+
onChange?.(newValues);
|
|
4122
|
+
}
|
|
4123
|
+
}
|
|
4124
|
+
),
|
|
4125
|
+
getLabel(option)
|
|
4126
|
+
] }, getKey(option));
|
|
4112
4127
|
}) })
|
|
4113
4128
|
] })
|
|
4114
4129
|
] });
|
|
@@ -4139,14 +4154,15 @@ function Select({
|
|
|
4139
4154
|
/* @__PURE__ */ jsx28(
|
|
4140
4155
|
"button",
|
|
4141
4156
|
{
|
|
4157
|
+
ref: triggerRef,
|
|
4142
4158
|
type: "button",
|
|
4143
4159
|
className: cn(
|
|
4144
4160
|
"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",
|
|
4145
4161
|
multiple && selectedValues.length > 0 && "flex-wrap gap-1",
|
|
4146
|
-
|
|
4162
|
+
"pr-10",
|
|
4147
4163
|
disabled && "cursor-not-allowed opacity-50"
|
|
4148
4164
|
),
|
|
4149
|
-
onClick: () =>
|
|
4165
|
+
onClick: () => isOpen ? setIsOpen(false) : openDropdown(),
|
|
4150
4166
|
disabled,
|
|
4151
4167
|
children: multiple && selectedOptions.length > 0 ? /* @__PURE__ */ jsx28("div", { className: "flex flex-wrap gap-1 flex-1 min-w-0", children: selectedOptions.map((option, index) => /* @__PURE__ */ jsxs24(
|
|
4152
4168
|
"span",
|
|
@@ -4155,22 +4171,11 @@ function Select({
|
|
|
4155
4171
|
onDragStart: (e) => handleDragStart(e, index),
|
|
4156
4172
|
onDragOver: handleDragOver,
|
|
4157
4173
|
onDrop: (e) => handleDrop(e, index),
|
|
4158
|
-
className: cn(
|
|
4159
|
-
"inline-flex items-center gap-1 rounded-sm bg-primary/15 text-primary px-2 py-1 text-xs",
|
|
4160
|
-
reorderable && "cursor-move"
|
|
4161
|
-
),
|
|
4174
|
+
className: cn("inline-flex items-center gap-1 rounded-sm bg-primary/15 text-primary px-2 py-1 text-xs", reorderable && "cursor-move"),
|
|
4162
4175
|
children: [
|
|
4163
4176
|
reorderable && /* @__PURE__ */ jsx28(GripVertical3, { className: "h-3 w-3 opacity-50" }),
|
|
4164
4177
|
getLabel(option),
|
|
4165
|
-
/* @__PURE__ */ jsx28(
|
|
4166
|
-
"button",
|
|
4167
|
-
{
|
|
4168
|
-
type: "button",
|
|
4169
|
-
onClick: (e) => handleRemove(getKey(option), e),
|
|
4170
|
-
className: "ml-1 hover:text-destructive",
|
|
4171
|
-
children: /* @__PURE__ */ jsx28(X7, { className: "h-3 w-3" })
|
|
4172
|
-
}
|
|
4173
|
-
)
|
|
4178
|
+
/* @__PURE__ */ jsx28("button", { type: "button", onClick: (e) => handleRemove(getKey(option), e), className: "ml-1 hover:text-destructive", children: /* @__PURE__ */ jsx28(X7, { className: "h-3 w-3" }) })
|
|
4174
4179
|
]
|
|
4175
4180
|
},
|
|
4176
4181
|
getKey(option)
|
|
@@ -4183,50 +4188,56 @@ function Select({
|
|
|
4183
4188
|
{
|
|
4184
4189
|
type: "button",
|
|
4185
4190
|
disabled,
|
|
4186
|
-
onClick: () =>
|
|
4191
|
+
onClick: () => isOpen ? setIsOpen(false) : openDropdown(),
|
|
4187
4192
|
className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors z-10 disabled:opacity-50",
|
|
4188
|
-
"aria-label": "Open options",
|
|
4189
4193
|
style: iconColor ? { color: iconColor } : void 0,
|
|
4190
4194
|
children: suffixIcon
|
|
4191
4195
|
}
|
|
4192
4196
|
),
|
|
4193
|
-
isOpen && /* @__PURE__ */
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4197
|
+
isOpen && /* @__PURE__ */ jsx28(FloatingPortal, { children: /* @__PURE__ */ jsxs24(
|
|
4198
|
+
"div",
|
|
4199
|
+
{
|
|
4200
|
+
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",
|
|
4201
|
+
style: dropStyle,
|
|
4202
|
+
children: [
|
|
4203
|
+
searchable && /* @__PURE__ */ jsxs24("div", { className: "sticky top-0 z-10 flex items-center border-b border-white/10 bg-background/90 px-3 py-2", children: [
|
|
4204
|
+
/* @__PURE__ */ jsx28(Search4, { className: "mr-2 h-4 w-4 shrink-0 opacity-50" }),
|
|
4205
|
+
/* @__PURE__ */ jsx28(
|
|
4206
|
+
"input",
|
|
4207
|
+
{
|
|
4208
|
+
className: "flex h-8 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground",
|
|
4209
|
+
placeholder: searchingMessage,
|
|
4210
|
+
value: search,
|
|
4211
|
+
onChange: (e) => {
|
|
4212
|
+
setSearch(e.target.value);
|
|
4213
|
+
setIsSearching(true);
|
|
4214
|
+
setTimeout(() => setIsSearching(false), 300);
|
|
4215
|
+
},
|
|
4216
|
+
onClick: (e) => e.stopPropagation()
|
|
4217
|
+
}
|
|
4218
|
+
)
|
|
4219
|
+
] }),
|
|
4220
|
+
/* @__PURE__ */ jsx28("div", { className: "p-1", children: isSearching ? /* @__PURE__ */ jsx28("div", { className: "py-6 text-center text-sm text-muted-foreground", children: loadingMessage }) : filteredOptions.length === 0 ? /* @__PURE__ */ jsx28("div", { className: "py-6 text-center text-sm text-muted-foreground", children: search ? noSearchResultsMessage : "No options available." }) : /* @__PURE__ */ jsxs24(Fragment5, { children: [
|
|
4221
|
+
filteredOptions.map((option) => /* @__PURE__ */ jsxs24(
|
|
4222
|
+
"div",
|
|
4223
|
+
{
|
|
4224
|
+
className: cn(
|
|
4225
|
+
"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",
|
|
4226
|
+
(multiple ? selectedValues.includes(getKey(option)) : value === getKey(option)) && "bg-accent text-accent-foreground"
|
|
4227
|
+
),
|
|
4228
|
+
onClick: () => handleSelect(getKey(option)),
|
|
4229
|
+
children: [
|
|
4230
|
+
/* @__PURE__ */ jsx28("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__ */ jsx28(Check5, { className: "h-4 w-4" }) }),
|
|
4231
|
+
/* @__PURE__ */ jsx28("span", { className: "truncate", children: getLabel(option) })
|
|
4232
|
+
]
|
|
4233
|
+
},
|
|
4234
|
+
getKey(option)
|
|
4235
|
+
)),
|
|
4236
|
+
createOptionForm && /* @__PURE__ */ jsx28("div", { className: "border-t border-white/10 mt-1 pt-1", children: createOptionForm })
|
|
4237
|
+
] }) })
|
|
4238
|
+
]
|
|
4239
|
+
}
|
|
4240
|
+
) })
|
|
4230
4241
|
] })
|
|
4231
4242
|
] });
|
|
4232
4243
|
}
|
|
@@ -5069,7 +5080,7 @@ import { PanelLeftClose, PanelLeftOpen, Sun as Sun2, Moon } from "lucide-react";
|
|
|
5069
5080
|
|
|
5070
5081
|
// src/components/ui/tooltip.tsx
|
|
5071
5082
|
import * as React28 from "react";
|
|
5072
|
-
import * as
|
|
5083
|
+
import * as ReactDOM2 from "react-dom";
|
|
5073
5084
|
import { Fragment as Fragment7, jsx as jsx33, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
5074
5085
|
function Tooltip({
|
|
5075
5086
|
content,
|
|
@@ -5124,7 +5135,7 @@ function Tooltip({
|
|
|
5124
5135
|
onBlur: () => setVisible(false),
|
|
5125
5136
|
children: [
|
|
5126
5137
|
children,
|
|
5127
|
-
visible &&
|
|
5138
|
+
visible && ReactDOM2.createPortal(
|
|
5128
5139
|
/* @__PURE__ */ jsx33(
|
|
5129
5140
|
"div",
|
|
5130
5141
|
{
|
|
@@ -5399,16 +5410,28 @@ function PanelSidebarGroup({
|
|
|
5399
5410
|
// src/components/ui/popover.tsx
|
|
5400
5411
|
import * as React31 from "react";
|
|
5401
5412
|
import { jsx as jsx36, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
};
|
|
5413
|
+
function calcStyle(triggerEl, placement) {
|
|
5414
|
+
const r = triggerEl.getBoundingClientRect();
|
|
5415
|
+
const GAP = 8;
|
|
5416
|
+
switch (placement) {
|
|
5417
|
+
case "bottom":
|
|
5418
|
+
return { top: r.bottom + GAP, left: r.left + r.width / 2, transform: "translateX(-50%)" };
|
|
5419
|
+
case "bottom-start":
|
|
5420
|
+
return { top: r.bottom + GAP, left: r.left };
|
|
5421
|
+
case "bottom-end":
|
|
5422
|
+
return { top: r.bottom + GAP, left: r.right, transform: "translateX(-100%)" };
|
|
5423
|
+
case "top":
|
|
5424
|
+
return { top: r.top - GAP, left: r.left + r.width / 2, transform: "translate(-50%, -100%)" };
|
|
5425
|
+
case "top-start":
|
|
5426
|
+
return { top: r.top - GAP, left: r.left, transform: "translateY(-100%)" };
|
|
5427
|
+
case "top-end":
|
|
5428
|
+
return { top: r.top - GAP, left: r.right, transform: "translate(-100%, -100%)" };
|
|
5429
|
+
case "left":
|
|
5430
|
+
return { top: r.top + r.height / 2, left: r.left - GAP, transform: "translate(-100%, -50%)" };
|
|
5431
|
+
case "right":
|
|
5432
|
+
return { top: r.top + r.height / 2, left: r.right + GAP, transform: "translateY(-50%)" };
|
|
5433
|
+
}
|
|
5434
|
+
}
|
|
5412
5435
|
function Popover({
|
|
5413
5436
|
trigger,
|
|
5414
5437
|
content,
|
|
@@ -5420,11 +5443,18 @@ function Popover({
|
|
|
5420
5443
|
}) {
|
|
5421
5444
|
const [internal, setInternal] = React31.useState(false);
|
|
5422
5445
|
const ref = React31.useRef(null);
|
|
5446
|
+
const [popStyle, setPopStyle] = React31.useState({});
|
|
5423
5447
|
const open = controlled ?? internal;
|
|
5424
5448
|
function setOpen(v) {
|
|
5425
5449
|
if (controlled === void 0) setInternal(v);
|
|
5426
5450
|
onOpenChange?.(v);
|
|
5427
5451
|
}
|
|
5452
|
+
function openPopover() {
|
|
5453
|
+
if (ref.current) {
|
|
5454
|
+
setPopStyle({ position: "fixed", zIndex: 9999, ...calcStyle(ref.current, placement) });
|
|
5455
|
+
}
|
|
5456
|
+
setOpen(true);
|
|
5457
|
+
}
|
|
5428
5458
|
React31.useEffect(() => {
|
|
5429
5459
|
if (triggerOn !== "click") return;
|
|
5430
5460
|
function handler(e) {
|
|
@@ -5433,14 +5463,17 @@ function Popover({
|
|
|
5433
5463
|
document.addEventListener("mousedown", handler);
|
|
5434
5464
|
return () => document.removeEventListener("mousedown", handler);
|
|
5435
5465
|
}, [triggerOn]);
|
|
5436
|
-
const hoverProps = triggerOn === "hover" ? { onMouseEnter:
|
|
5466
|
+
const hoverProps = triggerOn === "hover" ? { onMouseEnter: openPopover, onMouseLeave: () => setOpen(false) } : {};
|
|
5437
5467
|
return /* @__PURE__ */ jsxs31("div", { ref, className: "relative inline-block", ...hoverProps, children: [
|
|
5438
|
-
/* @__PURE__ */ jsx36("div", { onClick: () => triggerOn === "click" && setOpen(
|
|
5439
|
-
open && /* @__PURE__ */ jsx36(
|
|
5440
|
-
"
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5468
|
+
/* @__PURE__ */ jsx36("div", { onClick: () => triggerOn === "click" && (open ? setOpen(false) : openPopover()), children: trigger }),
|
|
5469
|
+
open && /* @__PURE__ */ jsx36(FloatingPortal, { children: /* @__PURE__ */ jsx36(
|
|
5470
|
+
"div",
|
|
5471
|
+
{
|
|
5472
|
+
className: cn("min-w-max rounded-xl border border-border glass shadow-2xl", className),
|
|
5473
|
+
style: popStyle,
|
|
5474
|
+
children: content
|
|
5475
|
+
}
|
|
5476
|
+
) })
|
|
5444
5477
|
] });
|
|
5445
5478
|
}
|
|
5446
5479
|
|
|
@@ -5727,7 +5760,7 @@ function RadioGroup({
|
|
|
5727
5760
|
}
|
|
5728
5761
|
|
|
5729
5762
|
// src/components/ui/repeater.tsx
|
|
5730
|
-
import { Plus as
|
|
5763
|
+
import { Plus as Plus3, Trash2 as Trash22, GripVertical as GripVertical4 } from "lucide-react";
|
|
5731
5764
|
import { jsx as jsx40, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
5732
5765
|
function Repeater({
|
|
5733
5766
|
items,
|
|
@@ -5772,7 +5805,7 @@ function Repeater({
|
|
|
5772
5805
|
onClick: onAdd,
|
|
5773
5806
|
className: "group flex w-full items-center justify-center gap-2 rounded-xl border border-dashed border-border py-3 text-sm font-medium text-muted-foreground transition-all duration-200 hover:border-primary/50 hover:bg-primary/5 hover:text-primary",
|
|
5774
5807
|
children: [
|
|
5775
|
-
/* @__PURE__ */ jsx40("span", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-muted group-hover:bg-primary/10 transition-colors", children: /* @__PURE__ */ jsx40(
|
|
5808
|
+
/* @__PURE__ */ jsx40("span", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-muted group-hover:bg-primary/10 transition-colors", children: /* @__PURE__ */ jsx40(Plus3, { className: "h-3 w-3" }) }),
|
|
5776
5809
|
addButtonText
|
|
5777
5810
|
]
|
|
5778
5811
|
}
|