@andreagiugni/tailwind-dashboard-ui 0.5.14 → 0.5.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -81,6 +81,8 @@ declare const AvatarText: React.FC<AvatarTextProps>;
81
81
  interface DropdownProps extends React.HTMLAttributes<HTMLDivElement> {
82
82
  isOpen: boolean;
83
83
  onClose: () => void;
84
+ /** Render under document.body so menus are not clipped by overflow containers. Default: true. */
85
+ portal?: boolean;
84
86
  }
85
87
  declare const Dropdown: React.FC<DropdownProps>;
86
88
 
package/dist/index.d.ts CHANGED
@@ -81,6 +81,8 @@ declare const AvatarText: React.FC<AvatarTextProps>;
81
81
  interface DropdownProps extends React.HTMLAttributes<HTMLDivElement> {
82
82
  isOpen: boolean;
83
83
  onClose: () => void;
84
+ /** Render under document.body so menus are not clipped by overflow containers. Default: true. */
85
+ portal?: boolean;
84
86
  }
85
87
  declare const Dropdown: React.FC<DropdownProps>;
86
88
 
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  export { BarChart } from './chunk-YAKIMPXZ.js';
3
3
  export { LineChart } from './chunk-NWIOJGF7.js';
4
- export { Calendar, Modal } from './chunk-DBV63VHC.js';
4
+ export { Calendar, Modal } from './chunk-QGLKSM7S.js';
5
5
  export { CountryMap } from './chunk-R66LONPQ.js';
6
6
  export { Editor } from './chunk-DXUWFHPF.js';
7
7
  export { ColorPicker } from './chunk-X3OP55FG.js';
@@ -9,7 +9,8 @@ import { layers } from './chunk-VX7S6VYG.js';
9
9
  import { cn } from './chunk-ZLIYUUA4.js';
10
10
  export { cn } from './chunk-ZLIYUUA4.js';
11
11
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
12
- import React5, { useRef, useEffect, useState, useCallback, useId, useMemo } from 'react';
12
+ import React5, { useRef, useState, useEffect, useLayoutEffect, useCallback, useId, useMemo } from 'react';
13
+ import { createPortal } from 'react-dom';
13
14
  import flatpickr from 'flatpickr';
14
15
  import 'flatpickr/dist/flatpickr.css';
15
16
 
@@ -414,9 +415,13 @@ var Dropdown = ({
414
415
  onClose,
415
416
  children,
416
417
  className,
418
+ portal = true,
419
+ style,
417
420
  ...rest
418
421
  }) => {
419
422
  const dropdownRef = useRef(null);
423
+ const anchorRef = useRef(null);
424
+ const [position, setPosition] = useState();
420
425
  useEffect(() => {
421
426
  const handleClickOutside = (event) => {
422
427
  if (dropdownRef.current && !dropdownRef.current.contains(event.target) && !event.target.closest(".dropdown-toggle")) {
@@ -428,20 +433,57 @@ var Dropdown = ({
428
433
  document.removeEventListener("mousedown", handleClickOutside);
429
434
  };
430
435
  }, [onClose]);
436
+ useLayoutEffect(() => {
437
+ if (!isOpen || !portal) return;
438
+ const updatePosition = () => {
439
+ const anchor = anchorRef.current;
440
+ const menu2 = dropdownRef.current;
441
+ const trigger = anchor?.parentElement?.querySelector(".dropdown-toggle");
442
+ if (!anchor || !menu2) return;
443
+ const triggerRect = (trigger ?? anchor).getBoundingClientRect();
444
+ const menuRect = menu2.getBoundingClientRect();
445
+ const gap = 8;
446
+ const viewportPadding = 8;
447
+ const fitsBelow = triggerRect.bottom + gap + menuRect.height <= window.innerHeight - viewportPadding;
448
+ const top = fitsBelow ? triggerRect.bottom + gap : Math.max(viewportPadding, triggerRect.top - gap - menuRect.height);
449
+ const left = Math.min(
450
+ window.innerWidth - viewportPadding - menuRect.width,
451
+ Math.max(viewportPadding, triggerRect.right - menuRect.width)
452
+ );
453
+ setPosition({ top, left });
454
+ };
455
+ updatePosition();
456
+ window.addEventListener("resize", updatePosition);
457
+ window.addEventListener("scroll", updatePosition, true);
458
+ return () => {
459
+ window.removeEventListener("resize", updatePosition);
460
+ window.removeEventListener("scroll", updatePosition, true);
461
+ };
462
+ }, [isOpen, portal]);
431
463
  if (!isOpen) return null;
432
- return /* @__PURE__ */ jsx(
464
+ const menu = /* @__PURE__ */ jsx(
433
465
  "div",
434
466
  {
435
467
  ref: dropdownRef,
436
468
  className: cn(
437
- "absolute right-0 mt-2 rounded-xl border border-gray-200 bg-white shadow-theme-lg dark:border-gray-800 dark:bg-gray-dark",
438
- layers.menu,
469
+ "rounded-xl border border-gray-200 bg-white shadow-theme-lg dark:border-gray-800 dark:bg-gray-dark",
470
+ portal ? cn("fixed", layers.portal) : cn("absolute right-0 mt-2", layers.menu),
439
471
  className
440
472
  ),
473
+ style: {
474
+ ...portal && !position ? { visibility: "hidden" } : void 0,
475
+ ...portal ? position : void 0,
476
+ ...style
477
+ },
441
478
  ...rest,
442
479
  children
443
480
  }
444
481
  );
482
+ if (!portal || typeof document === "undefined") return menu;
483
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
484
+ /* @__PURE__ */ jsx("span", { ref: anchorRef, "aria-hidden": "true", className: "pointer-events-none absolute" }),
485
+ createPortal(menu, document.body)
486
+ ] });
445
487
  };
446
488
  var variantBase = "flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-sm font-medium transition";
447
489
  var variantClasses3 = {