@andreagiugni/tailwind-dashboard-ui 0.5.15 → 0.5.17
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 +2 -2
- package/dist/index.cjs +112 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +113 -18
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
@@ -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,
|
|
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
|
-
|
|
464
|
+
const menu = /* @__PURE__ */ jsx(
|
|
433
465
|
"div",
|
|
434
466
|
{
|
|
435
467
|
ref: dropdownRef,
|
|
436
468
|
className: cn(
|
|
437
|
-
"
|
|
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 = {
|
|
@@ -691,15 +733,63 @@ var alignClass = {
|
|
|
691
733
|
right: "text-right"
|
|
692
734
|
};
|
|
693
735
|
function SortIcon({
|
|
694
|
-
|
|
695
|
-
direction
|
|
736
|
+
state
|
|
696
737
|
}) {
|
|
697
|
-
const
|
|
698
|
-
const
|
|
699
|
-
return /* @__PURE__ */ jsxs(
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
738
|
+
const active = "text-brand-500";
|
|
739
|
+
const inactive = "text-gray-400 dark:text-gray-500";
|
|
740
|
+
return /* @__PURE__ */ jsxs(
|
|
741
|
+
"span",
|
|
742
|
+
{
|
|
743
|
+
"data-sort-state": state,
|
|
744
|
+
className: "inline-flex shrink-0 flex-col items-center -space-y-1",
|
|
745
|
+
children: [
|
|
746
|
+
/* @__PURE__ */ jsx(
|
|
747
|
+
"svg",
|
|
748
|
+
{
|
|
749
|
+
"data-sort-direction": "asc",
|
|
750
|
+
width: "12",
|
|
751
|
+
height: "12",
|
|
752
|
+
viewBox: "0 0 12 12",
|
|
753
|
+
fill: "none",
|
|
754
|
+
"aria-hidden": "true",
|
|
755
|
+
className: state === "asc" ? active : inactive,
|
|
756
|
+
children: /* @__PURE__ */ jsx(
|
|
757
|
+
"path",
|
|
758
|
+
{
|
|
759
|
+
d: "M3.5 7.25 6 4.75l2.5 2.5",
|
|
760
|
+
stroke: "currentColor",
|
|
761
|
+
strokeWidth: "1.5",
|
|
762
|
+
strokeLinecap: "round",
|
|
763
|
+
strokeLinejoin: "round"
|
|
764
|
+
}
|
|
765
|
+
)
|
|
766
|
+
}
|
|
767
|
+
),
|
|
768
|
+
/* @__PURE__ */ jsx(
|
|
769
|
+
"svg",
|
|
770
|
+
{
|
|
771
|
+
"data-sort-direction": "desc",
|
|
772
|
+
width: "12",
|
|
773
|
+
height: "12",
|
|
774
|
+
viewBox: "0 0 12 12",
|
|
775
|
+
fill: "none",
|
|
776
|
+
"aria-hidden": "true",
|
|
777
|
+
className: state === "desc" ? active : inactive,
|
|
778
|
+
children: /* @__PURE__ */ jsx(
|
|
779
|
+
"path",
|
|
780
|
+
{
|
|
781
|
+
d: "m3.5 4.75 2.5 2.5 2.5-2.5",
|
|
782
|
+
stroke: "currentColor",
|
|
783
|
+
strokeWidth: "1.5",
|
|
784
|
+
strokeLinecap: "round",
|
|
785
|
+
strokeLinejoin: "round"
|
|
786
|
+
}
|
|
787
|
+
)
|
|
788
|
+
}
|
|
789
|
+
)
|
|
790
|
+
]
|
|
791
|
+
}
|
|
792
|
+
);
|
|
703
793
|
}
|
|
704
794
|
function DataDrivenTable({
|
|
705
795
|
data,
|
|
@@ -749,10 +839,14 @@ function DataDrivenTable({
|
|
|
749
839
|
const pageRows = pagination ? filtered.slice(start, start + pageSize) : filtered;
|
|
750
840
|
const toggleSort = (col) => {
|
|
751
841
|
if (!col.sortable) return;
|
|
752
|
-
if (sortKey
|
|
753
|
-
else {
|
|
842
|
+
if (sortKey !== col.key) {
|
|
754
843
|
setSortKey(col.key);
|
|
755
844
|
setSortDir("asc");
|
|
845
|
+
} else if (sortDir === "asc") {
|
|
846
|
+
setSortDir("desc");
|
|
847
|
+
} else {
|
|
848
|
+
setSortKey(void 0);
|
|
849
|
+
setSortDir("asc");
|
|
756
850
|
}
|
|
757
851
|
setPage(1);
|
|
758
852
|
};
|
|
@@ -830,8 +924,9 @@ function DataDrivenTable({
|
|
|
830
924
|
TableCell,
|
|
831
925
|
{
|
|
832
926
|
isHeader: true,
|
|
927
|
+
"aria-sort": col.sortable ? isActive ? sortDir === "asc" ? "ascending" : "descending" : "none" : void 0,
|
|
833
928
|
className: cn(
|
|
834
|
-
"whitespace-nowrap px-5 py-3 text-xs font-semibold text-gray-
|
|
929
|
+
"whitespace-nowrap px-5 py-3 text-xs font-semibold text-gray-500 dark:text-gray-400",
|
|
835
930
|
alignClass[col.align ?? "left"],
|
|
836
931
|
col.className
|
|
837
932
|
),
|
|
@@ -841,10 +936,10 @@ function DataDrivenTable({
|
|
|
841
936
|
type: "button",
|
|
842
937
|
onClick: () => toggleSort(col),
|
|
843
938
|
"aria-label": `Sort by ${typeof col.header === "string" ? col.header : col.key}`,
|
|
844
|
-
className: "inline-flex select-none items-center gap-
|
|
939
|
+
className: "inline-flex select-none items-center gap-2 text-gray-500 transition-colors hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200",
|
|
845
940
|
children: [
|
|
846
|
-
|
|
847
|
-
|
|
941
|
+
/* @__PURE__ */ jsx(SortIcon, { state: isActive ? sortDir : "none" }),
|
|
942
|
+
col.header
|
|
848
943
|
]
|
|
849
944
|
}
|
|
850
945
|
) : col.header
|