@juv/codego-react-ui 1.1.2 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +536 -451
- package/dist/index.d.cts +29 -3
- package/dist/index.d.ts +29 -3
- package/dist/index.global.js +1176 -1094
- package/dist/index.js +535 -453
- package/package.json +1 -1
package/dist/index.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
|
|
|
@@ -1539,12 +1589,12 @@ function DonutChart({ data, color, height, showValues, unit }) {
|
|
|
1539
1589
|
const total = data.reduce((s, d) => s + d.value, 0) || 1;
|
|
1540
1590
|
const cx = 80, cy = height / 2, r = Math.min(cx, cy) - 10, inner = r * 0.58;
|
|
1541
1591
|
let angle = -Math.PI / 2;
|
|
1542
|
-
const
|
|
1592
|
+
const defaultColors = ["primary", "info", "success", "warning", "danger"];
|
|
1543
1593
|
const slices = data.map((d, i) => {
|
|
1544
1594
|
const sweep = d.value / total * 2 * Math.PI;
|
|
1545
1595
|
const start = angle;
|
|
1546
1596
|
angle += sweep;
|
|
1547
|
-
const c = d.color ??
|
|
1597
|
+
const c = d.color ?? defaultColors[i % defaultColors.length];
|
|
1548
1598
|
return { ...d, start, sweep, color: c };
|
|
1549
1599
|
});
|
|
1550
1600
|
const arc = (cx2, cy2, r2, start, end) => {
|
|
@@ -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
|
{
|
|
@@ -5147,24 +5158,36 @@ function Tooltip({
|
|
|
5147
5158
|
|
|
5148
5159
|
// src/components/theme-provider.tsx
|
|
5149
5160
|
import { createContext as createContext2, useContext as useContext2, useEffect as useEffect18, useState as useState23 } from "react";
|
|
5161
|
+
|
|
5162
|
+
// src/components/conf/settingConfig.json
|
|
5163
|
+
var settingConfig_default = {
|
|
5164
|
+
theme: "dark",
|
|
5165
|
+
fontSize: "16px",
|
|
5166
|
+
fontFamily: '"Space Grotesk", "Inter", sans-serif',
|
|
5167
|
+
colors: {
|
|
5168
|
+
primary: "#8b5cf6",
|
|
5169
|
+
primaryHover: "#7c3aed",
|
|
5170
|
+
secondary: "#171717",
|
|
5171
|
+
secondaryHover: "#262626",
|
|
5172
|
+
info: "#3b82f6",
|
|
5173
|
+
infoHover: "#2563eb",
|
|
5174
|
+
warning: "#f59e0b",
|
|
5175
|
+
warningHover: "#d97706",
|
|
5176
|
+
danger: "#ef4444",
|
|
5177
|
+
dangerHover: "#dc2626"
|
|
5178
|
+
}
|
|
5179
|
+
};
|
|
5180
|
+
|
|
5181
|
+
// src/components/theme-provider.tsx
|
|
5150
5182
|
import { jsx as jsx34 } from "react/jsx-runtime";
|
|
5151
|
-
var
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
info: "#3b82f6",
|
|
5157
|
-
infoHover: "#2563eb",
|
|
5158
|
-
warning: "#f59e0b",
|
|
5159
|
-
warningHover: "#d97706",
|
|
5160
|
-
danger: "#ef4444",
|
|
5161
|
-
dangerHover: "#dc2626"
|
|
5183
|
+
var configDefaults = {
|
|
5184
|
+
theme: settingConfig_default.theme,
|
|
5185
|
+
fontSize: settingConfig_default.fontSize,
|
|
5186
|
+
fontFamily: settingConfig_default.fontFamily,
|
|
5187
|
+
colors: settingConfig_default.colors
|
|
5162
5188
|
};
|
|
5163
5189
|
var initialState = {
|
|
5164
|
-
|
|
5165
|
-
colors: defaultColors,
|
|
5166
|
-
fontSize: "16px",
|
|
5167
|
-
fontFamily: '"Space Grotesk", "Inter", sans-serif',
|
|
5190
|
+
...configDefaults,
|
|
5168
5191
|
setTheme: () => null,
|
|
5169
5192
|
setColors: () => null,
|
|
5170
5193
|
setFontSize: () => null,
|
|
@@ -5174,26 +5197,60 @@ var initialState = {
|
|
|
5174
5197
|
var ThemeProviderContext = createContext2(initialState);
|
|
5175
5198
|
var COLOR_PALETTE = [
|
|
5176
5199
|
{ base: "#6366f1", hover: "#4f46e5" },
|
|
5177
|
-
// Indigo
|
|
5178
5200
|
{ base: "#8b5cf6", hover: "#7c3aed" },
|
|
5179
|
-
// Violet
|
|
5180
5201
|
{ base: "#3b82f6", hover: "#2563eb" },
|
|
5181
|
-
// Blue
|
|
5182
5202
|
{ base: "#10b981", hover: "#059669" },
|
|
5183
|
-
// Emerald
|
|
5184
5203
|
{ base: "#22c55e", hover: "#16a34a" },
|
|
5185
|
-
// Green
|
|
5186
5204
|
{ base: "#eab308", hover: "#ca8a04" },
|
|
5187
|
-
// Yellow
|
|
5188
5205
|
{ base: "#f59e0b", hover: "#d97706" },
|
|
5189
|
-
// Amber
|
|
5190
5206
|
{ base: "#f97316", hover: "#ea580c" },
|
|
5191
|
-
// Orange
|
|
5192
5207
|
{ base: "#ef4444", hover: "#dc2626" },
|
|
5193
|
-
// Red
|
|
5194
5208
|
{ base: "#ec4899", hover: "#db2777" }
|
|
5195
|
-
// Pink
|
|
5196
5209
|
];
|
|
5210
|
+
function ThemeProvider({
|
|
5211
|
+
children,
|
|
5212
|
+
storageKey = "codego-ui-theme-settings",
|
|
5213
|
+
...props
|
|
5214
|
+
}) {
|
|
5215
|
+
const [settings, setSettings] = useState23(() => {
|
|
5216
|
+
try {
|
|
5217
|
+
const stored = localStorage.getItem(storageKey);
|
|
5218
|
+
if (stored) return { ...configDefaults, ...JSON.parse(stored) };
|
|
5219
|
+
} catch {
|
|
5220
|
+
}
|
|
5221
|
+
return configDefaults;
|
|
5222
|
+
});
|
|
5223
|
+
useEffect18(() => {
|
|
5224
|
+
localStorage.setItem(storageKey, JSON.stringify(settings));
|
|
5225
|
+
}, [settings, storageKey]);
|
|
5226
|
+
useEffect18(() => {
|
|
5227
|
+
const root = window.document.documentElement;
|
|
5228
|
+
root.classList.remove("light", "dark");
|
|
5229
|
+
const resolved = settings.theme === "system" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : settings.theme;
|
|
5230
|
+
root.classList.add(resolved);
|
|
5231
|
+
root.style.setProperty("--primary", settings.colors.primary);
|
|
5232
|
+
root.style.setProperty("--primary-hover", settings.colors.primaryHover);
|
|
5233
|
+
root.style.setProperty("--secondary", settings.colors.secondary);
|
|
5234
|
+
root.style.setProperty("--secondary-hover", settings.colors.secondaryHover);
|
|
5235
|
+
root.style.setProperty("--info", settings.colors.info);
|
|
5236
|
+
root.style.setProperty("--info-hover", settings.colors.infoHover);
|
|
5237
|
+
root.style.setProperty("--warning", settings.colors.warning);
|
|
5238
|
+
root.style.setProperty("--warning-hover", settings.colors.warningHover);
|
|
5239
|
+
root.style.setProperty("--danger", settings.colors.danger);
|
|
5240
|
+
root.style.setProperty("--danger-hover", settings.colors.dangerHover);
|
|
5241
|
+
root.style.setProperty("font-size", settings.fontSize);
|
|
5242
|
+
root.style.setProperty("--font-sans", settings.fontFamily);
|
|
5243
|
+
}, [settings]);
|
|
5244
|
+
const value = {
|
|
5245
|
+
...settings,
|
|
5246
|
+
setTheme: (theme) => setSettings((s) => ({ ...s, theme })),
|
|
5247
|
+
setColors: (colors) => setSettings((s) => ({ ...s, colors: { ...s.colors, ...colors } })),
|
|
5248
|
+
setFontSize: (fontSize) => setSettings((s) => ({ ...s, fontSize })),
|
|
5249
|
+
setFontFamily: (fontFamily) => setSettings((s) => ({ ...s, fontFamily })),
|
|
5250
|
+
resetSettings: () => setSettings(configDefaults)
|
|
5251
|
+
};
|
|
5252
|
+
return /* @__PURE__ */ jsx34(ThemeProviderContext.Provider, { ...props, value, children });
|
|
5253
|
+
}
|
|
5197
5254
|
var useTheme = () => {
|
|
5198
5255
|
const context = useContext2(ThemeProviderContext);
|
|
5199
5256
|
if (context === void 0)
|
|
@@ -5353,16 +5410,28 @@ function PanelSidebarGroup({
|
|
|
5353
5410
|
// src/components/ui/popover.tsx
|
|
5354
5411
|
import * as React31 from "react";
|
|
5355
5412
|
import { jsx as jsx36, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
};
|
|
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
|
+
}
|
|
5366
5435
|
function Popover({
|
|
5367
5436
|
trigger,
|
|
5368
5437
|
content,
|
|
@@ -5374,11 +5443,18 @@ function Popover({
|
|
|
5374
5443
|
}) {
|
|
5375
5444
|
const [internal, setInternal] = React31.useState(false);
|
|
5376
5445
|
const ref = React31.useRef(null);
|
|
5446
|
+
const [popStyle, setPopStyle] = React31.useState({});
|
|
5377
5447
|
const open = controlled ?? internal;
|
|
5378
5448
|
function setOpen(v) {
|
|
5379
5449
|
if (controlled === void 0) setInternal(v);
|
|
5380
5450
|
onOpenChange?.(v);
|
|
5381
5451
|
}
|
|
5452
|
+
function openPopover() {
|
|
5453
|
+
if (ref.current) {
|
|
5454
|
+
setPopStyle({ position: "fixed", zIndex: 9999, ...calcStyle(ref.current, placement) });
|
|
5455
|
+
}
|
|
5456
|
+
setOpen(true);
|
|
5457
|
+
}
|
|
5382
5458
|
React31.useEffect(() => {
|
|
5383
5459
|
if (triggerOn !== "click") return;
|
|
5384
5460
|
function handler(e) {
|
|
@@ -5387,14 +5463,17 @@ function Popover({
|
|
|
5387
5463
|
document.addEventListener("mousedown", handler);
|
|
5388
5464
|
return () => document.removeEventListener("mousedown", handler);
|
|
5389
5465
|
}, [triggerOn]);
|
|
5390
|
-
const hoverProps = triggerOn === "hover" ? { onMouseEnter:
|
|
5466
|
+
const hoverProps = triggerOn === "hover" ? { onMouseEnter: openPopover, onMouseLeave: () => setOpen(false) } : {};
|
|
5391
5467
|
return /* @__PURE__ */ jsxs31("div", { ref, className: "relative inline-block", ...hoverProps, children: [
|
|
5392
|
-
/* @__PURE__ */ jsx36("div", { onClick: () => triggerOn === "click" && setOpen(
|
|
5393
|
-
open && /* @__PURE__ */ jsx36(
|
|
5394
|
-
"
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
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
|
+
) })
|
|
5398
5477
|
] });
|
|
5399
5478
|
}
|
|
5400
5479
|
|
|
@@ -5681,7 +5760,7 @@ function RadioGroup({
|
|
|
5681
5760
|
}
|
|
5682
5761
|
|
|
5683
5762
|
// src/components/ui/repeater.tsx
|
|
5684
|
-
import { Plus as
|
|
5763
|
+
import { Plus as Plus3, Trash2 as Trash22, GripVertical as GripVertical4 } from "lucide-react";
|
|
5685
5764
|
import { jsx as jsx40, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
5686
5765
|
function Repeater({
|
|
5687
5766
|
items,
|
|
@@ -5726,7 +5805,7 @@ function Repeater({
|
|
|
5726
5805
|
onClick: onAdd,
|
|
5727
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",
|
|
5728
5807
|
children: [
|
|
5729
|
-
/* @__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" }) }),
|
|
5730
5809
|
addButtonText
|
|
5731
5810
|
]
|
|
5732
5811
|
}
|
|
@@ -7855,6 +7934,7 @@ export {
|
|
|
7855
7934
|
Badge,
|
|
7856
7935
|
Breadcrumb,
|
|
7857
7936
|
Button,
|
|
7937
|
+
COLOR_PALETTE,
|
|
7858
7938
|
Calendar,
|
|
7859
7939
|
Card,
|
|
7860
7940
|
CardContent,
|
|
@@ -7924,6 +8004,7 @@ export {
|
|
|
7924
8004
|
Tabs,
|
|
7925
8005
|
TagInput,
|
|
7926
8006
|
Textarea,
|
|
8007
|
+
ThemeProvider,
|
|
7927
8008
|
Timeline,
|
|
7928
8009
|
ToastProvider,
|
|
7929
8010
|
ToggleSwitch,
|
|
@@ -7932,5 +8013,6 @@ export {
|
|
|
7932
8013
|
TreeView,
|
|
7933
8014
|
Widget,
|
|
7934
8015
|
Wizard,
|
|
8016
|
+
useTheme,
|
|
7935
8017
|
useToast
|
|
7936
8018
|
};
|