@particle-academy/react-fancy 1.5.1 → 1.7.0
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/README.md +14 -2
- package/dist/index.cjs +1062 -392
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +98 -16
- package/dist/index.d.ts +98 -16
- package/dist/index.js +1064 -394
- package/dist/index.js.map +1 -1
- package/dist/styles.css +57 -0
- package/dist/styles.css.map +1 -1
- package/package.json +10 -9
package/dist/index.cjs
CHANGED
|
@@ -1323,13 +1323,6 @@ var avatarSize = {
|
|
|
1323
1323
|
lg: "w-6 h-6",
|
|
1324
1324
|
xl: "w-7 h-7"
|
|
1325
1325
|
};
|
|
1326
|
-
var alertIconSize = {
|
|
1327
|
-
xs: "w-2 h-2",
|
|
1328
|
-
sm: "w-2.5 h-2.5",
|
|
1329
|
-
md: "w-3 h-3",
|
|
1330
|
-
lg: "w-4 h-4",
|
|
1331
|
-
xl: "w-4 h-4"
|
|
1332
|
-
};
|
|
1333
1326
|
var badgeSize = {
|
|
1334
1327
|
xs: "text-[10px] px-1 min-w-[14px] h-3.5",
|
|
1335
1328
|
sm: "text-[10px] px-1.5 min-w-[16px] h-4",
|
|
@@ -1441,7 +1434,7 @@ var Action = react.forwardRef(
|
|
|
1441
1434
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1442
1435
|
"span",
|
|
1443
1436
|
{
|
|
1444
|
-
className: cn("flex-shrink-0", iconColorCls),
|
|
1437
|
+
className: cn("inline-flex items-center flex-shrink-0", iconColorCls),
|
|
1445
1438
|
children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: iconSlug, size: iconSizeMap[size] })
|
|
1446
1439
|
},
|
|
1447
1440
|
`icon-${trailing ? "t" : "l"}`
|
|
@@ -1495,17 +1488,8 @@ var Action = react.forwardRef(
|
|
|
1495
1488
|
className: "relative inline-flex flex-shrink-0",
|
|
1496
1489
|
"data-action-alert": true,
|
|
1497
1490
|
children: [
|
|
1498
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className:
|
|
1499
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1500
|
-
"span",
|
|
1501
|
-
{
|
|
1502
|
-
className: cn(
|
|
1503
|
-
alertIconSize[size],
|
|
1504
|
-
"absolute inset-0 text-red-400 dark:text-red-300 animate-ping opacity-75"
|
|
1505
|
-
),
|
|
1506
|
-
children: alertIconEl
|
|
1507
|
-
}
|
|
1508
|
-
)
|
|
1491
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500 dark:text-red-400 animate-pulse", children: alertIconEl }),
|
|
1492
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inset-0 flex items-center justify-center text-red-400 dark:text-red-300 animate-ping opacity-75", children: alertIconEl })
|
|
1509
1493
|
]
|
|
1510
1494
|
},
|
|
1511
1495
|
"alert-icon"
|
|
@@ -1645,7 +1629,7 @@ function dirtyRingClasses(dirty) {
|
|
|
1645
1629
|
function errorClasses(error) {
|
|
1646
1630
|
return error ? "border-red-500 focus:ring-red-500" : "";
|
|
1647
1631
|
}
|
|
1648
|
-
var inputBaseClasses = "border border-zinc-300 bg-white text-zinc-900 placeholder:text-zinc-400 focus:outline-none focus:ring-2 focus:ring-blue-500/40 focus:border-blue-500 disabled:opacity-50 disabled:cursor-not-allowed dark:border-zinc-
|
|
1632
|
+
var inputBaseClasses = "border border-zinc-300 bg-white text-zinc-900 placeholder:text-zinc-400 transition-[border-color,box-shadow] duration-150 focus:outline-none focus:ring-2 focus:ring-blue-500/40 focus:border-blue-500 disabled:opacity-50 disabled:cursor-not-allowed dark:border-zinc-700 dark:bg-[#1e1e24] dark:text-zinc-100 dark:placeholder:text-zinc-500 dark:focus:border-blue-400 dark:focus:ring-blue-400/20";
|
|
1649
1633
|
function resolveOption(option) {
|
|
1650
1634
|
if (typeof option === "string") {
|
|
1651
1635
|
return { value: option, label: option };
|
|
@@ -1662,13 +1646,13 @@ function Field({
|
|
|
1662
1646
|
children,
|
|
1663
1647
|
className
|
|
1664
1648
|
}) {
|
|
1665
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-react-fancy-field": "", className: cn("flex flex-col gap-
|
|
1649
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-react-fancy-field": "", className: cn("flex flex-col gap-2", className), children: [
|
|
1666
1650
|
label && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1667
1651
|
"label",
|
|
1668
1652
|
{
|
|
1669
1653
|
htmlFor,
|
|
1670
1654
|
className: cn(
|
|
1671
|
-
"font-medium text-zinc-700 dark:text-zinc-
|
|
1655
|
+
"font-medium text-zinc-700 dark:text-zinc-100",
|
|
1672
1656
|
labelSizeClasses[size]
|
|
1673
1657
|
),
|
|
1674
1658
|
children: [
|
|
@@ -1696,7 +1680,7 @@ var insidePaddingRight = {
|
|
|
1696
1680
|
lg: "pr-10",
|
|
1697
1681
|
xl: "pr-11"
|
|
1698
1682
|
};
|
|
1699
|
-
var affixOutsideClasses = "inline-flex items-center border border-zinc-300 bg-zinc-50 px-3 text-sm text-zinc-500 dark:border-zinc-
|
|
1683
|
+
var affixOutsideClasses = "inline-flex items-center border border-zinc-300 bg-zinc-50 px-3 text-sm text-zinc-500 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-400";
|
|
1700
1684
|
function InputWrapper({
|
|
1701
1685
|
children,
|
|
1702
1686
|
prefix,
|
|
@@ -1940,10 +1924,157 @@ var Textarea = react.forwardRef(
|
|
|
1940
1924
|
}
|
|
1941
1925
|
);
|
|
1942
1926
|
Textarea.displayName = "Textarea";
|
|
1927
|
+
function Portal({ children, container }) {
|
|
1928
|
+
if (typeof document === "undefined") return null;
|
|
1929
|
+
const target = container ?? document.body;
|
|
1930
|
+
return reactDom.createPortal(
|
|
1931
|
+
/* @__PURE__ */ jsxRuntime.jsx(PortalDarkWrapper, { children }),
|
|
1932
|
+
target
|
|
1933
|
+
);
|
|
1934
|
+
}
|
|
1935
|
+
function PortalDarkWrapper({ children }) {
|
|
1936
|
+
const ref = react.useRef(null);
|
|
1937
|
+
react.useEffect(() => {
|
|
1938
|
+
const root = document.documentElement;
|
|
1939
|
+
const wrapper = ref.current;
|
|
1940
|
+
if (!wrapper) return;
|
|
1941
|
+
const sync = () => {
|
|
1942
|
+
const isDark = root.classList.contains("dark") || root.getAttribute("data-theme") === "dark";
|
|
1943
|
+
wrapper.classList.toggle("dark", isDark);
|
|
1944
|
+
};
|
|
1945
|
+
sync();
|
|
1946
|
+
const observer = new MutationObserver(sync);
|
|
1947
|
+
observer.observe(root, {
|
|
1948
|
+
attributes: true,
|
|
1949
|
+
attributeFilter: ["class", "data-theme"]
|
|
1950
|
+
});
|
|
1951
|
+
return () => observer.disconnect();
|
|
1952
|
+
}, []);
|
|
1953
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, "data-react-fancy-portal": "", style: { display: "contents" }, children });
|
|
1954
|
+
}
|
|
1955
|
+
function getPosition(anchor, floating, placement, offset) {
|
|
1956
|
+
let x = 0;
|
|
1957
|
+
let y = 0;
|
|
1958
|
+
const base = placement.split("-")[0];
|
|
1959
|
+
const align = placement.split("-")[1];
|
|
1960
|
+
switch (base) {
|
|
1961
|
+
case "top":
|
|
1962
|
+
x = anchor.left + anchor.width / 2 - floating.width / 2;
|
|
1963
|
+
y = anchor.top - floating.height - offset;
|
|
1964
|
+
break;
|
|
1965
|
+
case "bottom":
|
|
1966
|
+
x = anchor.left + anchor.width / 2 - floating.width / 2;
|
|
1967
|
+
y = anchor.bottom + offset;
|
|
1968
|
+
break;
|
|
1969
|
+
case "left":
|
|
1970
|
+
x = anchor.left - floating.width - offset;
|
|
1971
|
+
y = anchor.top + anchor.height / 2 - floating.height / 2;
|
|
1972
|
+
break;
|
|
1973
|
+
case "right":
|
|
1974
|
+
x = anchor.right + offset;
|
|
1975
|
+
y = anchor.top + anchor.height / 2 - floating.height / 2;
|
|
1976
|
+
break;
|
|
1977
|
+
}
|
|
1978
|
+
if (base === "top" || base === "bottom") {
|
|
1979
|
+
if (align === "start") x = anchor.left;
|
|
1980
|
+
else if (align === "end") x = anchor.right - floating.width;
|
|
1981
|
+
}
|
|
1982
|
+
if (base === "left" || base === "right") {
|
|
1983
|
+
if (align === "start") y = anchor.top;
|
|
1984
|
+
else if (align === "end") y = anchor.bottom - floating.height;
|
|
1985
|
+
}
|
|
1986
|
+
let finalPlacement = placement;
|
|
1987
|
+
const vw = window.innerWidth;
|
|
1988
|
+
const vh = window.innerHeight;
|
|
1989
|
+
if (base === "bottom" && y + floating.height > vh) {
|
|
1990
|
+
y = anchor.top - floating.height - offset;
|
|
1991
|
+
finalPlacement = placement.replace("bottom", "top");
|
|
1992
|
+
} else if (base === "top" && y < 0) {
|
|
1993
|
+
y = anchor.bottom + offset;
|
|
1994
|
+
finalPlacement = placement.replace("top", "bottom");
|
|
1995
|
+
}
|
|
1996
|
+
x = Math.max(4, Math.min(x, vw - floating.width - 4));
|
|
1997
|
+
y = Math.max(4, Math.min(y, vh - floating.height - 4));
|
|
1998
|
+
return { x, y, placement: finalPlacement };
|
|
1999
|
+
}
|
|
2000
|
+
function useFloatingPosition(anchorRef, floatingRef, options = {}) {
|
|
2001
|
+
const { placement = "bottom", offset = 8, enabled = true } = options;
|
|
2002
|
+
const [position, setPosition] = react.useState({
|
|
2003
|
+
x: -9999,
|
|
2004
|
+
y: -9999,
|
|
2005
|
+
placement
|
|
2006
|
+
});
|
|
2007
|
+
const update = react.useCallback(() => {
|
|
2008
|
+
const anchor = anchorRef.current;
|
|
2009
|
+
const floating = floatingRef.current;
|
|
2010
|
+
if (!anchor || !floating) return;
|
|
2011
|
+
const anchorRect = anchor.getBoundingClientRect();
|
|
2012
|
+
const floatingRect = floating.getBoundingClientRect();
|
|
2013
|
+
setPosition(getPosition(anchorRect, floatingRect, placement, offset));
|
|
2014
|
+
}, [anchorRef, floatingRef, placement, offset]);
|
|
2015
|
+
react.useLayoutEffect(() => {
|
|
2016
|
+
if (!enabled) return;
|
|
2017
|
+
update();
|
|
2018
|
+
const raf = requestAnimationFrame(() => {
|
|
2019
|
+
update();
|
|
2020
|
+
});
|
|
2021
|
+
return () => cancelAnimationFrame(raf);
|
|
2022
|
+
}, [update, enabled]);
|
|
2023
|
+
react.useEffect(() => {
|
|
2024
|
+
if (!enabled) return;
|
|
2025
|
+
window.addEventListener("scroll", update, true);
|
|
2026
|
+
window.addEventListener("resize", update);
|
|
2027
|
+
return () => {
|
|
2028
|
+
window.removeEventListener("scroll", update, true);
|
|
2029
|
+
window.removeEventListener("resize", update);
|
|
2030
|
+
};
|
|
2031
|
+
}, [update, enabled]);
|
|
2032
|
+
return position;
|
|
2033
|
+
}
|
|
2034
|
+
function useOutsideClick(ref, handler, enabled = true, ignoreRef) {
|
|
2035
|
+
react.useEffect(() => {
|
|
2036
|
+
if (!enabled) return;
|
|
2037
|
+
const listener = (event) => {
|
|
2038
|
+
const el = ref.current;
|
|
2039
|
+
if (!el || el.contains(event.target)) return;
|
|
2040
|
+
if (ignoreRef?.current?.contains(event.target)) return;
|
|
2041
|
+
handler(event);
|
|
2042
|
+
};
|
|
2043
|
+
document.addEventListener("mousedown", listener);
|
|
2044
|
+
document.addEventListener("touchstart", listener);
|
|
2045
|
+
return () => {
|
|
2046
|
+
document.removeEventListener("mousedown", listener);
|
|
2047
|
+
document.removeEventListener("touchstart", listener);
|
|
2048
|
+
};
|
|
2049
|
+
}, [ref, handler, enabled, ignoreRef]);
|
|
2050
|
+
}
|
|
2051
|
+
function useEscapeKey(handler, enabled = true) {
|
|
2052
|
+
react.useEffect(() => {
|
|
2053
|
+
if (!enabled) return;
|
|
2054
|
+
const listener = (event) => {
|
|
2055
|
+
if (event.key === "Escape") {
|
|
2056
|
+
handler();
|
|
2057
|
+
}
|
|
2058
|
+
};
|
|
2059
|
+
document.addEventListener("keydown", listener);
|
|
2060
|
+
return () => document.removeEventListener("keydown", listener);
|
|
2061
|
+
}, [handler, enabled]);
|
|
2062
|
+
}
|
|
1943
2063
|
function isOptionGroup(item) {
|
|
1944
2064
|
return typeof item === "object" && "options" in item;
|
|
1945
2065
|
}
|
|
1946
|
-
function
|
|
2066
|
+
function flattenOptions(list) {
|
|
2067
|
+
const flat = [];
|
|
2068
|
+
for (const item of list) {
|
|
2069
|
+
if (isOptionGroup(item)) {
|
|
2070
|
+
flat.push(...item.options);
|
|
2071
|
+
} else {
|
|
2072
|
+
flat.push(item);
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
return flat;
|
|
2076
|
+
}
|
|
2077
|
+
function renderNativeOption(option, index) {
|
|
1947
2078
|
const resolved = resolveOption(option);
|
|
1948
2079
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1949
2080
|
"option",
|
|
@@ -1955,7 +2086,7 @@ function renderOption(option, index) {
|
|
|
1955
2086
|
`${resolved.value}-${index}`
|
|
1956
2087
|
);
|
|
1957
2088
|
}
|
|
1958
|
-
var
|
|
2089
|
+
var NativeSelect = react.forwardRef(
|
|
1959
2090
|
({
|
|
1960
2091
|
size = "md",
|
|
1961
2092
|
dirty,
|
|
@@ -2013,8 +2144,8 @@ var Select = react.forwardRef(
|
|
|
2013
2144
|
placeholder && /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: placeholder }),
|
|
2014
2145
|
list.map(
|
|
2015
2146
|
(item, index) => isOptionGroup(item) ? /* @__PURE__ */ jsxRuntime.jsx("optgroup", { label: item.label, children: item.options.map(
|
|
2016
|
-
(opt, optIndex) =>
|
|
2017
|
-
) }, `group-${index}`) :
|
|
2147
|
+
(opt, optIndex) => renderNativeOption(opt, optIndex)
|
|
2148
|
+
) }, `group-${index}`) : renderNativeOption(item, index)
|
|
2018
2149
|
)
|
|
2019
2150
|
]
|
|
2020
2151
|
}
|
|
@@ -2038,6 +2169,270 @@ var Select = react.forwardRef(
|
|
|
2038
2169
|
return select;
|
|
2039
2170
|
}
|
|
2040
2171
|
);
|
|
2172
|
+
NativeSelect.displayName = "NativeSelect";
|
|
2173
|
+
var ListboxSelect = react.forwardRef(
|
|
2174
|
+
({
|
|
2175
|
+
size = "md",
|
|
2176
|
+
dirty,
|
|
2177
|
+
error,
|
|
2178
|
+
label,
|
|
2179
|
+
description,
|
|
2180
|
+
required,
|
|
2181
|
+
disabled,
|
|
2182
|
+
className,
|
|
2183
|
+
id,
|
|
2184
|
+
list,
|
|
2185
|
+
placeholder = "Select...",
|
|
2186
|
+
multiple = false,
|
|
2187
|
+
values: controlledValues,
|
|
2188
|
+
defaultValues,
|
|
2189
|
+
onValueChange,
|
|
2190
|
+
onValuesChange,
|
|
2191
|
+
searchable = false,
|
|
2192
|
+
selectedSuffix = "selected",
|
|
2193
|
+
indicator = "check",
|
|
2194
|
+
value: controlledSingleValue,
|
|
2195
|
+
defaultValue: defaultSingleValue
|
|
2196
|
+
}, _ref) => {
|
|
2197
|
+
const autoId = react.useId();
|
|
2198
|
+
const selectId = id ?? autoId;
|
|
2199
|
+
const [open, setOpen] = react.useState(false);
|
|
2200
|
+
const [search2, setSearch] = react.useState("");
|
|
2201
|
+
const [activeIndex, setActiveIndex] = react.useState(-1);
|
|
2202
|
+
const [singleValue, setSingleValue] = react.useState(
|
|
2203
|
+
controlledSingleValue ?? defaultSingleValue ?? ""
|
|
2204
|
+
);
|
|
2205
|
+
const currentSingle = controlledSingleValue ?? singleValue;
|
|
2206
|
+
const [multiValues, setMultiValues] = react.useState(
|
|
2207
|
+
controlledValues ?? defaultValues ?? []
|
|
2208
|
+
);
|
|
2209
|
+
const currentMulti = controlledValues ?? multiValues;
|
|
2210
|
+
react.useEffect(() => {
|
|
2211
|
+
if (controlledValues) setMultiValues(controlledValues);
|
|
2212
|
+
}, [controlledValues]);
|
|
2213
|
+
react.useEffect(() => {
|
|
2214
|
+
if (controlledSingleValue !== void 0) setSingleValue(controlledSingleValue);
|
|
2215
|
+
}, [controlledSingleValue]);
|
|
2216
|
+
const anchorRef = react.useRef(null);
|
|
2217
|
+
const listRef = react.useRef(null);
|
|
2218
|
+
const wrapperRef = react.useRef(null);
|
|
2219
|
+
const searchRef = react.useRef(null);
|
|
2220
|
+
const position = useFloatingPosition(anchorRef, listRef, {
|
|
2221
|
+
placement: "bottom-start",
|
|
2222
|
+
offset: 4,
|
|
2223
|
+
enabled: open
|
|
2224
|
+
});
|
|
2225
|
+
const close = react.useCallback(() => {
|
|
2226
|
+
setOpen(false);
|
|
2227
|
+
setSearch("");
|
|
2228
|
+
setActiveIndex(-1);
|
|
2229
|
+
}, []);
|
|
2230
|
+
useOutsideClick(wrapperRef, close, open);
|
|
2231
|
+
useEscapeKey(close, open);
|
|
2232
|
+
react.useEffect(() => {
|
|
2233
|
+
if (open && searchable) {
|
|
2234
|
+
requestAnimationFrame(() => searchRef.current?.focus());
|
|
2235
|
+
}
|
|
2236
|
+
}, [open, searchable]);
|
|
2237
|
+
const allOptions = flattenOptions(list);
|
|
2238
|
+
const resolvedOptions = allOptions.map(resolveOption);
|
|
2239
|
+
const filtered = search2 ? resolvedOptions.filter(
|
|
2240
|
+
(o) => o.label.toLowerCase().includes(search2.toLowerCase())
|
|
2241
|
+
) : resolvedOptions;
|
|
2242
|
+
const isSelected = (value) => {
|
|
2243
|
+
if (multiple) return currentMulti.includes(value);
|
|
2244
|
+
return currentSingle === value;
|
|
2245
|
+
};
|
|
2246
|
+
const toggleOption = react.useCallback(
|
|
2247
|
+
(value) => {
|
|
2248
|
+
if (multiple) {
|
|
2249
|
+
const next = currentMulti.includes(value) ? currentMulti.filter((v) => v !== value) : [...currentMulti, value];
|
|
2250
|
+
setMultiValues(next);
|
|
2251
|
+
onValuesChange?.(next);
|
|
2252
|
+
} else {
|
|
2253
|
+
setSingleValue(value);
|
|
2254
|
+
onValueChange?.(value);
|
|
2255
|
+
close();
|
|
2256
|
+
}
|
|
2257
|
+
},
|
|
2258
|
+
[multiple, currentMulti, onValuesChange, onValueChange, close]
|
|
2259
|
+
);
|
|
2260
|
+
const getDisplayText = () => {
|
|
2261
|
+
if (multiple) {
|
|
2262
|
+
if (currentMulti.length === 0) return placeholder;
|
|
2263
|
+
if (currentMulti.length === 1) {
|
|
2264
|
+
const opt2 = resolvedOptions.find((o) => o.value === currentMulti[0]);
|
|
2265
|
+
return opt2?.label ?? currentMulti[0];
|
|
2266
|
+
}
|
|
2267
|
+
return `${currentMulti.length} ${selectedSuffix}`;
|
|
2268
|
+
}
|
|
2269
|
+
if (!currentSingle) return placeholder;
|
|
2270
|
+
const opt = resolvedOptions.find((o) => o.value === currentSingle);
|
|
2271
|
+
return opt?.label ?? currentSingle;
|
|
2272
|
+
};
|
|
2273
|
+
const hasValue = multiple ? currentMulti.length > 0 : !!currentSingle;
|
|
2274
|
+
const handleKeyDown = (e) => {
|
|
2275
|
+
if (!open) {
|
|
2276
|
+
if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
|
|
2277
|
+
e.preventDefault();
|
|
2278
|
+
setOpen(true);
|
|
2279
|
+
}
|
|
2280
|
+
return;
|
|
2281
|
+
}
|
|
2282
|
+
if (e.key === "ArrowDown") {
|
|
2283
|
+
e.preventDefault();
|
|
2284
|
+
setActiveIndex((i) => Math.min(i + 1, filtered.length - 1));
|
|
2285
|
+
} else if (e.key === "ArrowUp") {
|
|
2286
|
+
e.preventDefault();
|
|
2287
|
+
setActiveIndex((i) => Math.max(i - 1, 0));
|
|
2288
|
+
} else if (e.key === "Enter" && activeIndex >= 0) {
|
|
2289
|
+
e.preventDefault();
|
|
2290
|
+
const item = filtered[activeIndex];
|
|
2291
|
+
if (item && !item.disabled) toggleOption(item.value);
|
|
2292
|
+
}
|
|
2293
|
+
};
|
|
2294
|
+
const trigger = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2295
|
+
"button",
|
|
2296
|
+
{
|
|
2297
|
+
ref: anchorRef,
|
|
2298
|
+
type: "button",
|
|
2299
|
+
id: selectId,
|
|
2300
|
+
disabled,
|
|
2301
|
+
onClick: () => setOpen((o) => !o),
|
|
2302
|
+
onKeyDown: handleKeyDown,
|
|
2303
|
+
role: "combobox",
|
|
2304
|
+
"aria-expanded": open,
|
|
2305
|
+
"aria-haspopup": "listbox",
|
|
2306
|
+
"data-react-fancy-select": "",
|
|
2307
|
+
"data-variant": "listbox",
|
|
2308
|
+
className: cn(
|
|
2309
|
+
inputBaseClasses,
|
|
2310
|
+
inputSizeClasses[size],
|
|
2311
|
+
dirtyClasses(dirty),
|
|
2312
|
+
errorClasses(error),
|
|
2313
|
+
"flex w-full cursor-pointer items-center justify-between gap-2 text-left",
|
|
2314
|
+
!hasValue && "text-zinc-400 dark:text-zinc-500",
|
|
2315
|
+
className
|
|
2316
|
+
),
|
|
2317
|
+
children: [
|
|
2318
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: getDisplayText() }),
|
|
2319
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2320
|
+
"svg",
|
|
2321
|
+
{
|
|
2322
|
+
className: cn("h-4 w-4 shrink-0 text-zinc-400 transition-transform", open && "rotate-180"),
|
|
2323
|
+
viewBox: "0 0 20 20",
|
|
2324
|
+
fill: "currentColor",
|
|
2325
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2326
|
+
"path",
|
|
2327
|
+
{
|
|
2328
|
+
fillRule: "evenodd",
|
|
2329
|
+
d: "M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z",
|
|
2330
|
+
clipRule: "evenodd"
|
|
2331
|
+
}
|
|
2332
|
+
)
|
|
2333
|
+
}
|
|
2334
|
+
)
|
|
2335
|
+
]
|
|
2336
|
+
}
|
|
2337
|
+
);
|
|
2338
|
+
const dropdown = open && /* @__PURE__ */ jsxRuntime.jsx(Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2339
|
+
"div",
|
|
2340
|
+
{
|
|
2341
|
+
ref: listRef,
|
|
2342
|
+
role: "listbox",
|
|
2343
|
+
"aria-multiselectable": multiple || void 0,
|
|
2344
|
+
className: "fixed z-50 max-h-60 min-w-[8rem] overflow-y-auto rounded-xl border border-zinc-200 bg-white p-1 shadow-lg dark:border-zinc-700 dark:bg-zinc-900 dark:shadow-zinc-950/50 fancy-scale-in",
|
|
2345
|
+
style: {
|
|
2346
|
+
left: position.x,
|
|
2347
|
+
top: position.y,
|
|
2348
|
+
width: anchorRef.current?.offsetWidth
|
|
2349
|
+
},
|
|
2350
|
+
children: [
|
|
2351
|
+
searchable && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 pb-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2352
|
+
"input",
|
|
2353
|
+
{
|
|
2354
|
+
ref: searchRef,
|
|
2355
|
+
type: "text",
|
|
2356
|
+
value: search2,
|
|
2357
|
+
onChange: (e) => {
|
|
2358
|
+
setSearch(e.target.value);
|
|
2359
|
+
setActiveIndex(-1);
|
|
2360
|
+
},
|
|
2361
|
+
onKeyDown: handleKeyDown,
|
|
2362
|
+
placeholder: "Search...",
|
|
2363
|
+
className: "w-full rounded-md border-0 bg-zinc-100 px-2.5 py-1.5 text-sm text-zinc-900 placeholder:text-zinc-400 outline-none dark:bg-zinc-800 dark:text-zinc-100 dark:placeholder:text-zinc-500"
|
|
2364
|
+
}
|
|
2365
|
+
) }),
|
|
2366
|
+
filtered.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2 text-sm text-zinc-400", children: "No results found" }) : filtered.map((option, i) => {
|
|
2367
|
+
const selected = isSelected(option.value);
|
|
2368
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2369
|
+
"button",
|
|
2370
|
+
{
|
|
2371
|
+
type: "button",
|
|
2372
|
+
role: "option",
|
|
2373
|
+
"aria-selected": selected,
|
|
2374
|
+
disabled: option.disabled,
|
|
2375
|
+
onClick: () => toggleOption(option.value),
|
|
2376
|
+
className: cn(
|
|
2377
|
+
"flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-sm transition-colors",
|
|
2378
|
+
i === activeIndex ? "bg-zinc-100 dark:bg-zinc-800" : "hover:bg-zinc-50 dark:hover:bg-zinc-800/50",
|
|
2379
|
+
selected ? "text-zinc-900 dark:text-zinc-100" : "text-zinc-700 dark:text-zinc-300",
|
|
2380
|
+
option.disabled && "cursor-not-allowed opacity-50"
|
|
2381
|
+
),
|
|
2382
|
+
children: [
|
|
2383
|
+
indicator === "checkbox" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2384
|
+
"span",
|
|
2385
|
+
{
|
|
2386
|
+
className: cn(
|
|
2387
|
+
"flex h-4 w-4 shrink-0 items-center justify-center rounded border transition-colors",
|
|
2388
|
+
selected ? "border-blue-500 bg-blue-500 text-white dark:border-blue-400 dark:bg-blue-400" : "border-zinc-300 dark:border-zinc-600"
|
|
2389
|
+
),
|
|
2390
|
+
children: selected && /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "h-3 w-3", viewBox: "0 0 12 12", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "2.5 6 5 8.5 9.5 3.5" }) })
|
|
2391
|
+
}
|
|
2392
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-4 w-4 shrink-0 items-center justify-center", children: selected && /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "h-4 w-4 text-blue-500 dark:text-blue-400", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z", clipRule: "evenodd" }) }) }),
|
|
2393
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
2394
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "block truncate", children: option.label }),
|
|
2395
|
+
option.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block truncate text-xs text-zinc-400 dark:text-zinc-500", children: option.description })
|
|
2396
|
+
] })
|
|
2397
|
+
]
|
|
2398
|
+
},
|
|
2399
|
+
option.value
|
|
2400
|
+
);
|
|
2401
|
+
})
|
|
2402
|
+
]
|
|
2403
|
+
}
|
|
2404
|
+
) });
|
|
2405
|
+
const content = /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: wrapperRef, className: "relative", children: [
|
|
2406
|
+
trigger,
|
|
2407
|
+
dropdown
|
|
2408
|
+
] });
|
|
2409
|
+
if (label || error || description) {
|
|
2410
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2411
|
+
Field,
|
|
2412
|
+
{
|
|
2413
|
+
label,
|
|
2414
|
+
description,
|
|
2415
|
+
error,
|
|
2416
|
+
required,
|
|
2417
|
+
htmlFor: selectId,
|
|
2418
|
+
size,
|
|
2419
|
+
children: content
|
|
2420
|
+
}
|
|
2421
|
+
);
|
|
2422
|
+
}
|
|
2423
|
+
return content;
|
|
2424
|
+
}
|
|
2425
|
+
);
|
|
2426
|
+
ListboxSelect.displayName = "ListboxSelect";
|
|
2427
|
+
var Select = react.forwardRef(
|
|
2428
|
+
(props, ref) => {
|
|
2429
|
+
const variant = props.variant ?? (props.multiple ? "listbox" : "native");
|
|
2430
|
+
if (variant === "listbox") {
|
|
2431
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ListboxSelect, { ...props, ref });
|
|
2432
|
+
}
|
|
2433
|
+
return /* @__PURE__ */ jsxRuntime.jsx(NativeSelect, { ...props, ref });
|
|
2434
|
+
}
|
|
2435
|
+
);
|
|
2041
2436
|
Select.displayName = "Select";
|
|
2042
2437
|
function useControllableState(controlledValue, defaultValue, onChange) {
|
|
2043
2438
|
const [uncontrolledValue, setUncontrolledValue] = react.useState(defaultValue);
|
|
@@ -2116,7 +2511,7 @@ var Checkbox = react.forwardRef(
|
|
|
2116
2511
|
onChange: (e) => setChecked(e.target.checked),
|
|
2117
2512
|
className: cn(
|
|
2118
2513
|
sizeClasses6,
|
|
2119
|
-
"cursor-pointer rounded border border-zinc-300 bg-white text-blue-600 focus:ring-2 focus:ring-blue-500/40 focus:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50 dark:border-zinc-
|
|
2514
|
+
"cursor-pointer rounded border border-zinc-300 bg-white text-blue-600 transition-[border-color,box-shadow] duration-150 focus:ring-2 focus:ring-blue-500/40 focus:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50 dark:border-zinc-700 dark:bg-[#1e1e24]",
|
|
2120
2515
|
dirtyRingClasses(dirty),
|
|
2121
2516
|
error && "border-red-500"
|
|
2122
2517
|
)
|
|
@@ -2128,7 +2523,7 @@ var Checkbox = react.forwardRef(
|
|
|
2128
2523
|
{
|
|
2129
2524
|
htmlFor: checkboxId,
|
|
2130
2525
|
className: cn(
|
|
2131
|
-
"cursor-pointer text-sm text-zinc-700 dark:text-zinc-
|
|
2526
|
+
"cursor-pointer text-sm text-zinc-700 dark:text-zinc-100",
|
|
2132
2527
|
disabled && "cursor-not-allowed opacity-50"
|
|
2133
2528
|
),
|
|
2134
2529
|
children: [
|
|
@@ -2203,7 +2598,7 @@ function CheckboxGroup({
|
|
|
2203
2598
|
onChange: () => handleToggle(resolved.value),
|
|
2204
2599
|
className: cn(
|
|
2205
2600
|
sizeClasses6,
|
|
2206
|
-
"cursor-pointer rounded border border-zinc-300 bg-white text-blue-600 focus:ring-2 focus:ring-blue-500/40 focus:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50 dark:border-zinc-
|
|
2601
|
+
"cursor-pointer rounded border border-zinc-300 bg-white text-blue-600 transition-[border-color,box-shadow] duration-150 focus:ring-2 focus:ring-blue-500/40 focus:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50 dark:border-zinc-700 dark:bg-[#1e1e24]",
|
|
2207
2602
|
dirtyRingClasses(dirty),
|
|
2208
2603
|
error && "border-red-500"
|
|
2209
2604
|
)
|
|
@@ -2215,7 +2610,7 @@ function CheckboxGroup({
|
|
|
2215
2610
|
{
|
|
2216
2611
|
htmlFor: optionId,
|
|
2217
2612
|
className: cn(
|
|
2218
|
-
"cursor-pointer text-sm text-zinc-700 dark:text-zinc-
|
|
2613
|
+
"cursor-pointer text-sm text-zinc-700 dark:text-zinc-100",
|
|
2219
2614
|
(disabled || resolved.disabled) && "cursor-not-allowed opacity-50"
|
|
2220
2615
|
),
|
|
2221
2616
|
children: resolved.label
|
|
@@ -2300,7 +2695,7 @@ function RadioGroup({
|
|
|
2300
2695
|
onChange: () => setValue(resolved.value),
|
|
2301
2696
|
className: cn(
|
|
2302
2697
|
sizeClasses6,
|
|
2303
|
-
"cursor-pointer border border-zinc-300 bg-white text-blue-600 focus:ring-2 focus:ring-blue-500/40 focus:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50 dark:border-zinc-
|
|
2698
|
+
"cursor-pointer border border-zinc-300 bg-white text-blue-600 transition-[border-color,box-shadow] duration-150 focus:ring-2 focus:ring-blue-500/40 focus:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50 dark:border-zinc-700 dark:bg-[#1e1e24]",
|
|
2304
2699
|
dirtyRingClasses(dirty),
|
|
2305
2700
|
error && "border-red-500"
|
|
2306
2701
|
)
|
|
@@ -2312,7 +2707,7 @@ function RadioGroup({
|
|
|
2312
2707
|
{
|
|
2313
2708
|
htmlFor: optionId,
|
|
2314
2709
|
className: cn(
|
|
2315
|
-
"cursor-pointer text-sm text-zinc-700 dark:text-zinc-
|
|
2710
|
+
"cursor-pointer text-sm text-zinc-700 dark:text-zinc-100",
|
|
2316
2711
|
(disabled || resolved.disabled) && "cursor-not-allowed opacity-50"
|
|
2317
2712
|
),
|
|
2318
2713
|
children: resolved.label
|
|
@@ -2419,7 +2814,7 @@ var Switch = react.forwardRef(
|
|
|
2419
2814
|
className: cn(
|
|
2420
2815
|
"relative inline-flex shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/40 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
2421
2816
|
trackSizes,
|
|
2422
|
-
checked ? trackColorMap[color] : "bg-zinc-200 dark:bg-zinc-
|
|
2817
|
+
checked ? trackColorMap[color] : "bg-zinc-200 dark:bg-zinc-600",
|
|
2423
2818
|
dirtyRingClasses(dirty),
|
|
2424
2819
|
error && "ring-2 ring-red-500/50"
|
|
2425
2820
|
),
|
|
@@ -2442,7 +2837,7 @@ var Switch = react.forwardRef(
|
|
|
2442
2837
|
{
|
|
2443
2838
|
htmlFor: switchId,
|
|
2444
2839
|
className: cn(
|
|
2445
|
-
"cursor-pointer text-sm text-zinc-700 dark:text-zinc-
|
|
2840
|
+
"cursor-pointer text-sm text-zinc-700 dark:text-zinc-100",
|
|
2446
2841
|
disabled && "cursor-not-allowed opacity-50"
|
|
2447
2842
|
),
|
|
2448
2843
|
children: [
|
|
@@ -2744,7 +3139,7 @@ function MultiSwitch({
|
|
|
2744
3139
|
role: "radiogroup",
|
|
2745
3140
|
id,
|
|
2746
3141
|
className: cn(
|
|
2747
|
-
"relative inline-flex rounded-lg border border-zinc-300 bg-zinc-100 dark:border-zinc-
|
|
3142
|
+
"relative inline-flex rounded-lg border border-zinc-300 bg-zinc-100 dark:border-zinc-700 dark:bg-zinc-800",
|
|
2748
3143
|
dirty && "ring-2 ring-amber-400/50",
|
|
2749
3144
|
error && "ring-2 ring-red-500/50",
|
|
2750
3145
|
disabled && "opacity-50 cursor-not-allowed",
|
|
@@ -3438,7 +3833,7 @@ function EmojiSelect({
|
|
|
3438
3833
|
"button",
|
|
3439
3834
|
{
|
|
3440
3835
|
type: "button",
|
|
3441
|
-
className: "flex items-center gap-2 rounded-lg border border-zinc-300 px-3 py-2 text-sm dark:border-zinc-
|
|
3836
|
+
className: "flex items-center gap-2 rounded-lg border border-zinc-300 px-3 py-2 text-sm transition-[border-color,box-shadow] duration-150 dark:border-zinc-700 dark:bg-[#1e1e24]",
|
|
3442
3837
|
onClick: () => setOpen(!open),
|
|
3443
3838
|
children: selected ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xl", children: selected }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-zinc-400", children: "Pick emoji" })
|
|
3444
3839
|
}
|
|
@@ -3451,7 +3846,7 @@ function EmojiSelect({
|
|
|
3451
3846
|
value: query,
|
|
3452
3847
|
onChange: (e) => setQuery(e.target.value),
|
|
3453
3848
|
placeholder,
|
|
3454
|
-
className: "mb-2 w-full rounded-md border border-zinc-200 px-2 py-1 text-sm dark:border-zinc-
|
|
3849
|
+
className: "mb-2 w-full rounded-md border border-zinc-200 px-2 py-1 text-sm transition-[border-color,box-shadow] duration-150 dark:border-zinc-700 dark:bg-[#1e1e24] dark:text-zinc-100",
|
|
3455
3850
|
autoFocus: true
|
|
3456
3851
|
}
|
|
3457
3852
|
),
|
|
@@ -3706,34 +4101,6 @@ var Table = Object.assign(TableRoot, {
|
|
|
3706
4101
|
Tray: TableTray,
|
|
3707
4102
|
RowTray: TableRowTray
|
|
3708
4103
|
});
|
|
3709
|
-
function Portal({ children, container }) {
|
|
3710
|
-
if (typeof document === "undefined") return null;
|
|
3711
|
-
const target = container ?? document.body;
|
|
3712
|
-
return reactDom.createPortal(
|
|
3713
|
-
/* @__PURE__ */ jsxRuntime.jsx(PortalDarkWrapper, { children }),
|
|
3714
|
-
target
|
|
3715
|
-
);
|
|
3716
|
-
}
|
|
3717
|
-
function PortalDarkWrapper({ children }) {
|
|
3718
|
-
const ref = react.useRef(null);
|
|
3719
|
-
react.useEffect(() => {
|
|
3720
|
-
const root = document.documentElement;
|
|
3721
|
-
const wrapper = ref.current;
|
|
3722
|
-
if (!wrapper) return;
|
|
3723
|
-
const sync = () => {
|
|
3724
|
-
const isDark = root.classList.contains("dark") || root.getAttribute("data-theme") === "dark";
|
|
3725
|
-
wrapper.classList.toggle("dark", isDark);
|
|
3726
|
-
};
|
|
3727
|
-
sync();
|
|
3728
|
-
const observer = new MutationObserver(sync);
|
|
3729
|
-
observer.observe(root, {
|
|
3730
|
-
attributes: true,
|
|
3731
|
-
attributeFilter: ["class", "data-theme"]
|
|
3732
|
-
});
|
|
3733
|
-
return () => observer.disconnect();
|
|
3734
|
-
}, []);
|
|
3735
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, "data-react-fancy-portal": "", style: { display: "contents" }, children });
|
|
3736
|
-
}
|
|
3737
4104
|
var sizeClasses3 = {
|
|
3738
4105
|
xs: "text-xs",
|
|
3739
4106
|
sm: "text-sm",
|
|
@@ -4511,42 +4878,66 @@ var Callout = react.forwardRef(
|
|
|
4511
4878
|
);
|
|
4512
4879
|
Callout.displayName = "Callout";
|
|
4513
4880
|
var TimelineContext = react.createContext({
|
|
4514
|
-
|
|
4515
|
-
index: 0
|
|
4881
|
+
variant: "stacked",
|
|
4882
|
+
index: 0,
|
|
4883
|
+
total: 0,
|
|
4884
|
+
animated: true
|
|
4516
4885
|
});
|
|
4517
4886
|
function useTimeline() {
|
|
4518
4887
|
return react.useContext(TimelineContext);
|
|
4519
4888
|
}
|
|
4520
4889
|
var dotColorClasses2 = {
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
amber: "bg-amber-500
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4890
|
+
red: "bg-red-500",
|
|
4891
|
+
orange: "bg-orange-500",
|
|
4892
|
+
amber: "bg-amber-500",
|
|
4893
|
+
yellow: "bg-yellow-500",
|
|
4894
|
+
lime: "bg-lime-500",
|
|
4895
|
+
green: "bg-green-500",
|
|
4896
|
+
emerald: "bg-emerald-500",
|
|
4897
|
+
teal: "bg-teal-500",
|
|
4898
|
+
cyan: "bg-cyan-500",
|
|
4899
|
+
sky: "bg-sky-500",
|
|
4900
|
+
blue: "bg-blue-500",
|
|
4901
|
+
indigo: "bg-indigo-500",
|
|
4902
|
+
violet: "bg-violet-500",
|
|
4903
|
+
purple: "bg-purple-500",
|
|
4904
|
+
fuchsia: "bg-fuchsia-500",
|
|
4905
|
+
pink: "bg-pink-500",
|
|
4906
|
+
rose: "bg-rose-500",
|
|
4907
|
+
zinc: "bg-zinc-300 dark:bg-zinc-600"
|
|
4533
4908
|
};
|
|
4534
4909
|
var ringColorClasses = {
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
amber: "ring-amber-500/30
|
|
4538
|
-
|
|
4910
|
+
red: "ring-red-500/30",
|
|
4911
|
+
orange: "ring-orange-500/30",
|
|
4912
|
+
amber: "ring-amber-500/30",
|
|
4913
|
+
yellow: "ring-yellow-500/30",
|
|
4914
|
+
lime: "ring-lime-500/30",
|
|
4915
|
+
green: "ring-green-500/30",
|
|
4916
|
+
emerald: "ring-emerald-500/30",
|
|
4917
|
+
teal: "ring-teal-500/30",
|
|
4918
|
+
cyan: "ring-cyan-500/30",
|
|
4919
|
+
sky: "ring-sky-500/30",
|
|
4920
|
+
blue: "ring-blue-500/30",
|
|
4921
|
+
indigo: "ring-indigo-500/30",
|
|
4922
|
+
violet: "ring-violet-500/30",
|
|
4923
|
+
purple: "ring-purple-500/30",
|
|
4924
|
+
fuchsia: "ring-fuchsia-500/30",
|
|
4925
|
+
pink: "ring-pink-500/30",
|
|
4926
|
+
rose: "ring-rose-500/30",
|
|
4539
4927
|
zinc: "ring-zinc-400/30 dark:ring-zinc-500/30"
|
|
4540
4928
|
};
|
|
4541
|
-
function Dot({ icon, color, active }) {
|
|
4929
|
+
function Dot({ icon, emoji, color, active }) {
|
|
4542
4930
|
const c = color ?? "zinc";
|
|
4931
|
+
if (emoji) {
|
|
4932
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full border border-zinc-200 bg-zinc-100 dark:border-zinc-700 dark:bg-zinc-800", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: emoji }) });
|
|
4933
|
+
}
|
|
4543
4934
|
if (icon) {
|
|
4544
4935
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4545
4936
|
"span",
|
|
4546
4937
|
{
|
|
4547
4938
|
className: cn(
|
|
4548
|
-
"flex h-
|
|
4549
|
-
|
|
4939
|
+
"flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-white",
|
|
4940
|
+
dotColorClasses2[c],
|
|
4550
4941
|
active && "ring-4",
|
|
4551
4942
|
active && ringColorClasses[c]
|
|
4552
4943
|
),
|
|
@@ -4558,7 +4949,7 @@ function Dot({ icon, color, active }) {
|
|
|
4558
4949
|
"span",
|
|
4559
4950
|
{
|
|
4560
4951
|
className: cn(
|
|
4561
|
-
"h-3 w-3 rounded-full",
|
|
4952
|
+
"h-3 w-3 shrink-0 rounded-full",
|
|
4562
4953
|
dotColorClasses2[c],
|
|
4563
4954
|
active && "ring-4",
|
|
4564
4955
|
active && ringColorClasses[c]
|
|
@@ -4566,32 +4957,83 @@ function Dot({ icon, color, active }) {
|
|
|
4566
4957
|
}
|
|
4567
4958
|
);
|
|
4568
4959
|
}
|
|
4960
|
+
function useIntersectionReveal(animated) {
|
|
4961
|
+
const ref = react.useRef(null);
|
|
4962
|
+
const [visible, setVisible] = react.useState(!animated);
|
|
4963
|
+
react.useEffect(() => {
|
|
4964
|
+
if (!animated || !ref.current) return;
|
|
4965
|
+
const el = ref.current;
|
|
4966
|
+
const observer = new IntersectionObserver(
|
|
4967
|
+
([entry]) => {
|
|
4968
|
+
if (entry.isIntersecting) {
|
|
4969
|
+
setVisible(true);
|
|
4970
|
+
observer.disconnect();
|
|
4971
|
+
}
|
|
4972
|
+
},
|
|
4973
|
+
{ threshold: 0.2 }
|
|
4974
|
+
);
|
|
4975
|
+
observer.observe(el);
|
|
4976
|
+
return () => observer.disconnect();
|
|
4977
|
+
}, [animated]);
|
|
4978
|
+
return { ref, visible };
|
|
4979
|
+
}
|
|
4569
4980
|
var TimelineItem = react.forwardRef(
|
|
4570
|
-
({
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
const { orientation, index } = useTimeline();
|
|
4578
|
-
if (orientation === "horizontal") {
|
|
4579
|
-
const isTop = index % 2 === 0;
|
|
4981
|
+
({ children, icon, emoji, date, color = "zinc", active = false, className }, _ref) => {
|
|
4982
|
+
const { variant, index, total, animated } = useTimeline();
|
|
4983
|
+
const { ref, visible } = useIntersectionReveal(animated);
|
|
4984
|
+
const isLast = index === total - 1;
|
|
4985
|
+
const isLargeDot = !!icon || !!emoji;
|
|
4986
|
+
const isEven = index % 2 === 0;
|
|
4987
|
+
if (variant === "horizontal") {
|
|
4580
4988
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4581
4989
|
"div",
|
|
4582
4990
|
{
|
|
4583
4991
|
ref,
|
|
4584
4992
|
"data-react-fancy-timeline-item": "",
|
|
4585
|
-
className: cn(
|
|
4586
|
-
|
|
4993
|
+
className: cn(
|
|
4994
|
+
"flex flex-col items-center",
|
|
4995
|
+
!isLast && "min-w-40",
|
|
4996
|
+
animated && "transition duration-500 ease-out",
|
|
4997
|
+
animated && (visible ? "translate-y-0 opacity-100" : "translate-y-4 opacity-0"),
|
|
4998
|
+
className
|
|
4999
|
+
),
|
|
4587
5000
|
children: [
|
|
4588
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4589
|
-
|
|
4590
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4591
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
4592
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-px flex-1 bg-zinc-200 dark:bg-zinc-700" })
|
|
5001
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-8 w-full items-center", children: [
|
|
5002
|
+
index > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-px flex-1 bg-zinc-200 dark:bg-zinc-700" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1" }),
|
|
5003
|
+
/* @__PURE__ */ jsxRuntime.jsx(Dot, { icon, emoji, color, active }),
|
|
5004
|
+
!isLast ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-px flex-1 bg-zinc-200 dark:bg-zinc-700" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1" })
|
|
4593
5005
|
] }),
|
|
4594
|
-
/* @__PURE__ */ jsxRuntime.
|
|
5006
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 max-w-40 px-2 text-center", children: [
|
|
5007
|
+
date && /* @__PURE__ */ jsxRuntime.jsx("time", { className: "text-xs font-medium uppercase tracking-wide text-zinc-500 dark:text-zinc-400", children: date }),
|
|
5008
|
+
children
|
|
5009
|
+
] })
|
|
5010
|
+
]
|
|
5011
|
+
}
|
|
5012
|
+
);
|
|
5013
|
+
}
|
|
5014
|
+
if (variant === "alternating") {
|
|
5015
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5016
|
+
"div",
|
|
5017
|
+
{
|
|
5018
|
+
ref,
|
|
5019
|
+
"data-react-fancy-timeline-item": "",
|
|
5020
|
+
className: cn(
|
|
5021
|
+
"relative flex gap-x-4 md:grid md:grid-cols-[1fr_1.5rem_1fr] md:gap-x-6",
|
|
5022
|
+
animated && "transition duration-500 ease-out",
|
|
5023
|
+
animated && (visible ? "translate-y-0 opacity-100" : "translate-y-4 opacity-0"),
|
|
5024
|
+
className
|
|
5025
|
+
),
|
|
5026
|
+
children: [
|
|
5027
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative z-10 flex w-8 shrink-0 justify-center md:col-start-2 md:row-start-1 md:w-auto md:justify-center", children: !isLargeDot ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1.5", children: /* @__PURE__ */ jsxRuntime.jsx(Dot, { icon, emoji, color, active }) }) : /* @__PURE__ */ jsxRuntime.jsx(Dot, { icon, emoji, color, active }) }),
|
|
5028
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(
|
|
5029
|
+
"min-w-0 flex-1",
|
|
5030
|
+
!isLast && "pb-8",
|
|
5031
|
+
isLargeDot && "pt-1",
|
|
5032
|
+
isEven ? "md:col-start-1 md:row-start-1 md:text-right" : "md:col-start-3"
|
|
5033
|
+
), children: [
|
|
5034
|
+
date && /* @__PURE__ */ jsxRuntime.jsx("time", { className: "text-xs font-medium uppercase tracking-wide text-zinc-500 dark:text-zinc-400", children: date }),
|
|
5035
|
+
children
|
|
5036
|
+
] })
|
|
4595
5037
|
]
|
|
4596
5038
|
}
|
|
4597
5039
|
);
|
|
@@ -4601,11 +5043,18 @@ var TimelineItem = react.forwardRef(
|
|
|
4601
5043
|
{
|
|
4602
5044
|
ref,
|
|
4603
5045
|
"data-react-fancy-timeline-item": "",
|
|
4604
|
-
className: cn(
|
|
5046
|
+
className: cn(
|
|
5047
|
+
"relative flex gap-x-4",
|
|
5048
|
+
animated && "transition duration-500 ease-out",
|
|
5049
|
+
animated && (visible ? "translate-y-0 opacity-100" : "translate-y-4 opacity-0"),
|
|
5050
|
+
className
|
|
5051
|
+
),
|
|
4605
5052
|
children: [
|
|
4606
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
4607
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4608
|
-
|
|
5053
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative z-10 flex w-8 shrink-0 justify-center", children: !isLargeDot ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1.5", children: /* @__PURE__ */ jsxRuntime.jsx(Dot, { icon, emoji, color, active }) }) : /* @__PURE__ */ jsxRuntime.jsx(Dot, { icon, emoji, color, active }) }),
|
|
5054
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("min-w-0 flex-1", !isLast && "pb-8", isLargeDot && "pt-1"), children: [
|
|
5055
|
+
date && /* @__PURE__ */ jsxRuntime.jsx("time", { className: "text-xs font-medium uppercase tracking-wide text-zinc-500 dark:text-zinc-400", children: date }),
|
|
5056
|
+
children
|
|
5057
|
+
] })
|
|
4609
5058
|
]
|
|
4610
5059
|
}
|
|
4611
5060
|
);
|
|
@@ -4613,8 +5062,8 @@ var TimelineItem = react.forwardRef(
|
|
|
4613
5062
|
);
|
|
4614
5063
|
TimelineItem.displayName = "TimelineItem";
|
|
4615
5064
|
var TimelineBlock = react.forwardRef(
|
|
4616
|
-
({ heading, children, icon, color = "zinc", active = false, className }, ref) => {
|
|
4617
|
-
return /* @__PURE__ */ jsxRuntime.jsx(TimelineItem, { icon, color, active, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5065
|
+
({ heading, children, icon, emoji, color = "zinc", active = false, className }, ref) => {
|
|
5066
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TimelineItem, { icon, emoji, color, active, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4618
5067
|
"div",
|
|
4619
5068
|
{
|
|
4620
5069
|
ref,
|
|
@@ -4624,117 +5073,75 @@ var TimelineBlock = react.forwardRef(
|
|
|
4624
5073
|
active && "ring-2 ring-blue-500/20 dark:ring-blue-400/20",
|
|
4625
5074
|
className
|
|
4626
5075
|
),
|
|
4627
|
-
children: [
|
|
4628
|
-
heading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2 text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: heading }),
|
|
4629
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-zinc-600 dark:text-zinc-400", children })
|
|
4630
|
-
]
|
|
4631
|
-
}
|
|
4632
|
-
) });
|
|
4633
|
-
}
|
|
4634
|
-
);
|
|
4635
|
-
TimelineBlock.displayName = "TimelineBlock";
|
|
4636
|
-
var TimelineRoot = react.forwardRef(
|
|
4637
|
-
({ children, orientation = "vertical", className }, ref) => {
|
|
4638
|
-
const items = react.Children.toArray(children);
|
|
4639
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4640
|
-
"div",
|
|
4641
|
-
{
|
|
4642
|
-
ref,
|
|
4643
|
-
"data-react-fancy-timeline": "",
|
|
4644
|
-
"data-orientation": orientation,
|
|
4645
|
-
className: cn(
|
|
4646
|
-
orientation === "vertical" ? "flex flex-col" : "flex flex-row items-center overflow-x-auto",
|
|
4647
|
-
className
|
|
4648
|
-
),
|
|
4649
|
-
children: items.map((child, i) => /* @__PURE__ */ jsxRuntime.jsx(TimelineContext.Provider, { value: { orientation, index: i }, children: child }, i))
|
|
4650
|
-
}
|
|
4651
|
-
);
|
|
4652
|
-
}
|
|
4653
|
-
);
|
|
4654
|
-
TimelineRoot.displayName = "Timeline";
|
|
4655
|
-
var Timeline = Object.assign(TimelineRoot, {
|
|
4656
|
-
Item: TimelineItem,
|
|
4657
|
-
Block: TimelineBlock
|
|
4658
|
-
});
|
|
4659
|
-
function getPosition(anchor, floating, placement, offset) {
|
|
4660
|
-
let x = 0;
|
|
4661
|
-
let y = 0;
|
|
4662
|
-
const base = placement.split("-")[0];
|
|
4663
|
-
const align = placement.split("-")[1];
|
|
4664
|
-
switch (base) {
|
|
4665
|
-
case "top":
|
|
4666
|
-
x = anchor.left + anchor.width / 2 - floating.width / 2;
|
|
4667
|
-
y = anchor.top - floating.height - offset;
|
|
4668
|
-
break;
|
|
4669
|
-
case "bottom":
|
|
4670
|
-
x = anchor.left + anchor.width / 2 - floating.width / 2;
|
|
4671
|
-
y = anchor.bottom + offset;
|
|
4672
|
-
break;
|
|
4673
|
-
case "left":
|
|
4674
|
-
x = anchor.left - floating.width - offset;
|
|
4675
|
-
y = anchor.top + anchor.height / 2 - floating.height / 2;
|
|
4676
|
-
break;
|
|
4677
|
-
case "right":
|
|
4678
|
-
x = anchor.right + offset;
|
|
4679
|
-
y = anchor.top + anchor.height / 2 - floating.height / 2;
|
|
4680
|
-
break;
|
|
4681
|
-
}
|
|
4682
|
-
if (base === "top" || base === "bottom") {
|
|
4683
|
-
if (align === "start") x = anchor.left;
|
|
4684
|
-
else if (align === "end") x = anchor.right - floating.width;
|
|
4685
|
-
}
|
|
4686
|
-
if (base === "left" || base === "right") {
|
|
4687
|
-
if (align === "start") y = anchor.top;
|
|
4688
|
-
else if (align === "end") y = anchor.bottom - floating.height;
|
|
4689
|
-
}
|
|
4690
|
-
let finalPlacement = placement;
|
|
4691
|
-
const vw = window.innerWidth;
|
|
4692
|
-
const vh = window.innerHeight;
|
|
4693
|
-
if (base === "bottom" && y + floating.height > vh) {
|
|
4694
|
-
y = anchor.top - floating.height - offset;
|
|
4695
|
-
finalPlacement = placement.replace("bottom", "top");
|
|
4696
|
-
} else if (base === "top" && y < 0) {
|
|
4697
|
-
y = anchor.bottom + offset;
|
|
4698
|
-
finalPlacement = placement.replace("top", "bottom");
|
|
5076
|
+
children: [
|
|
5077
|
+
heading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2 text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: heading }),
|
|
5078
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-zinc-600 dark:text-zinc-400", children })
|
|
5079
|
+
]
|
|
5080
|
+
}
|
|
5081
|
+
) });
|
|
4699
5082
|
}
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
const
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
5083
|
+
);
|
|
5084
|
+
TimelineBlock.displayName = "TimelineBlock";
|
|
5085
|
+
var TimelineRoot = react.forwardRef(
|
|
5086
|
+
({
|
|
5087
|
+
children,
|
|
5088
|
+
variant: variantProp,
|
|
5089
|
+
orientation,
|
|
5090
|
+
events,
|
|
5091
|
+
heading,
|
|
5092
|
+
description,
|
|
5093
|
+
animated = true,
|
|
5094
|
+
className
|
|
5095
|
+
}, ref) => {
|
|
5096
|
+
const scrollRef = react.useRef(null);
|
|
5097
|
+
let variant = variantProp ?? "stacked";
|
|
5098
|
+
if (!variantProp && orientation) {
|
|
5099
|
+
variant = orientation === "horizontal" ? "horizontal" : "stacked";
|
|
5100
|
+
}
|
|
5101
|
+
const isHorizontal = variant === "horizontal";
|
|
5102
|
+
const isAlternating = variant === "alternating";
|
|
5103
|
+
const items = events ? events.map((e, i) => /* @__PURE__ */ jsxRuntime.jsxs(TimelineItem, { date: e.date, emoji: e.emoji, icon: e.icon, color: e.color, children: [
|
|
5104
|
+
e.title && /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "font-semibold text-zinc-900 dark:text-white", children: e.title }),
|
|
5105
|
+
e.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-sm leading-relaxed text-zinc-600 dark:text-zinc-400", children: e.description })
|
|
5106
|
+
] }, i)) : react.Children.toArray(children);
|
|
5107
|
+
const handleWheel = react.useCallback((e) => {
|
|
5108
|
+
if (!scrollRef.current) return;
|
|
5109
|
+
e.preventDefault();
|
|
5110
|
+
scrollRef.current.scrollLeft += e.deltaY;
|
|
5111
|
+
}, []);
|
|
5112
|
+
const content = items.map((child, i) => /* @__PURE__ */ jsxRuntime.jsx(TimelineContext.Provider, { value: { variant, index: i, total: items.length, animated }, children: child }, i));
|
|
5113
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, "data-react-fancy-timeline": "", "data-variant": variant, className, children: [
|
|
5114
|
+
(heading || description) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-8", children: [
|
|
5115
|
+
heading && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xl font-semibold text-zinc-900 dark:text-white", children: heading }),
|
|
5116
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-zinc-500 dark:text-zinc-400", children: description })
|
|
5117
|
+
] }),
|
|
5118
|
+
isHorizontal ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5119
|
+
"div",
|
|
5120
|
+
{
|
|
5121
|
+
ref: scrollRef,
|
|
5122
|
+
className: "overflow-x-auto pb-4 -mb-4",
|
|
5123
|
+
style: { scrollbarWidth: "thin", scrollbarColor: "rgb(161 161 170) transparent" },
|
|
5124
|
+
onWheel: handleWheel,
|
|
5125
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-w-max items-start", children: content })
|
|
5126
|
+
}
|
|
5127
|
+
) : (
|
|
5128
|
+
/* Vertical variants: continuous background line behind all events */
|
|
5129
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
5130
|
+
items.length > 1 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(
|
|
5131
|
+
"absolute top-0 bottom-0 w-px bg-zinc-200 dark:bg-zinc-700",
|
|
5132
|
+
isAlternating ? "left-4 md:left-1/2 md:-translate-x-px" : "left-4"
|
|
5133
|
+
) }),
|
|
5134
|
+
content
|
|
5135
|
+
] })
|
|
5136
|
+
)
|
|
5137
|
+
] });
|
|
5138
|
+
}
|
|
5139
|
+
);
|
|
5140
|
+
TimelineRoot.displayName = "Timeline";
|
|
5141
|
+
var Timeline = Object.assign(TimelineRoot, {
|
|
5142
|
+
Item: TimelineItem,
|
|
5143
|
+
Block: TimelineBlock
|
|
5144
|
+
});
|
|
4738
5145
|
var Tooltip = react.forwardRef(
|
|
4739
5146
|
function Tooltip2({ children, content, placement = "top", delay = 200, offset = 8, className }, _ref) {
|
|
4740
5147
|
const [open, setOpen] = react.useState(false);
|
|
@@ -4769,7 +5176,7 @@ var Tooltip = react.forwardRef(
|
|
|
4769
5176
|
"data-react-fancy-tooltip": "",
|
|
4770
5177
|
role: "tooltip",
|
|
4771
5178
|
className: cn(
|
|
4772
|
-
"fancy-fade-in pointer-events-none fixed z-50 max-w-xs rounded-lg bg-zinc-900 px-3 py-1.5 text-sm text-white shadow-lg dark:bg-zinc-
|
|
5179
|
+
"fancy-fade-in pointer-events-none fixed z-50 max-w-xs rounded-lg bg-zinc-900 px-3 py-1.5 text-sm text-white shadow-lg dark:bg-zinc-700 dark:text-zinc-100",
|
|
4773
5180
|
className
|
|
4774
5181
|
),
|
|
4775
5182
|
style: { left: position.x, top: position.y },
|
|
@@ -4779,7 +5186,7 @@ var Tooltip = react.forwardRef(
|
|
|
4779
5186
|
"div",
|
|
4780
5187
|
{
|
|
4781
5188
|
className: cn(
|
|
4782
|
-
"absolute h-2 w-2 rotate-45 bg-zinc-900 dark:bg-zinc-
|
|
5189
|
+
"absolute h-2 w-2 rotate-45 bg-zinc-900 dark:bg-zinc-700",
|
|
4783
5190
|
position.placement.startsWith("top") && "bottom-[-4px] left-1/2 -translate-x-1/2",
|
|
4784
5191
|
position.placement.startsWith("bottom") && "top-[-4px] left-1/2 -translate-x-1/2",
|
|
4785
5192
|
position.placement.startsWith("left") && "right-[-4px] top-1/2 -translate-y-1/2",
|
|
@@ -4802,78 +5209,26 @@ function usePopover() {
|
|
|
4802
5209
|
}
|
|
4803
5210
|
return ctx;
|
|
4804
5211
|
}
|
|
4805
|
-
function PopoverTrigger({ children }) {
|
|
4806
|
-
const { setOpen, open, anchorRef } = usePopover();
|
|
4807
|
-
return
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
const el = ref.current;
|
|
4820
|
-
if (!el || el.contains(event.target)) return;
|
|
4821
|
-
if (ignoreRef?.current?.contains(event.target)) return;
|
|
4822
|
-
handler(event);
|
|
4823
|
-
};
|
|
4824
|
-
document.addEventListener("mousedown", listener);
|
|
4825
|
-
document.addEventListener("touchstart", listener);
|
|
4826
|
-
return () => {
|
|
4827
|
-
document.removeEventListener("mousedown", listener);
|
|
4828
|
-
document.removeEventListener("touchstart", listener);
|
|
4829
|
-
};
|
|
4830
|
-
}, [ref, handler, enabled, ignoreRef]);
|
|
4831
|
-
}
|
|
4832
|
-
function useEscapeKey(handler, enabled = true) {
|
|
4833
|
-
react.useEffect(() => {
|
|
4834
|
-
if (!enabled) return;
|
|
4835
|
-
const listener = (event) => {
|
|
4836
|
-
if (event.key === "Escape") {
|
|
4837
|
-
handler();
|
|
4838
|
-
}
|
|
4839
|
-
};
|
|
4840
|
-
document.addEventListener("keydown", listener);
|
|
4841
|
-
return () => document.removeEventListener("keydown", listener);
|
|
4842
|
-
}, [handler, enabled]);
|
|
4843
|
-
}
|
|
4844
|
-
function useAnimation({
|
|
4845
|
-
open,
|
|
4846
|
-
enterClass,
|
|
4847
|
-
exitClass
|
|
4848
|
-
}) {
|
|
4849
|
-
const [mounted, setMounted] = react.useState(open);
|
|
4850
|
-
const [animClass, setAnimClass] = react.useState(open ? enterClass : "");
|
|
4851
|
-
const ref = react.useRef(null);
|
|
4852
|
-
react.useEffect(() => {
|
|
4853
|
-
if (open) {
|
|
4854
|
-
setMounted(true);
|
|
4855
|
-
setAnimClass(enterClass);
|
|
4856
|
-
} else if (mounted) {
|
|
4857
|
-
setAnimClass(exitClass);
|
|
4858
|
-
}
|
|
4859
|
-
}, [open, enterClass, exitClass, mounted]);
|
|
4860
|
-
const handleAnimationEnd = react.useCallback(() => {
|
|
4861
|
-
if (!open) {
|
|
4862
|
-
setMounted(false);
|
|
4863
|
-
setAnimClass("");
|
|
5212
|
+
function PopoverTrigger({ children, className }) {
|
|
5213
|
+
const { setOpen, open, anchorRef, hover, onHoverEnter, onHoverLeave } = usePopover();
|
|
5214
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5215
|
+
"span",
|
|
5216
|
+
{
|
|
5217
|
+
ref: anchorRef,
|
|
5218
|
+
"data-react-fancy-popover-trigger": "",
|
|
5219
|
+
className: cn("inline-flex", className),
|
|
5220
|
+
onClick: hover ? void 0 : () => setOpen(!open),
|
|
5221
|
+
onMouseEnter: hover ? onHoverEnter : void 0,
|
|
5222
|
+
onMouseLeave: hover ? onHoverLeave : void 0,
|
|
5223
|
+
"aria-expanded": open,
|
|
5224
|
+
"aria-haspopup": true,
|
|
5225
|
+
children
|
|
4864
5226
|
}
|
|
4865
|
-
|
|
4866
|
-
react.useEffect(() => {
|
|
4867
|
-
const el = ref.current;
|
|
4868
|
-
if (!el) return;
|
|
4869
|
-
el.addEventListener("animationend", handleAnimationEnd);
|
|
4870
|
-
return () => el.removeEventListener("animationend", handleAnimationEnd);
|
|
4871
|
-
}, [handleAnimationEnd, mounted]);
|
|
4872
|
-
return { mounted, className: animClass, ref };
|
|
5227
|
+
);
|
|
4873
5228
|
}
|
|
5229
|
+
PopoverTrigger.displayName = "PopoverTrigger";
|
|
4874
5230
|
function PopoverContent({ children, className }) {
|
|
4875
|
-
const { open, setOpen, anchorRef, placement, offset } = usePopover();
|
|
4876
|
-
const floatingRef = react.useRef(null);
|
|
5231
|
+
const { open, setOpen, anchorRef, floatingRef, placement, offset, hover, onHoverEnter, onHoverLeave } = usePopover();
|
|
4877
5232
|
const outsideRef = react.useRef(null);
|
|
4878
5233
|
const position = useFloatingPosition(anchorRef, floatingRef, {
|
|
4879
5234
|
placement,
|
|
@@ -4881,29 +5236,26 @@ function PopoverContent({ children, className }) {
|
|
|
4881
5236
|
enabled: open
|
|
4882
5237
|
});
|
|
4883
5238
|
const close = react.useCallback(() => setOpen(false), [setOpen]);
|
|
4884
|
-
useOutsideClick(outsideRef, close, open, anchorRef);
|
|
5239
|
+
useOutsideClick(outsideRef, close, open && !hover, anchorRef);
|
|
4885
5240
|
useEscapeKey(close, open);
|
|
4886
|
-
const
|
|
4887
|
-
|
|
4888
|
-
enterClass: "fancy-scale-in",
|
|
4889
|
-
exitClass: "fancy-fade-out"
|
|
4890
|
-
});
|
|
4891
|
-
if (!mounted) return null;
|
|
5241
|
+
const positioned = position.x !== -9999 && position.y !== -9999;
|
|
5242
|
+
if (!open) return null;
|
|
4892
5243
|
return /* @__PURE__ */ jsxRuntime.jsx(Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4893
5244
|
"div",
|
|
4894
5245
|
{
|
|
4895
5246
|
ref: (node) => {
|
|
4896
5247
|
outsideRef.current = node;
|
|
4897
5248
|
floatingRef.current = node;
|
|
4898
|
-
animRef.current = node;
|
|
4899
5249
|
},
|
|
4900
5250
|
"data-react-fancy-popover": "",
|
|
4901
5251
|
className: cn(
|
|
4902
5252
|
"fixed z-50 rounded-xl border border-zinc-200 bg-white p-4 text-zinc-700 shadow-lg dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-200 dark:shadow-zinc-950/50",
|
|
4903
|
-
|
|
5253
|
+
positioned ? "fancy-scale-in" : "invisible",
|
|
4904
5254
|
className
|
|
4905
5255
|
),
|
|
4906
5256
|
style: { left: position.x, top: position.y },
|
|
5257
|
+
onMouseEnter: hover ? onHoverEnter : void 0,
|
|
5258
|
+
onMouseLeave: hover ? onHoverLeave : void 0,
|
|
4907
5259
|
children
|
|
4908
5260
|
}
|
|
4909
5261
|
) });
|
|
@@ -4915,17 +5267,37 @@ function PopoverRoot({
|
|
|
4915
5267
|
defaultOpen = false,
|
|
4916
5268
|
onOpenChange,
|
|
4917
5269
|
placement = "bottom",
|
|
4918
|
-
offset = 8
|
|
5270
|
+
offset = 8,
|
|
5271
|
+
hover = false,
|
|
5272
|
+
hoverDelay = 200,
|
|
5273
|
+
hoverCloseDelay = 300
|
|
4919
5274
|
}) {
|
|
4920
|
-
const [
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
onOpenChange
|
|
4924
|
-
);
|
|
5275
|
+
const [internalOpen, setInternalOpen] = react.useState(defaultOpen);
|
|
5276
|
+
const isControlled = controlledOpen !== void 0;
|
|
5277
|
+
const open = isControlled ? controlledOpen : internalOpen;
|
|
4925
5278
|
const anchorRef = react.useRef(null);
|
|
5279
|
+
const floatingRef = react.useRef(null);
|
|
5280
|
+
const hoverTimeoutRef = react.useRef(void 0);
|
|
5281
|
+
const setOpen = react.useCallback(
|
|
5282
|
+
(next) => {
|
|
5283
|
+
if (!isControlled) setInternalOpen(next);
|
|
5284
|
+
onOpenChange?.(next);
|
|
5285
|
+
},
|
|
5286
|
+
[isControlled, onOpenChange]
|
|
5287
|
+
);
|
|
5288
|
+
const onHoverEnter = react.useCallback(() => {
|
|
5289
|
+
if (!hover) return;
|
|
5290
|
+
clearTimeout(hoverTimeoutRef.current);
|
|
5291
|
+
hoverTimeoutRef.current = setTimeout(() => setOpen(true), hoverDelay);
|
|
5292
|
+
}, [hover, hoverDelay, setOpen]);
|
|
5293
|
+
const onHoverLeave = react.useCallback(() => {
|
|
5294
|
+
if (!hover) return;
|
|
5295
|
+
clearTimeout(hoverTimeoutRef.current);
|
|
5296
|
+
hoverTimeoutRef.current = setTimeout(() => setOpen(false), hoverCloseDelay);
|
|
5297
|
+
}, [hover, hoverCloseDelay, setOpen]);
|
|
4926
5298
|
const ctx = react.useMemo(
|
|
4927
|
-
() => ({ open, setOpen, anchorRef, placement, offset }),
|
|
4928
|
-
[open, setOpen,
|
|
5299
|
+
() => ({ open, setOpen, anchorRef, floatingRef, placement, offset, hover, onHoverEnter, onHoverLeave }),
|
|
5300
|
+
[open, setOpen, placement, offset, hover, onHoverEnter, onHoverLeave]
|
|
4929
5301
|
);
|
|
4930
5302
|
return /* @__PURE__ */ jsxRuntime.jsx(PopoverContext.Provider, { value: ctx, children });
|
|
4931
5303
|
}
|
|
@@ -4953,6 +5325,36 @@ function DropdownTrigger({ children }) {
|
|
|
4953
5325
|
});
|
|
4954
5326
|
}
|
|
4955
5327
|
DropdownTrigger.displayName = "DropdownTrigger";
|
|
5328
|
+
function useAnimation({
|
|
5329
|
+
open,
|
|
5330
|
+
enterClass,
|
|
5331
|
+
exitClass
|
|
5332
|
+
}) {
|
|
5333
|
+
const [mounted, setMounted] = react.useState(open);
|
|
5334
|
+
const [animClass, setAnimClass] = react.useState(open ? enterClass : "");
|
|
5335
|
+
const ref = react.useRef(null);
|
|
5336
|
+
react.useEffect(() => {
|
|
5337
|
+
if (open) {
|
|
5338
|
+
setMounted(true);
|
|
5339
|
+
setAnimClass(enterClass);
|
|
5340
|
+
} else if (mounted) {
|
|
5341
|
+
setAnimClass(exitClass);
|
|
5342
|
+
}
|
|
5343
|
+
}, [open, enterClass, exitClass, mounted]);
|
|
5344
|
+
const handleAnimationEnd = react.useCallback(() => {
|
|
5345
|
+
if (!open) {
|
|
5346
|
+
setMounted(false);
|
|
5347
|
+
setAnimClass("");
|
|
5348
|
+
}
|
|
5349
|
+
}, [open]);
|
|
5350
|
+
react.useEffect(() => {
|
|
5351
|
+
const el = ref.current;
|
|
5352
|
+
if (!el) return;
|
|
5353
|
+
el.addEventListener("animationend", handleAnimationEnd);
|
|
5354
|
+
return () => el.removeEventListener("animationend", handleAnimationEnd);
|
|
5355
|
+
}, [handleAnimationEnd, mounted]);
|
|
5356
|
+
return { mounted, className: animClass, ref };
|
|
5357
|
+
}
|
|
4956
5358
|
function DropdownItems({ children, className }) {
|
|
4957
5359
|
const { open, setOpen, anchorRef, activeIndex, setActiveIndex, placement, offset } = useDropdown();
|
|
4958
5360
|
const floatingRef = react.useRef(null);
|
|
@@ -6271,7 +6673,7 @@ var Autocomplete = react.forwardRef(
|
|
|
6271
6673
|
role: "combobox",
|
|
6272
6674
|
"aria-expanded": open,
|
|
6273
6675
|
"aria-autocomplete": "list",
|
|
6274
|
-
className: "w-full rounded-lg border border-zinc-200 bg-white px-3 py-2 text-sm text-zinc-900 placeholder:text-zinc-400 outline-none transition-
|
|
6676
|
+
className: "w-full rounded-lg border border-zinc-200 bg-white px-3 py-2 text-sm text-zinc-900 placeholder:text-zinc-400 outline-none transition-[border-color,box-shadow] duration-150 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/40 dark:border-zinc-700 dark:bg-[#1e1e24] dark:text-zinc-100 dark:placeholder:text-zinc-500 dark:focus:border-blue-400 dark:focus:ring-blue-400/20"
|
|
6275
6677
|
}
|
|
6276
6678
|
),
|
|
6277
6679
|
open && /* @__PURE__ */ jsxRuntime.jsx(Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -6365,7 +6767,7 @@ var Pillbox = react.forwardRef(
|
|
|
6365
6767
|
"data-react-fancy-pillbox": "",
|
|
6366
6768
|
ref,
|
|
6367
6769
|
className: cn(
|
|
6368
|
-
"flex flex-wrap items-center gap-1.5 rounded-lg border border-zinc-200 bg-white px-3 py-2 transition-
|
|
6770
|
+
"flex flex-wrap items-center gap-1.5 rounded-lg border border-zinc-200 bg-white px-3 py-2 transition-[border-color,box-shadow] duration-150 focus-within:border-blue-500 focus-within:ring-2 focus-within:ring-blue-500/40 dark:border-zinc-700 dark:bg-[#1e1e24] dark:text-zinc-100 dark:focus-within:border-blue-400 dark:focus-within:ring-blue-400/20",
|
|
6369
6771
|
disabled && "cursor-not-allowed opacity-50",
|
|
6370
6772
|
className
|
|
6371
6773
|
),
|
|
@@ -6496,7 +6898,7 @@ var OtpInput = react.forwardRef(
|
|
|
6496
6898
|
onFocus: (e) => e.target.select(),
|
|
6497
6899
|
disabled,
|
|
6498
6900
|
autoFocus: autoFocus && i === 0,
|
|
6499
|
-
className: "h-12 w-10 rounded-lg border border-zinc-200 bg-white text-center text-lg font-medium outline-none transition-
|
|
6901
|
+
className: "h-12 w-10 rounded-lg border border-zinc-200 bg-white text-center text-lg font-medium text-zinc-900 outline-none transition-[border-color,box-shadow] duration-150 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/40 dark:border-zinc-700 dark:bg-[#1e1e24] dark:text-zinc-100 dark:focus:border-blue-400 dark:focus:ring-blue-400/20",
|
|
6500
6902
|
"aria-label": `Digit ${i + 1}`
|
|
6501
6903
|
},
|
|
6502
6904
|
i
|
|
@@ -6545,7 +6947,7 @@ function FileUploadDropzone({
|
|
|
6545
6947
|
onClick: () => !disabled && inputRef.current?.click(),
|
|
6546
6948
|
className: cn(
|
|
6547
6949
|
"flex cursor-pointer flex-col items-center justify-center rounded-xl border-2 border-dashed p-8 text-center transition-colors",
|
|
6548
|
-
dragOver ? "border-blue-400 bg-blue-50 dark:border-blue-500 dark:bg-blue-950" : "border-zinc-300 hover:border-zinc-400 dark:border-zinc-
|
|
6950
|
+
dragOver ? "border-blue-400 bg-blue-50 dark:border-blue-500 dark:bg-blue-950" : "border-zinc-300 hover:border-zinc-400 dark:border-zinc-700 dark:hover:border-zinc-500",
|
|
6549
6951
|
disabled && "cursor-not-allowed opacity-50",
|
|
6550
6952
|
className
|
|
6551
6953
|
),
|
|
@@ -7905,6 +8307,7 @@ function usePanZoom({
|
|
|
7905
8307
|
if (!container) return;
|
|
7906
8308
|
function handleWheel(e) {
|
|
7907
8309
|
if (!zoomableRef.current) return;
|
|
8310
|
+
if (!e.ctrlKey && !e.metaKey) return;
|
|
7908
8311
|
e.preventDefault();
|
|
7909
8312
|
const rect = container.getBoundingClientRect();
|
|
7910
8313
|
const mouseX = e.clientX - rect.left;
|
|
@@ -9097,9 +9500,11 @@ function useCanvas() {
|
|
|
9097
9500
|
if (!ctx) throw new Error("useCanvas must be used within a Canvas component");
|
|
9098
9501
|
return ctx;
|
|
9099
9502
|
}
|
|
9100
|
-
function CanvasNode({ children, id, x, y, className, style }) {
|
|
9101
|
-
const { registerNode, unregisterNode } = useCanvas();
|
|
9503
|
+
function CanvasNode({ children, id, x, y, draggable, onPositionChange, className, style }) {
|
|
9504
|
+
const { registerNode, unregisterNode, viewport } = useCanvas();
|
|
9102
9505
|
const nodeRef = react.useRef(null);
|
|
9506
|
+
const isDragging = react.useRef(false);
|
|
9507
|
+
const dragStart = react.useRef({ mouseX: 0, mouseY: 0, nodeX: 0, nodeY: 0 });
|
|
9103
9508
|
react.useEffect(() => {
|
|
9104
9509
|
const el = nodeRef.current;
|
|
9105
9510
|
if (!el) return;
|
|
@@ -9114,14 +9519,39 @@ function CanvasNode({ children, id, x, y, className, style }) {
|
|
|
9114
9519
|
unregisterNode(id);
|
|
9115
9520
|
};
|
|
9116
9521
|
}, [id, x, y, registerNode, unregisterNode]);
|
|
9522
|
+
const handlePointerDown = react.useCallback(
|
|
9523
|
+
(e) => {
|
|
9524
|
+
if (!draggable || e.button !== 0) return;
|
|
9525
|
+
e.stopPropagation();
|
|
9526
|
+
isDragging.current = true;
|
|
9527
|
+
dragStart.current = { mouseX: e.clientX, mouseY: e.clientY, nodeX: x, nodeY: y };
|
|
9528
|
+
e.target.setPointerCapture(e.pointerId);
|
|
9529
|
+
},
|
|
9530
|
+
[draggable, x, y]
|
|
9531
|
+
);
|
|
9532
|
+
const handlePointerMove = react.useCallback(
|
|
9533
|
+
(e) => {
|
|
9534
|
+
if (!isDragging.current) return;
|
|
9535
|
+
const dx = (e.clientX - dragStart.current.mouseX) / viewport.zoom;
|
|
9536
|
+
const dy = (e.clientY - dragStart.current.mouseY) / viewport.zoom;
|
|
9537
|
+
onPositionChange?.(dragStart.current.nodeX + dx, dragStart.current.nodeY + dy);
|
|
9538
|
+
},
|
|
9539
|
+
[viewport.zoom, onPositionChange]
|
|
9540
|
+
);
|
|
9541
|
+
const handlePointerUp = react.useCallback(() => {
|
|
9542
|
+
isDragging.current = false;
|
|
9543
|
+
}, []);
|
|
9117
9544
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
9118
9545
|
"div",
|
|
9119
9546
|
{
|
|
9120
9547
|
ref: nodeRef,
|
|
9121
9548
|
"data-react-fancy-canvas-node": "",
|
|
9122
9549
|
"data-node-id": id,
|
|
9123
|
-
className: cn("absolute", className),
|
|
9550
|
+
className: cn("absolute", draggable && "cursor-grab active:cursor-grabbing", className),
|
|
9124
9551
|
style: { left: x, top: y, ...style },
|
|
9552
|
+
onPointerDown: handlePointerDown,
|
|
9553
|
+
onPointerMove: handlePointerMove,
|
|
9554
|
+
onPointerUp: handlePointerUp,
|
|
9125
9555
|
children
|
|
9126
9556
|
}
|
|
9127
9557
|
);
|
|
@@ -9158,10 +9588,18 @@ function getAnchorPoint(rect, anchor, otherRect) {
|
|
|
9158
9588
|
}
|
|
9159
9589
|
}
|
|
9160
9590
|
function bezierPath(from, to) {
|
|
9161
|
-
const dx = Math.abs(to.x - from.x)
|
|
9162
|
-
const
|
|
9163
|
-
|
|
9164
|
-
|
|
9591
|
+
const dx = Math.abs(to.x - from.x);
|
|
9592
|
+
const dy = Math.abs(to.y - from.y);
|
|
9593
|
+
if (dx > dy) {
|
|
9594
|
+
const offset2 = dx * 0.5;
|
|
9595
|
+
const cp1x = from.x + (to.x > from.x ? offset2 : -offset2);
|
|
9596
|
+
const cp2x = to.x + (to.x > from.x ? -offset2 : offset2);
|
|
9597
|
+
return `M${from.x},${from.y} C${cp1x},${from.y} ${cp2x},${to.y} ${to.x},${to.y}`;
|
|
9598
|
+
}
|
|
9599
|
+
const offset = Math.max(dy * 0.5, 30);
|
|
9600
|
+
const cp1y = from.y + (to.y > from.y ? offset : -offset);
|
|
9601
|
+
const cp2y = to.y + (to.y > from.y ? -offset : offset);
|
|
9602
|
+
return `M${from.x},${from.y} C${from.x},${cp1y} ${to.x},${cp2y} ${to.x},${to.y}`;
|
|
9165
9603
|
}
|
|
9166
9604
|
function stepPath(from, to) {
|
|
9167
9605
|
const midX = (from.x + to.x) / 2;
|
|
@@ -9346,6 +9784,7 @@ function CanvasRoot({
|
|
|
9346
9784
|
pannable = true,
|
|
9347
9785
|
zoomable = true,
|
|
9348
9786
|
showGrid = false,
|
|
9787
|
+
fitOnMount = false,
|
|
9349
9788
|
className,
|
|
9350
9789
|
style
|
|
9351
9790
|
}) {
|
|
@@ -9365,15 +9804,41 @@ function CanvasRoot({
|
|
|
9365
9804
|
() => ({ viewport, setViewport, registerNode, unregisterNode, nodeRects, registryVersion, containerRef }),
|
|
9366
9805
|
[viewport, setViewport, registerNode, unregisterNode, nodeRects, registryVersion]
|
|
9367
9806
|
);
|
|
9807
|
+
const hasFitted = react.useRef(false);
|
|
9808
|
+
react.useEffect(() => {
|
|
9809
|
+
if (!fitOnMount || hasFitted.current || nodeRects.size === 0) return;
|
|
9810
|
+
const container = containerRef.current;
|
|
9811
|
+
if (!container || container.clientWidth === 0) return;
|
|
9812
|
+
hasFitted.current = true;
|
|
9813
|
+
requestAnimationFrame(() => {
|
|
9814
|
+
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
9815
|
+
nodeRects.forEach((r) => {
|
|
9816
|
+
minX = Math.min(minX, r.x);
|
|
9817
|
+
minY = Math.min(minY, r.y);
|
|
9818
|
+
maxX = Math.max(maxX, r.x + r.width);
|
|
9819
|
+
maxY = Math.max(maxY, r.y + r.height);
|
|
9820
|
+
});
|
|
9821
|
+
const padding = 40;
|
|
9822
|
+
const contentW = maxX - minX + padding * 2;
|
|
9823
|
+
const contentH = maxY - minY + padding * 2;
|
|
9824
|
+
const cw = container.clientWidth;
|
|
9825
|
+
const ch = container.clientHeight;
|
|
9826
|
+
const zoom = Math.min(cw / contentW, ch / contentH, 1.5);
|
|
9827
|
+
const panX = (cw - contentW * zoom) / 2 - minX * zoom + padding * zoom;
|
|
9828
|
+
const panY = (ch - contentH * zoom) / 2 - minY * zoom + padding * zoom;
|
|
9829
|
+
setViewport({ panX, panY, zoom });
|
|
9830
|
+
});
|
|
9831
|
+
}, [fitOnMount, nodeRects, registryVersion, setViewport]);
|
|
9368
9832
|
const edges = [];
|
|
9369
9833
|
const others = [];
|
|
9370
9834
|
const overlays = [];
|
|
9371
9835
|
react.Children.forEach(children, (child) => {
|
|
9372
9836
|
const el = child;
|
|
9373
9837
|
if (!el || !el.type) return;
|
|
9374
|
-
|
|
9838
|
+
const elType = el.type;
|
|
9839
|
+
if (elType === CanvasEdge || elType?._isCanvasEdge) {
|
|
9375
9840
|
edges.push(el);
|
|
9376
|
-
} else if (
|
|
9841
|
+
} else if (elType === CanvasMinimap || elType === CanvasControls) {
|
|
9377
9842
|
overlays.push(el);
|
|
9378
9843
|
} else {
|
|
9379
9844
|
others.push(el);
|
|
@@ -9420,15 +9885,16 @@ function CanvasRoot({
|
|
|
9420
9885
|
},
|
|
9421
9886
|
children: [
|
|
9422
9887
|
/* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
|
|
9423
|
-
/* @__PURE__ */ jsxRuntime.jsx("marker", { id: "canvas-arrow", viewBox: "0 0 10 10", refX: "10", refY: "5", markerWidth: "8", markerHeight: "8", orient: "auto
|
|
9424
|
-
/* @__PURE__ */ jsxRuntime.jsx("marker", { id: "canvas-circle", viewBox: "0 0 10 10", refX: "5", refY: "5", markerWidth: "8", markerHeight: "8", orient: "auto
|
|
9425
|
-
/* @__PURE__ */ jsxRuntime.jsx("marker", { id: "canvas-
|
|
9426
|
-
/* @__PURE__ */ jsxRuntime.
|
|
9427
|
-
|
|
9428
|
-
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "
|
|
9429
|
-
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "
|
|
9430
|
-
|
|
9431
|
-
|
|
9888
|
+
/* @__PURE__ */ jsxRuntime.jsx("marker", { id: "canvas-arrow", viewBox: "0 0 10 10", refX: "10", refY: "5", markerWidth: "8", markerHeight: "8", orient: "auto", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M0,0 L10,5 L0,10 Z", fill: "#71717a" }) }),
|
|
9889
|
+
/* @__PURE__ */ jsxRuntime.jsx("marker", { id: "canvas-circle", viewBox: "0 0 10 10", refX: "5", refY: "5", markerWidth: "8", markerHeight: "8", orient: "auto", children: /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "5", cy: "5", r: "3.5", fill: "#71717a" }) }),
|
|
9890
|
+
/* @__PURE__ */ jsxRuntime.jsx("marker", { id: "canvas-diamond", viewBox: "0 0 12 12", refX: "6", refY: "6", markerWidth: "10", markerHeight: "10", orient: "auto", children: /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "6,0 12,6 6,12 0,6", fill: "none", stroke: "#71717a", strokeWidth: "1.5" }) }),
|
|
9891
|
+
/* @__PURE__ */ jsxRuntime.jsx("marker", { id: "canvas-one", viewBox: "0 0 2 16", refX: "1", refY: "8", markerWidth: "2", markerHeight: "14", orient: "auto", children: /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "1", y1: "0", x2: "1", y2: "16", stroke: "#71717a", strokeWidth: "2" }) }),
|
|
9892
|
+
/* @__PURE__ */ jsxRuntime.jsxs("marker", { id: "canvas-crow-foot", viewBox: "0 0 16 16", refX: "16", refY: "8", markerWidth: "14", markerHeight: "14", orient: "auto", children: [
|
|
9893
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "16", y1: "8", x2: "0", y2: "0", stroke: "#71717a", strokeWidth: "2", strokeLinecap: "round" }),
|
|
9894
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "16", y1: "8", x2: "0", y2: "8", stroke: "#71717a", strokeWidth: "2", strokeLinecap: "round" }),
|
|
9895
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "16", y1: "8", x2: "0", y2: "16", stroke: "#71717a", strokeWidth: "2", strokeLinecap: "round" }),
|
|
9896
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "16", y1: "0", x2: "16", y2: "16", stroke: "#71717a", strokeWidth: "2", strokeLinecap: "round" })
|
|
9897
|
+
] })
|
|
9432
9898
|
] }),
|
|
9433
9899
|
edges
|
|
9434
9900
|
]
|
|
@@ -9486,13 +9952,16 @@ function DiagramField({
|
|
|
9486
9952
|
DiagramField.displayName = "DiagramField";
|
|
9487
9953
|
function DiagramEntity({
|
|
9488
9954
|
children,
|
|
9489
|
-
id,
|
|
9955
|
+
id: idProp,
|
|
9490
9956
|
name,
|
|
9491
9957
|
x = 0,
|
|
9492
9958
|
y = 0,
|
|
9493
9959
|
color = "bg-blue-600 dark:bg-blue-500",
|
|
9960
|
+
draggable,
|
|
9961
|
+
onPositionChange,
|
|
9494
9962
|
className
|
|
9495
9963
|
}) {
|
|
9964
|
+
const id = idProp ?? name;
|
|
9496
9965
|
const fields = [];
|
|
9497
9966
|
const other = [];
|
|
9498
9967
|
react.Children.forEach(children, (child) => {
|
|
@@ -9504,7 +9973,7 @@ function DiagramEntity({
|
|
|
9504
9973
|
other.push(el);
|
|
9505
9974
|
}
|
|
9506
9975
|
});
|
|
9507
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Canvas.Node, { id, x, y, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9976
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Canvas.Node, { id, x, y, draggable, onPositionChange, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9508
9977
|
"div",
|
|
9509
9978
|
{
|
|
9510
9979
|
"data-react-fancy-diagram-entity": "",
|
|
@@ -9531,37 +10000,193 @@ function DiagramEntity({
|
|
|
9531
10000
|
) });
|
|
9532
10001
|
}
|
|
9533
10002
|
DiagramEntity.displayName = "DiagramEntity";
|
|
9534
|
-
|
|
9535
|
-
|
|
9536
|
-
|
|
9537
|
-
|
|
9538
|
-
|
|
9539
|
-
|
|
9540
|
-
case "
|
|
9541
|
-
|
|
10003
|
+
var HEADER_HEIGHT = 36;
|
|
10004
|
+
var FIELD_HEIGHT = 28;
|
|
10005
|
+
var SYMBOL_SIZE = 12;
|
|
10006
|
+
function oneSymbol(pt, direction) {
|
|
10007
|
+
const s = SYMBOL_SIZE * 0.6;
|
|
10008
|
+
switch (direction) {
|
|
10009
|
+
case "left":
|
|
10010
|
+
case "right":
|
|
10011
|
+
return `M${pt.x},${pt.y - s} L${pt.x},${pt.y + s}`;
|
|
10012
|
+
case "up":
|
|
10013
|
+
case "down":
|
|
10014
|
+
return `M${pt.x - s},${pt.y} L${pt.x + s},${pt.y}`;
|
|
9542
10015
|
}
|
|
9543
10016
|
}
|
|
10017
|
+
function crowFootSymbol(pt, direction) {
|
|
10018
|
+
const s = SYMBOL_SIZE;
|
|
10019
|
+
const spread = s * 0.8;
|
|
10020
|
+
let tip;
|
|
10021
|
+
switch (direction) {
|
|
10022
|
+
case "right":
|
|
10023
|
+
tip = { x: pt.x - s, y: pt.y };
|
|
10024
|
+
return [
|
|
10025
|
+
`M${pt.x},${pt.y - spread} L${tip.x},${tip.y}`,
|
|
10026
|
+
`M${pt.x},${pt.y} L${tip.x},${tip.y}`,
|
|
10027
|
+
`M${pt.x},${pt.y + spread} L${tip.x},${tip.y}`,
|
|
10028
|
+
// bar at entity edge
|
|
10029
|
+
`M${pt.x},${pt.y - spread} L${pt.x},${pt.y + spread}`
|
|
10030
|
+
].join(" ");
|
|
10031
|
+
case "left":
|
|
10032
|
+
tip = { x: pt.x + s, y: pt.y };
|
|
10033
|
+
return [
|
|
10034
|
+
`M${pt.x},${pt.y - spread} L${tip.x},${tip.y}`,
|
|
10035
|
+
`M${pt.x},${pt.y} L${tip.x},${tip.y}`,
|
|
10036
|
+
`M${pt.x},${pt.y + spread} L${tip.x},${tip.y}`,
|
|
10037
|
+
`M${pt.x},${pt.y - spread} L${pt.x},${pt.y + spread}`
|
|
10038
|
+
].join(" ");
|
|
10039
|
+
case "down":
|
|
10040
|
+
tip = { x: pt.x, y: pt.y - s };
|
|
10041
|
+
return [
|
|
10042
|
+
`M${pt.x - spread},${pt.y} L${tip.x},${tip.y}`,
|
|
10043
|
+
`M${pt.x},${pt.y} L${tip.x},${tip.y}`,
|
|
10044
|
+
`M${pt.x + spread},${pt.y} L${tip.x},${tip.y}`,
|
|
10045
|
+
`M${pt.x - spread},${pt.y} L${pt.x + spread},${pt.y}`
|
|
10046
|
+
].join(" ");
|
|
10047
|
+
case "up":
|
|
10048
|
+
tip = { x: pt.x, y: pt.y + s };
|
|
10049
|
+
return [
|
|
10050
|
+
`M${pt.x - spread},${pt.y} L${tip.x},${tip.y}`,
|
|
10051
|
+
`M${pt.x},${pt.y} L${tip.x},${tip.y}`,
|
|
10052
|
+
`M${pt.x + spread},${pt.y} L${tip.x},${tip.y}`,
|
|
10053
|
+
`M${pt.x - spread},${pt.y} L${pt.x + spread},${pt.y}`
|
|
10054
|
+
].join(" ");
|
|
10055
|
+
}
|
|
10056
|
+
}
|
|
10057
|
+
function getSymbolPath(type, end, pt, direction) {
|
|
10058
|
+
const side = end === "start" ? type.split("-to-")[0] : type.split("-to-")[1];
|
|
10059
|
+
if (side === "one") return oneSymbol(pt, direction);
|
|
10060
|
+
if (side === "many") return crowFootSymbol(pt, direction);
|
|
10061
|
+
return null;
|
|
10062
|
+
}
|
|
9544
10063
|
function DiagramRelation({
|
|
9545
10064
|
from,
|
|
9546
10065
|
to,
|
|
10066
|
+
fromField: fromFieldProp,
|
|
10067
|
+
toField: toFieldProp,
|
|
9547
10068
|
type,
|
|
9548
|
-
label
|
|
9549
|
-
className
|
|
10069
|
+
label
|
|
9550
10070
|
}) {
|
|
9551
|
-
const
|
|
9552
|
-
|
|
9553
|
-
|
|
9554
|
-
|
|
9555
|
-
|
|
9556
|
-
|
|
9557
|
-
|
|
9558
|
-
|
|
9559
|
-
|
|
9560
|
-
|
|
9561
|
-
|
|
10071
|
+
const { nodeRects, registryVersion } = useCanvas();
|
|
10072
|
+
const { schema } = useDiagram();
|
|
10073
|
+
const result = react.useMemo(() => {
|
|
10074
|
+
const fromRect = nodeRects.get(from);
|
|
10075
|
+
const toRect = nodeRects.get(to);
|
|
10076
|
+
if (!fromRect || !toRect) return null;
|
|
10077
|
+
const fromEntity = schema.entities.find((e) => (e.id ?? e.name) === from);
|
|
10078
|
+
const toEntity = schema.entities.find((e) => (e.id ?? e.name) === to);
|
|
10079
|
+
let fromFieldIdx = -1;
|
|
10080
|
+
let toFieldIdx = -1;
|
|
10081
|
+
if (fromFieldProp && fromEntity?.fields) {
|
|
10082
|
+
fromFieldIdx = fromEntity.fields.findIndex((f) => f.name === fromFieldProp);
|
|
10083
|
+
} else if (fromEntity?.fields) {
|
|
10084
|
+
fromFieldIdx = fromEntity.fields.findIndex((f) => f.primary);
|
|
9562
10085
|
}
|
|
9563
|
-
|
|
10086
|
+
if (toFieldProp && toEntity?.fields) {
|
|
10087
|
+
toFieldIdx = toEntity.fields.findIndex((f) => f.name === toFieldProp);
|
|
10088
|
+
} else if (toEntity?.fields) {
|
|
10089
|
+
const fromName = (fromEntity?.name ?? from).toLowerCase();
|
|
10090
|
+
toFieldIdx = toEntity.fields.findIndex(
|
|
10091
|
+
(f) => f.foreign && (f.name === `${fromName}_id` || f.name === `${fromName}Id`)
|
|
10092
|
+
);
|
|
10093
|
+
if (toFieldIdx === -1) {
|
|
10094
|
+
toFieldIdx = toEntity.fields.findIndex((f) => f.foreign);
|
|
10095
|
+
}
|
|
10096
|
+
}
|
|
10097
|
+
const fromFieldY = fromFieldIdx >= 0 ? HEADER_HEIGHT + fromFieldIdx * FIELD_HEIGHT + FIELD_HEIGHT / 2 : fromRect.height / 2;
|
|
10098
|
+
const toFieldY = toFieldIdx >= 0 ? HEADER_HEIGHT + toFieldIdx * FIELD_HEIGHT + FIELD_HEIGHT / 2 : toRect.height / 2;
|
|
10099
|
+
const fromCx = fromRect.x + fromRect.width / 2;
|
|
10100
|
+
const toCx = toRect.x + toRect.width / 2;
|
|
10101
|
+
const fromCy = fromRect.y + fromRect.height / 2;
|
|
10102
|
+
const toCy = toRect.y + toRect.height / 2;
|
|
10103
|
+
const dx = Math.abs(fromCx - toCx);
|
|
10104
|
+
const dy = Math.abs(fromCy - toCy);
|
|
10105
|
+
let fromPt, toPt;
|
|
10106
|
+
let fromDir;
|
|
10107
|
+
let toDir;
|
|
10108
|
+
if (dx > dy * 0.5) {
|
|
10109
|
+
if (fromCx < toCx) {
|
|
10110
|
+
fromPt = { x: fromRect.x + fromRect.width, y: fromRect.y + fromFieldY };
|
|
10111
|
+
toPt = { x: toRect.x, y: toRect.y + toFieldY };
|
|
10112
|
+
fromDir = "right";
|
|
10113
|
+
toDir = "left";
|
|
10114
|
+
} else {
|
|
10115
|
+
fromPt = { x: fromRect.x, y: fromRect.y + fromFieldY };
|
|
10116
|
+
toPt = { x: toRect.x + toRect.width, y: toRect.y + toFieldY };
|
|
10117
|
+
fromDir = "left";
|
|
10118
|
+
toDir = "right";
|
|
10119
|
+
}
|
|
10120
|
+
} else {
|
|
10121
|
+
if (fromCy < toCy) {
|
|
10122
|
+
fromPt = { x: fromRect.x + fromRect.width / 2, y: fromRect.y + fromRect.height };
|
|
10123
|
+
toPt = { x: toRect.x + toRect.width / 2, y: toRect.y };
|
|
10124
|
+
fromDir = "down";
|
|
10125
|
+
toDir = "up";
|
|
10126
|
+
} else {
|
|
10127
|
+
fromPt = { x: fromRect.x + fromRect.width / 2, y: fromRect.y };
|
|
10128
|
+
toPt = { x: toRect.x + toRect.width / 2, y: toRect.y + toRect.height };
|
|
10129
|
+
fromDir = "up";
|
|
10130
|
+
toDir = "down";
|
|
10131
|
+
}
|
|
10132
|
+
}
|
|
10133
|
+
const offsetFrom = { ...fromPt };
|
|
10134
|
+
const offsetTo = { ...toPt };
|
|
10135
|
+
switch (fromDir) {
|
|
10136
|
+
case "right":
|
|
10137
|
+
offsetFrom.x += SYMBOL_SIZE;
|
|
10138
|
+
break;
|
|
10139
|
+
case "left":
|
|
10140
|
+
offsetFrom.x -= SYMBOL_SIZE;
|
|
10141
|
+
break;
|
|
10142
|
+
case "down":
|
|
10143
|
+
offsetFrom.y += SYMBOL_SIZE;
|
|
10144
|
+
break;
|
|
10145
|
+
case "up":
|
|
10146
|
+
offsetFrom.y -= SYMBOL_SIZE;
|
|
10147
|
+
break;
|
|
10148
|
+
}
|
|
10149
|
+
switch (toDir) {
|
|
10150
|
+
case "right":
|
|
10151
|
+
offsetTo.x += SYMBOL_SIZE;
|
|
10152
|
+
break;
|
|
10153
|
+
case "left":
|
|
10154
|
+
offsetTo.x -= SYMBOL_SIZE;
|
|
10155
|
+
break;
|
|
10156
|
+
case "down":
|
|
10157
|
+
offsetTo.y += SYMBOL_SIZE;
|
|
10158
|
+
break;
|
|
10159
|
+
case "up":
|
|
10160
|
+
offsetTo.y -= SYMBOL_SIZE;
|
|
10161
|
+
break;
|
|
10162
|
+
}
|
|
10163
|
+
const adx = Math.abs(offsetTo.x - offsetFrom.x);
|
|
10164
|
+
const ady = Math.abs(offsetTo.y - offsetFrom.y);
|
|
10165
|
+
let linePath;
|
|
10166
|
+
if (adx > ady) {
|
|
10167
|
+
const off = adx * 0.4;
|
|
10168
|
+
const cp1x = offsetFrom.x + (offsetTo.x > offsetFrom.x ? off : -off);
|
|
10169
|
+
const cp2x = offsetTo.x + (offsetTo.x > offsetFrom.x ? -off : off);
|
|
10170
|
+
linePath = `M${offsetFrom.x},${offsetFrom.y} C${cp1x},${offsetFrom.y} ${cp2x},${offsetTo.y} ${offsetTo.x},${offsetTo.y}`;
|
|
10171
|
+
} else {
|
|
10172
|
+
const off = Math.max(ady * 0.4, 20);
|
|
10173
|
+
const cp1y = offsetFrom.y + (offsetTo.y > offsetFrom.y ? off : -off);
|
|
10174
|
+
const cp2y = offsetTo.y + (offsetTo.y > offsetFrom.y ? -off : off);
|
|
10175
|
+
linePath = `M${offsetFrom.x},${offsetFrom.y} C${offsetFrom.x},${cp1y} ${offsetTo.x},${cp2y} ${offsetTo.x},${offsetTo.y}`;
|
|
10176
|
+
}
|
|
10177
|
+
const startSymbol = getSymbolPath(type, "start", fromPt, fromDir);
|
|
10178
|
+
const endSymbol = getSymbolPath(type, "end", toPt, toDir);
|
|
10179
|
+
return { linePath, startSymbol, endSymbol, midX: (offsetFrom.x + offsetTo.x) / 2, midY: (offsetFrom.y + offsetTo.y) / 2 };
|
|
10180
|
+
}, [from, to, fromFieldProp, toFieldProp, type, schema, nodeRects, registryVersion]);
|
|
10181
|
+
if (!result) return null;
|
|
10182
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("g", { "data-react-fancy-diagram-relation": "", children: [
|
|
10183
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: result.linePath, fill: "none", stroke: "#71717a", strokeWidth: 2 }),
|
|
10184
|
+
result.startSymbol && /* @__PURE__ */ jsxRuntime.jsx("path", { d: result.startSymbol, fill: "none", stroke: "#71717a", strokeWidth: 2 }),
|
|
10185
|
+
result.endSymbol && /* @__PURE__ */ jsxRuntime.jsx("path", { d: result.endSymbol, fill: "none", stroke: "#71717a", strokeWidth: 2 }),
|
|
10186
|
+
label && /* @__PURE__ */ jsxRuntime.jsx("foreignObject", { x: result.midX - 40, y: result.midY - 12, width: 80, height: 24, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center text-xs text-zinc-500", children: label }) })
|
|
10187
|
+
] });
|
|
9564
10188
|
}
|
|
10189
|
+
DiagramRelation._isCanvasEdge = true;
|
|
9565
10190
|
DiagramRelation.displayName = "DiagramRelation";
|
|
9566
10191
|
var FORMAT_LABELS = {
|
|
9567
10192
|
erd: "ERD",
|
|
@@ -9672,12 +10297,12 @@ DiagramToolbar.displayName = "DiagramToolbar";
|
|
|
9672
10297
|
|
|
9673
10298
|
// src/components/Diagram/diagram.layout.ts
|
|
9674
10299
|
var ENTITY_WIDTH = 220;
|
|
9675
|
-
var
|
|
9676
|
-
var
|
|
10300
|
+
var HEADER_HEIGHT2 = 40;
|
|
10301
|
+
var FIELD_HEIGHT2 = 28;
|
|
9677
10302
|
var HORIZONTAL_GAP = 80;
|
|
9678
10303
|
var VERTICAL_GAP = 60;
|
|
9679
10304
|
function getEntityHeight(fieldCount) {
|
|
9680
|
-
return
|
|
10305
|
+
return HEADER_HEIGHT2 + Math.max(fieldCount, 1) * FIELD_HEIGHT2;
|
|
9681
10306
|
}
|
|
9682
10307
|
function computeDiagramLayout(schema) {
|
|
9683
10308
|
const positions = /* @__PURE__ */ new Map();
|
|
@@ -9780,58 +10405,103 @@ function DiagramRoot({
|
|
|
9780
10405
|
}) {
|
|
9781
10406
|
const downloadableRef = react.useRef(downloadable);
|
|
9782
10407
|
const importableRef = react.useRef(importable);
|
|
9783
|
-
const
|
|
10408
|
+
const normalizedSchema = react.useMemo(() => {
|
|
9784
10409
|
if (!schema) return { entities: [], relations: [] };
|
|
9785
|
-
const
|
|
9786
|
-
|
|
9787
|
-
|
|
9788
|
-
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
10410
|
+
const entities = schema.entities.map((e) => ({
|
|
10411
|
+
...e,
|
|
10412
|
+
id: e.id ?? e.name
|
|
10413
|
+
}));
|
|
10414
|
+
const relations = schema.relations.map((r, i) => ({
|
|
10415
|
+
...r,
|
|
10416
|
+
id: r.id ?? `rel-${i}`
|
|
10417
|
+
}));
|
|
10418
|
+
return { entities, relations };
|
|
9792
10419
|
}, [schema]);
|
|
10420
|
+
const initialPositions = react.useMemo(() => {
|
|
10421
|
+
if (normalizedSchema.entities.length === 0) return /* @__PURE__ */ new Map();
|
|
10422
|
+
const layout = computeDiagramLayout(normalizedSchema);
|
|
10423
|
+
const positions = /* @__PURE__ */ new Map();
|
|
10424
|
+
for (const entity of normalizedSchema.entities) {
|
|
10425
|
+
if (entity.x !== void 0 && entity.y !== void 0) {
|
|
10426
|
+
positions.set(entity.id, { x: entity.x, y: entity.y });
|
|
10427
|
+
} else {
|
|
10428
|
+
const pos = layout.get(entity.id);
|
|
10429
|
+
positions.set(entity.id, pos ?? { x: 0, y: 0 });
|
|
10430
|
+
}
|
|
10431
|
+
}
|
|
10432
|
+
return positions;
|
|
10433
|
+
}, [normalizedSchema]);
|
|
10434
|
+
const computedDefaultViewport = react.useMemo(() => {
|
|
10435
|
+
if (defaultViewport) return defaultViewport;
|
|
10436
|
+
if (initialPositions.size === 0) return { panX: 0, panY: 0, zoom: 1 };
|
|
10437
|
+
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
10438
|
+
initialPositions.forEach((pos) => {
|
|
10439
|
+
minX = Math.min(minX, pos.x);
|
|
10440
|
+
minY = Math.min(minY, pos.y);
|
|
10441
|
+
maxX = Math.max(maxX, pos.x + 220);
|
|
10442
|
+
maxY = Math.max(maxY, pos.y + 200);
|
|
10443
|
+
});
|
|
10444
|
+
const padding = 40;
|
|
10445
|
+
const panX = -minX + padding;
|
|
10446
|
+
const panY = -minY + padding;
|
|
10447
|
+
return { panX, panY, zoom: 1 };
|
|
10448
|
+
}, [defaultViewport, initialPositions]);
|
|
10449
|
+
const [entityPositions, setEntityPositions] = react.useState(initialPositions);
|
|
10450
|
+
const handleEntityMove = react.useCallback((entityId, x, y) => {
|
|
10451
|
+
setEntityPositions((prev) => {
|
|
10452
|
+
const next = new Map(prev);
|
|
10453
|
+
next.set(entityId, { x, y });
|
|
10454
|
+
return next;
|
|
10455
|
+
});
|
|
10456
|
+
}, []);
|
|
9793
10457
|
const ctx = react.useMemo(
|
|
9794
10458
|
() => ({
|
|
9795
10459
|
diagramType: type,
|
|
9796
|
-
schema:
|
|
10460
|
+
schema: normalizedSchema,
|
|
9797
10461
|
downloadableRef,
|
|
9798
10462
|
importableRef,
|
|
9799
10463
|
exportFormats,
|
|
9800
10464
|
onImport
|
|
9801
10465
|
}),
|
|
9802
|
-
[type,
|
|
10466
|
+
[type, normalizedSchema, exportFormats, onImport]
|
|
9803
10467
|
);
|
|
9804
10468
|
return /* @__PURE__ */ jsxRuntime.jsx(DiagramContext.Provider, { value: ctx, children: /* @__PURE__ */ jsxRuntime.jsx("div", { "data-react-fancy-diagram": "", className: "relative h-full w-full", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9805
10469
|
Canvas,
|
|
9806
10470
|
{
|
|
9807
10471
|
viewport,
|
|
9808
|
-
defaultViewport,
|
|
10472
|
+
defaultViewport: computedDefaultViewport,
|
|
9809
10473
|
onViewportChange,
|
|
9810
10474
|
showGrid: true,
|
|
10475
|
+
fitOnMount: true,
|
|
9811
10476
|
className: cn("h-full w-full", className),
|
|
9812
10477
|
children: [
|
|
9813
|
-
|
|
9814
|
-
|
|
9815
|
-
|
|
9816
|
-
|
|
9817
|
-
|
|
9818
|
-
|
|
9819
|
-
|
|
9820
|
-
|
|
9821
|
-
|
|
9822
|
-
|
|
9823
|
-
|
|
9824
|
-
|
|
9825
|
-
|
|
9826
|
-
|
|
9827
|
-
|
|
9828
|
-
|
|
9829
|
-
|
|
9830
|
-
|
|
9831
|
-
|
|
9832
|
-
|
|
9833
|
-
|
|
9834
|
-
|
|
10478
|
+
normalizedSchema.entities.map((entity) => {
|
|
10479
|
+
const pos = entityPositions.get(entity.id) ?? { x: 0, y: 0 };
|
|
10480
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
10481
|
+
DiagramEntity,
|
|
10482
|
+
{
|
|
10483
|
+
id: entity.id,
|
|
10484
|
+
name: entity.name,
|
|
10485
|
+
x: pos.x,
|
|
10486
|
+
y: pos.y,
|
|
10487
|
+
draggable: true,
|
|
10488
|
+
onPositionChange: (nx, ny) => handleEntityMove(entity.id, nx, ny),
|
|
10489
|
+
children: entity.fields?.map((field) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
10490
|
+
DiagramField,
|
|
10491
|
+
{
|
|
10492
|
+
name: field.name,
|
|
10493
|
+
type: field.type,
|
|
10494
|
+
primary: field.primary,
|
|
10495
|
+
foreign: field.foreign,
|
|
10496
|
+
nullable: field.nullable
|
|
10497
|
+
},
|
|
10498
|
+
field.name
|
|
10499
|
+
))
|
|
10500
|
+
},
|
|
10501
|
+
entity.id
|
|
10502
|
+
);
|
|
10503
|
+
}),
|
|
10504
|
+
normalizedSchema.relations.map((rel) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
9835
10505
|
DiagramRelation,
|
|
9836
10506
|
{
|
|
9837
10507
|
from: rel.from,
|