@diwauhris/ui 1.7.38 → 1.7.40
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/lib/assets/ui.css +25 -0
- package/lib/index.cjs +94 -67
- package/lib/index.mjs +94 -67
- package/package.json +1 -1
package/lib/assets/ui.css
CHANGED
|
@@ -250,6 +250,10 @@
|
|
|
250
250
|
pointer-events: none;
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
+
.pointer-events-auto {
|
|
254
|
+
pointer-events: auto;
|
|
255
|
+
}
|
|
256
|
+
|
|
253
257
|
.\!visible {
|
|
254
258
|
visibility: visible !important;
|
|
255
259
|
}
|
|
@@ -1328,6 +1332,10 @@
|
|
|
1328
1332
|
max-width: 96px;
|
|
1329
1333
|
}
|
|
1330
1334
|
|
|
1335
|
+
.max-w-\[calc\(100vw-16px\)\] {
|
|
1336
|
+
max-width: calc(100vw - 16px);
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1331
1339
|
.max-w-lg {
|
|
1332
1340
|
max-width: 32rem;
|
|
1333
1341
|
}
|
|
@@ -2560,6 +2568,10 @@
|
|
|
2560
2568
|
background-color: rgb(0 55 123 / 0.5);
|
|
2561
2569
|
}
|
|
2562
2570
|
|
|
2571
|
+
.bg-brand-navy\/60 {
|
|
2572
|
+
background-color: rgb(0 55 123 / 0.6);
|
|
2573
|
+
}
|
|
2574
|
+
|
|
2563
2575
|
.bg-brand-navy\/\[0\.03\] {
|
|
2564
2576
|
background-color: rgb(0 55 123 / 0.03);
|
|
2565
2577
|
}
|
|
@@ -4157,6 +4169,11 @@
|
|
|
4157
4169
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
|
4158
4170
|
}
|
|
4159
4171
|
|
|
4172
|
+
.backdrop-blur {
|
|
4173
|
+
--tw-backdrop-blur: blur(8px);
|
|
4174
|
+
backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
|
|
4175
|
+
}
|
|
4176
|
+
|
|
4160
4177
|
.backdrop-blur-sm {
|
|
4161
4178
|
--tw-backdrop-blur: blur(4px);
|
|
4162
4179
|
backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
|
|
@@ -4232,6 +4249,14 @@
|
|
|
4232
4249
|
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
|
|
4233
4250
|
}
|
|
4234
4251
|
|
|
4252
|
+
.will-change-\[opacity\] {
|
|
4253
|
+
will-change: opacity;
|
|
4254
|
+
}
|
|
4255
|
+
|
|
4256
|
+
.will-change-\[transform\2c opacity\] {
|
|
4257
|
+
will-change: transform,opacity;
|
|
4258
|
+
}
|
|
4259
|
+
|
|
4235
4260
|
@keyframes enter {
|
|
4236
4261
|
from {
|
|
4237
4262
|
opacity: var(--tw-enter-opacity, 1);
|
package/lib/index.cjs
CHANGED
|
@@ -2462,73 +2462,76 @@ function Modal({ isOpen, onClose, title, children, icon, subtitle, headerMeta, f
|
|
|
2462
2462
|
onOpenChange: (isOpen) => {
|
|
2463
2463
|
if (!isOpen && !preventClose) onClose();
|
|
2464
2464
|
},
|
|
2465
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_radix_ui_react_dialog.Portal, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dialog.Overlay, { className: "fixed inset-0 z-50 bg-brand-navy/
|
|
2466
|
-
className:
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
"
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2465
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_radix_ui_react_dialog.Portal, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dialog.Overlay, { className: "fixed inset-0 z-50 bg-brand-navy/60 will-change-[opacity] data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0 duration-150 ease-out" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2466
|
+
className: "pointer-events-none fixed inset-0 z-50 flex items-center justify-center p-4",
|
|
2467
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_radix_ui_react_dialog.Content, {
|
|
2468
|
+
className: cn("pointer-events-auto relative", "flex w-full flex-col", "rounded-lg border border-slate-200 bg-white shadow-xl", "max-h-[85vh] outline-none", maxWidth, "will-change-[transform,opacity]", "data-[state=open]:animate-in data-[state=closed]:animate-out", "data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0", "data-[state=open]:zoom-in-95 data-[state=closed]:zoom-out-95", "duration-150 ease-out"),
|
|
2469
|
+
style: { padding: 0 },
|
|
2470
|
+
onOpenAutoFocus,
|
|
2471
|
+
onCloseAutoFocus,
|
|
2472
|
+
onEscapeKeyDown: preventClose ? (e) => e.preventDefault() : onEscapeKeyDown,
|
|
2473
|
+
onInteractOutside: (e) => {
|
|
2474
|
+
if (e.target?.closest(".pis-datepicker-popover")) {
|
|
2475
|
+
e.preventDefault();
|
|
2476
|
+
return;
|
|
2477
|
+
}
|
|
2478
|
+
if (preventClose) {
|
|
2479
|
+
e.preventDefault();
|
|
2480
|
+
return;
|
|
2481
|
+
}
|
|
2482
|
+
onInteractOutside?.(e);
|
|
2483
|
+
},
|
|
2484
|
+
children: [
|
|
2485
|
+
!preventClose && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dialog.Close, {
|
|
2486
|
+
asChild: true,
|
|
2487
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2488
|
+
type: "button",
|
|
2489
|
+
"aria-label": closeLabel,
|
|
2490
|
+
className: "absolute right-4 top-4 rounded-lg p-1.5 text-slate-400 hover:bg-slate-100 hover:text-slate-600 transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-blue/30",
|
|
2491
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.X, {
|
|
2492
|
+
size: 16,
|
|
2493
|
+
"aria-hidden": "true"
|
|
2494
|
+
})
|
|
2492
2495
|
})
|
|
2493
|
-
})
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
children:
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
})
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
})
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2496
|
+
}),
|
|
2497
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2498
|
+
className: "px-6 pt-6 pb-4 border-b-2 border-slate-100",
|
|
2499
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2500
|
+
className: "flex items-center gap-2.5",
|
|
2501
|
+
children: [icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2502
|
+
className: iconBadgeClass,
|
|
2503
|
+
children: icon
|
|
2504
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dialog.Title, {
|
|
2505
|
+
className: cn(typography.titleOverlay, danger ? "text-rose-700" : "text-slate-900"),
|
|
2506
|
+
children: title
|
|
2507
|
+
}), subtitle && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dialog.Description, {
|
|
2508
|
+
className: "text-xs text-slate-500 mt-0.5",
|
|
2509
|
+
children: subtitle
|
|
2510
|
+
})] })]
|
|
2511
|
+
}), headerMeta && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2512
|
+
className: "mt-2",
|
|
2513
|
+
children: headerMeta
|
|
2514
|
+
})]
|
|
2515
|
+
}),
|
|
2516
|
+
onSubmit ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
|
|
2517
|
+
onSubmit,
|
|
2518
|
+
className: "flex flex-col min-h-0 flex-1",
|
|
2519
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2520
|
+
className: "flex-1 overflow-y-auto px-6 py-5",
|
|
2521
|
+
children: bodyContent
|
|
2522
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2523
|
+
className: "px-6 py-4 border-t border-slate-100",
|
|
2524
|
+
children: resolvedFooter
|
|
2525
|
+
})]
|
|
2526
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2518
2527
|
className: "flex-1 overflow-y-auto px-6 py-5",
|
|
2519
2528
|
children: bodyContent
|
|
2520
2529
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2521
2530
|
className: "px-6 py-4 border-t border-slate-100",
|
|
2522
2531
|
children: resolvedFooter
|
|
2523
|
-
})]
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
children: bodyContent
|
|
2527
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2528
|
-
className: "px-6 py-4 border-t border-slate-100",
|
|
2529
|
-
children: resolvedFooter
|
|
2530
|
-
})] })
|
|
2531
|
-
]
|
|
2532
|
+
})] })
|
|
2533
|
+
]
|
|
2534
|
+
})
|
|
2532
2535
|
})] })
|
|
2533
2536
|
});
|
|
2534
2537
|
}
|
|
@@ -3989,26 +3992,44 @@ function SidebarItem({ href, onClick, active = false, icon, badge, disabled = fa
|
|
|
3989
3992
|
*/
|
|
3990
3993
|
function Dropdown({ trigger, isOpen, onToggle, onClose, children, triggerClassName = "", panelClassName = "" }) {
|
|
3991
3994
|
const ref = (0, react.useRef)(null);
|
|
3995
|
+
const panelRef = (0, react.useRef)(null);
|
|
3992
3996
|
const triggerRef = (0, react.useRef)(null);
|
|
3993
3997
|
const panelId = `${(0, react.useId)().replace(/:/g, "")}-panel`;
|
|
3994
3998
|
const [panelStyle, setPanelStyle] = (0, react.useState)({});
|
|
3999
|
+
const [positioned, setPositioned] = (0, react.useState)(false);
|
|
3995
4000
|
(0, react.useEffect)(() => {
|
|
3996
|
-
if (!isOpen || !triggerRef.current)
|
|
4001
|
+
if (!isOpen || !triggerRef.current) {
|
|
4002
|
+
setPositioned(false);
|
|
4003
|
+
return;
|
|
4004
|
+
}
|
|
4005
|
+
const GAP = 4;
|
|
4006
|
+
const MARGIN = 8;
|
|
3997
4007
|
const updatePosition = () => {
|
|
3998
4008
|
if (!triggerRef.current) return;
|
|
3999
4009
|
const rect = triggerRef.current.getBoundingClientRect();
|
|
4010
|
+
const panelHeight = panelRef.current?.offsetHeight ?? 280;
|
|
4011
|
+
const panelWidth = panelRef.current?.offsetWidth ?? Math.max(rect.width, 180);
|
|
4012
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
4013
|
+
const spaceAbove = rect.top;
|
|
4014
|
+
const top = spaceBelow >= panelHeight + GAP + MARGIN || spaceBelow >= spaceAbove ? Math.min(rect.bottom + GAP, window.innerHeight - panelHeight - MARGIN) : Math.max(rect.top - panelHeight - GAP, MARGIN);
|
|
4015
|
+
const left = Math.max(MARGIN, Math.min(rect.left, window.innerWidth - panelWidth - MARGIN));
|
|
4000
4016
|
setPanelStyle({
|
|
4001
4017
|
position: "fixed",
|
|
4002
|
-
top:
|
|
4003
|
-
left
|
|
4004
|
-
zIndex:
|
|
4018
|
+
top: Math.max(MARGIN, top),
|
|
4019
|
+
left,
|
|
4020
|
+
zIndex: 1e3,
|
|
4005
4021
|
minWidth: Math.max(rect.width, 180)
|
|
4006
4022
|
});
|
|
4007
4023
|
};
|
|
4008
4024
|
updatePosition();
|
|
4025
|
+
const raf = requestAnimationFrame(() => {
|
|
4026
|
+
updatePosition();
|
|
4027
|
+
setPositioned(true);
|
|
4028
|
+
});
|
|
4009
4029
|
window.addEventListener("scroll", updatePosition, true);
|
|
4010
4030
|
window.addEventListener("resize", updatePosition);
|
|
4011
4031
|
return () => {
|
|
4032
|
+
cancelAnimationFrame(raf);
|
|
4012
4033
|
window.removeEventListener("scroll", updatePosition, true);
|
|
4013
4034
|
window.removeEventListener("resize", updatePosition);
|
|
4014
4035
|
};
|
|
@@ -4017,6 +4038,8 @@ function Dropdown({ trigger, isOpen, onToggle, onClose, children, triggerClassNa
|
|
|
4017
4038
|
if (!isOpen) return;
|
|
4018
4039
|
const handlePointerDown = (e) => {
|
|
4019
4040
|
const target = e.target;
|
|
4041
|
+
if (panelRef.current?.contains(target)) return;
|
|
4042
|
+
if (target.closest?.(".pis-datepicker-popover")) return;
|
|
4020
4043
|
if (ref.current && !ref.current.contains(target)) {
|
|
4021
4044
|
onClose();
|
|
4022
4045
|
triggerRef.current?.focus();
|
|
@@ -4051,8 +4074,12 @@ function Dropdown({ trigger, isOpen, onToggle, onClose, children, triggerClassNa
|
|
|
4051
4074
|
children: trigger
|
|
4052
4075
|
}), isOpen && (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4053
4076
|
id: panelId,
|
|
4054
|
-
|
|
4055
|
-
|
|
4077
|
+
ref: panelRef,
|
|
4078
|
+
style: {
|
|
4079
|
+
...panelStyle,
|
|
4080
|
+
visibility: positioned ? "visible" : "hidden"
|
|
4081
|
+
},
|
|
4082
|
+
className: cn("w-max max-w-[calc(100vw-16px)] max-h-[280px] overflow-y-auto", "rounded-xl border border-slate-200 bg-white shadow-lg", panelClassName),
|
|
4056
4083
|
children
|
|
4057
4084
|
}), document.body)]
|
|
4058
4085
|
});
|
package/lib/index.mjs
CHANGED
|
@@ -2438,73 +2438,76 @@ function Modal({ isOpen, onClose, title, children, icon, subtitle, headerMeta, f
|
|
|
2438
2438
|
onOpenChange: (isOpen) => {
|
|
2439
2439
|
if (!isOpen && !preventClose) onClose();
|
|
2440
2440
|
},
|
|
2441
|
-
children: /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { children: [/* @__PURE__ */ jsx(DialogPrimitive.Overlay, { className: "fixed inset-0 z-50 bg-brand-navy/
|
|
2442
|
-
className:
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
"
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2441
|
+
children: /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { children: [/* @__PURE__ */ jsx(DialogPrimitive.Overlay, { className: "fixed inset-0 z-50 bg-brand-navy/60 will-change-[opacity] data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0 duration-150 ease-out" }), /* @__PURE__ */ jsx("div", {
|
|
2442
|
+
className: "pointer-events-none fixed inset-0 z-50 flex items-center justify-center p-4",
|
|
2443
|
+
children: /* @__PURE__ */ jsxs(DialogPrimitive.Content, {
|
|
2444
|
+
className: cn("pointer-events-auto relative", "flex w-full flex-col", "rounded-lg border border-slate-200 bg-white shadow-xl", "max-h-[85vh] outline-none", maxWidth, "will-change-[transform,opacity]", "data-[state=open]:animate-in data-[state=closed]:animate-out", "data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0", "data-[state=open]:zoom-in-95 data-[state=closed]:zoom-out-95", "duration-150 ease-out"),
|
|
2445
|
+
style: { padding: 0 },
|
|
2446
|
+
onOpenAutoFocus,
|
|
2447
|
+
onCloseAutoFocus,
|
|
2448
|
+
onEscapeKeyDown: preventClose ? (e) => e.preventDefault() : onEscapeKeyDown,
|
|
2449
|
+
onInteractOutside: (e) => {
|
|
2450
|
+
if (e.target?.closest(".pis-datepicker-popover")) {
|
|
2451
|
+
e.preventDefault();
|
|
2452
|
+
return;
|
|
2453
|
+
}
|
|
2454
|
+
if (preventClose) {
|
|
2455
|
+
e.preventDefault();
|
|
2456
|
+
return;
|
|
2457
|
+
}
|
|
2458
|
+
onInteractOutside?.(e);
|
|
2459
|
+
},
|
|
2460
|
+
children: [
|
|
2461
|
+
!preventClose && /* @__PURE__ */ jsx(DialogPrimitive.Close, {
|
|
2462
|
+
asChild: true,
|
|
2463
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
2464
|
+
type: "button",
|
|
2465
|
+
"aria-label": closeLabel,
|
|
2466
|
+
className: "absolute right-4 top-4 rounded-lg p-1.5 text-slate-400 hover:bg-slate-100 hover:text-slate-600 transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-blue/30",
|
|
2467
|
+
children: /* @__PURE__ */ jsx(X, {
|
|
2468
|
+
size: 16,
|
|
2469
|
+
"aria-hidden": "true"
|
|
2470
|
+
})
|
|
2468
2471
|
})
|
|
2469
|
-
})
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
children:
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
})
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
})
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2472
|
+
}),
|
|
2473
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2474
|
+
className: "px-6 pt-6 pb-4 border-b-2 border-slate-100",
|
|
2475
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
2476
|
+
className: "flex items-center gap-2.5",
|
|
2477
|
+
children: [icon && /* @__PURE__ */ jsx("div", {
|
|
2478
|
+
className: iconBadgeClass,
|
|
2479
|
+
children: icon
|
|
2480
|
+
}), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(DialogPrimitive.Title, {
|
|
2481
|
+
className: cn(typography.titleOverlay, danger ? "text-rose-700" : "text-slate-900"),
|
|
2482
|
+
children: title
|
|
2483
|
+
}), subtitle && /* @__PURE__ */ jsx(DialogPrimitive.Description, {
|
|
2484
|
+
className: "text-xs text-slate-500 mt-0.5",
|
|
2485
|
+
children: subtitle
|
|
2486
|
+
})] })]
|
|
2487
|
+
}), headerMeta && /* @__PURE__ */ jsx("div", {
|
|
2488
|
+
className: "mt-2",
|
|
2489
|
+
children: headerMeta
|
|
2490
|
+
})]
|
|
2491
|
+
}),
|
|
2492
|
+
onSubmit ? /* @__PURE__ */ jsxs("form", {
|
|
2493
|
+
onSubmit,
|
|
2494
|
+
className: "flex flex-col min-h-0 flex-1",
|
|
2495
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
2496
|
+
className: "flex-1 overflow-y-auto px-6 py-5",
|
|
2497
|
+
children: bodyContent
|
|
2498
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
2499
|
+
className: "px-6 py-4 border-t border-slate-100",
|
|
2500
|
+
children: resolvedFooter
|
|
2501
|
+
})]
|
|
2502
|
+
}) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
|
|
2494
2503
|
className: "flex-1 overflow-y-auto px-6 py-5",
|
|
2495
2504
|
children: bodyContent
|
|
2496
2505
|
}), /* @__PURE__ */ jsx("div", {
|
|
2497
2506
|
className: "px-6 py-4 border-t border-slate-100",
|
|
2498
2507
|
children: resolvedFooter
|
|
2499
|
-
})]
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
children: bodyContent
|
|
2503
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
2504
|
-
className: "px-6 py-4 border-t border-slate-100",
|
|
2505
|
-
children: resolvedFooter
|
|
2506
|
-
})] })
|
|
2507
|
-
]
|
|
2508
|
+
})] })
|
|
2509
|
+
]
|
|
2510
|
+
})
|
|
2508
2511
|
})] })
|
|
2509
2512
|
});
|
|
2510
2513
|
}
|
|
@@ -3965,26 +3968,44 @@ function SidebarItem({ href, onClick, active = false, icon, badge, disabled = fa
|
|
|
3965
3968
|
*/
|
|
3966
3969
|
function Dropdown({ trigger, isOpen, onToggle, onClose, children, triggerClassName = "", panelClassName = "" }) {
|
|
3967
3970
|
const ref = useRef(null);
|
|
3971
|
+
const panelRef = useRef(null);
|
|
3968
3972
|
const triggerRef = useRef(null);
|
|
3969
3973
|
const panelId = `${useId().replace(/:/g, "")}-panel`;
|
|
3970
3974
|
const [panelStyle, setPanelStyle] = useState({});
|
|
3975
|
+
const [positioned, setPositioned] = useState(false);
|
|
3971
3976
|
useEffect(() => {
|
|
3972
|
-
if (!isOpen || !triggerRef.current)
|
|
3977
|
+
if (!isOpen || !triggerRef.current) {
|
|
3978
|
+
setPositioned(false);
|
|
3979
|
+
return;
|
|
3980
|
+
}
|
|
3981
|
+
const GAP = 4;
|
|
3982
|
+
const MARGIN = 8;
|
|
3973
3983
|
const updatePosition = () => {
|
|
3974
3984
|
if (!triggerRef.current) return;
|
|
3975
3985
|
const rect = triggerRef.current.getBoundingClientRect();
|
|
3986
|
+
const panelHeight = panelRef.current?.offsetHeight ?? 280;
|
|
3987
|
+
const panelWidth = panelRef.current?.offsetWidth ?? Math.max(rect.width, 180);
|
|
3988
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
3989
|
+
const spaceAbove = rect.top;
|
|
3990
|
+
const top = spaceBelow >= panelHeight + GAP + MARGIN || spaceBelow >= spaceAbove ? Math.min(rect.bottom + GAP, window.innerHeight - panelHeight - MARGIN) : Math.max(rect.top - panelHeight - GAP, MARGIN);
|
|
3991
|
+
const left = Math.max(MARGIN, Math.min(rect.left, window.innerWidth - panelWidth - MARGIN));
|
|
3976
3992
|
setPanelStyle({
|
|
3977
3993
|
position: "fixed",
|
|
3978
|
-
top:
|
|
3979
|
-
left
|
|
3980
|
-
zIndex:
|
|
3994
|
+
top: Math.max(MARGIN, top),
|
|
3995
|
+
left,
|
|
3996
|
+
zIndex: 1e3,
|
|
3981
3997
|
minWidth: Math.max(rect.width, 180)
|
|
3982
3998
|
});
|
|
3983
3999
|
};
|
|
3984
4000
|
updatePosition();
|
|
4001
|
+
const raf = requestAnimationFrame(() => {
|
|
4002
|
+
updatePosition();
|
|
4003
|
+
setPositioned(true);
|
|
4004
|
+
});
|
|
3985
4005
|
window.addEventListener("scroll", updatePosition, true);
|
|
3986
4006
|
window.addEventListener("resize", updatePosition);
|
|
3987
4007
|
return () => {
|
|
4008
|
+
cancelAnimationFrame(raf);
|
|
3988
4009
|
window.removeEventListener("scroll", updatePosition, true);
|
|
3989
4010
|
window.removeEventListener("resize", updatePosition);
|
|
3990
4011
|
};
|
|
@@ -3993,6 +4014,8 @@ function Dropdown({ trigger, isOpen, onToggle, onClose, children, triggerClassNa
|
|
|
3993
4014
|
if (!isOpen) return;
|
|
3994
4015
|
const handlePointerDown = (e) => {
|
|
3995
4016
|
const target = e.target;
|
|
4017
|
+
if (panelRef.current?.contains(target)) return;
|
|
4018
|
+
if (target.closest?.(".pis-datepicker-popover")) return;
|
|
3996
4019
|
if (ref.current && !ref.current.contains(target)) {
|
|
3997
4020
|
onClose();
|
|
3998
4021
|
triggerRef.current?.focus();
|
|
@@ -4027,8 +4050,12 @@ function Dropdown({ trigger, isOpen, onToggle, onClose, children, triggerClassNa
|
|
|
4027
4050
|
children: trigger
|
|
4028
4051
|
}), isOpen && createPortal(/* @__PURE__ */ jsx("div", {
|
|
4029
4052
|
id: panelId,
|
|
4030
|
-
|
|
4031
|
-
|
|
4053
|
+
ref: panelRef,
|
|
4054
|
+
style: {
|
|
4055
|
+
...panelStyle,
|
|
4056
|
+
visibility: positioned ? "visible" : "hidden"
|
|
4057
|
+
},
|
|
4058
|
+
className: cn("w-max max-w-[calc(100vw-16px)] max-h-[280px] overflow-y-auto", "rounded-xl border border-slate-200 bg-white shadow-lg", panelClassName),
|
|
4032
4059
|
children
|
|
4033
4060
|
}), document.body)]
|
|
4034
4061
|
});
|