@eztrak/shared 0.5.0 → 0.6.1
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/{chunk-AGKS3RRK.mjs → chunk-ET7TMD3D.mjs} +159 -6
- package/dist/chunk-ET7TMD3D.mjs.map +1 -0
- package/dist/components/index.d.mts +24 -2
- package/dist/components/index.d.ts +24 -2
- package/dist/components/index.js +158 -4
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +3 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +158 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -1
- package/package.json +6 -1
- package/dist/chunk-AGKS3RRK.mjs.map +0 -1
|
@@ -534,6 +534,16 @@ function CustomPagination({
|
|
|
534
534
|
// src/components/search-filters/ResetFiltersButton.tsx
|
|
535
535
|
import { useSearchParams as useSearchParams2 } from "react-router-dom";
|
|
536
536
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
537
|
+
var BASE_STYLES = "inline-flex items-center gap-1.5 px-5 py-3 rounded-md text-sm font-medium transition-colors duration-200 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50";
|
|
538
|
+
var VARIANTS = {
|
|
539
|
+
primary: "bg-white text-secondary border border-secondary hover:bg-lightGray hover:text-black",
|
|
540
|
+
"primary-outline": "bg-white text-primary-150 border border-primary-150 font-bold hover:bg-primary-100 hover:text-white",
|
|
541
|
+
"primary-fill": "bg-primary-150 text-white border border-primary-150 hover:bg-primary/90",
|
|
542
|
+
secondary: "bg-primary-150 text-white border border-primary-150 hover:bg-primary/90",
|
|
543
|
+
danger: "bg-red-600 text-white border border-red-600 hover:bg-red-700",
|
|
544
|
+
outline: "bg-white text-primary border border-primary hover:bg-primary/10",
|
|
545
|
+
ghost: "bg-transparent text-secondary border border-transparent hover:bg-primary/10"
|
|
546
|
+
};
|
|
537
547
|
function ResetIcon({
|
|
538
548
|
size = 16,
|
|
539
549
|
className
|
|
@@ -563,6 +573,7 @@ function ResetIcon({
|
|
|
563
573
|
function ResetFiltersButton({
|
|
564
574
|
label = "Reset Filters",
|
|
565
575
|
icon,
|
|
576
|
+
variant = "primary-outline",
|
|
566
577
|
className,
|
|
567
578
|
onReset,
|
|
568
579
|
disabled = false
|
|
@@ -579,10 +590,7 @@ function ResetFiltersButton({
|
|
|
579
590
|
type: "button",
|
|
580
591
|
onClick: handleReset,
|
|
581
592
|
disabled,
|
|
582
|
-
className: cn(
|
|
583
|
-
"inline-flex items-center gap-1.5 rounded-xl border border-primary-150 bg-white px-3 py-1.5 text-sm font-medium text-primary-150 hover:bg-gray-50 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-white",
|
|
584
|
-
className
|
|
585
|
-
),
|
|
593
|
+
className: cn(BASE_STYLES, VARIANTS[variant], className),
|
|
586
594
|
children: [
|
|
587
595
|
resolvedIcon,
|
|
588
596
|
label
|
|
@@ -591,11 +599,156 @@ function ResetFiltersButton({
|
|
|
591
599
|
);
|
|
592
600
|
}
|
|
593
601
|
|
|
602
|
+
// src/components/modal/Modal.tsx
|
|
603
|
+
import { AnimatePresence, motion } from "framer-motion";
|
|
604
|
+
import { useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
605
|
+
import { createPortal } from "react-dom";
|
|
606
|
+
import { FaFileExport, FaPrint } from "react-icons/fa";
|
|
607
|
+
import { IoCloseCircleOutline } from "react-icons/io5";
|
|
608
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
609
|
+
function Modal({
|
|
610
|
+
isOpen,
|
|
611
|
+
onClose,
|
|
612
|
+
title,
|
|
613
|
+
children,
|
|
614
|
+
footer,
|
|
615
|
+
className = "w-2/3",
|
|
616
|
+
width,
|
|
617
|
+
onPrint,
|
|
618
|
+
onExport,
|
|
619
|
+
modalBodyClassName,
|
|
620
|
+
modalBodyWrapperClass,
|
|
621
|
+
closeOnBackdropClick = false,
|
|
622
|
+
closeOnEscape = true,
|
|
623
|
+
zIndex = 1e3
|
|
624
|
+
}) {
|
|
625
|
+
const modalRef = useRef2(null);
|
|
626
|
+
const handleBackdropClick = (e) => {
|
|
627
|
+
if (e.target === e.currentTarget && closeOnBackdropClick) {
|
|
628
|
+
onClose();
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
useEffect2(() => {
|
|
632
|
+
const handleEscape = (e) => {
|
|
633
|
+
if (e.key === "Escape" && isOpen && closeOnEscape) {
|
|
634
|
+
onClose();
|
|
635
|
+
}
|
|
636
|
+
};
|
|
637
|
+
if (isOpen) {
|
|
638
|
+
document.addEventListener("keydown", handleEscape);
|
|
639
|
+
document.body.style.overflow = "hidden";
|
|
640
|
+
}
|
|
641
|
+
return () => {
|
|
642
|
+
document.removeEventListener("keydown", handleEscape);
|
|
643
|
+
document.body.style.overflow = "unset";
|
|
644
|
+
};
|
|
645
|
+
}, [isOpen, onClose, closeOnEscape]);
|
|
646
|
+
const modalContent = /* @__PURE__ */ jsx4(AnimatePresence, { children: isOpen && /* @__PURE__ */ jsx4(
|
|
647
|
+
"div",
|
|
648
|
+
{
|
|
649
|
+
className: "fixed inset-0 bg-gray-500 bg-opacity-50 flex justify-center items-center p-4",
|
|
650
|
+
onClick: handleBackdropClick,
|
|
651
|
+
style: {
|
|
652
|
+
position: "fixed",
|
|
653
|
+
top: 0,
|
|
654
|
+
left: 0,
|
|
655
|
+
right: 0,
|
|
656
|
+
bottom: 0,
|
|
657
|
+
width: "100vw",
|
|
658
|
+
height: "100vh",
|
|
659
|
+
margin: 0,
|
|
660
|
+
padding: "1rem",
|
|
661
|
+
zIndex
|
|
662
|
+
},
|
|
663
|
+
children: /* @__PURE__ */ jsxs4(
|
|
664
|
+
motion.div,
|
|
665
|
+
{
|
|
666
|
+
ref: modalRef,
|
|
667
|
+
initial: { y: "-100vh", opacity: 0 },
|
|
668
|
+
animate: { y: 0, opacity: 1 },
|
|
669
|
+
exit: { y: "100vh", opacity: 0 },
|
|
670
|
+
transition: { duration: 0.3 },
|
|
671
|
+
className: cn(
|
|
672
|
+
"bg-white rounded-3xl shadow-lg max-h-[90vh] flex flex-col mx-auto",
|
|
673
|
+
className,
|
|
674
|
+
width
|
|
675
|
+
),
|
|
676
|
+
onClick: (e) => e.stopPropagation(),
|
|
677
|
+
style: {
|
|
678
|
+
maxWidth: "95vw",
|
|
679
|
+
maxHeight: "90vh"
|
|
680
|
+
},
|
|
681
|
+
children: [
|
|
682
|
+
/* @__PURE__ */ jsxs4("div", { className: "sticky top-0 z-10 flex justify-between items-center bg-white text-2xl p-8 pb-4 rounded-t-3xl", children: [
|
|
683
|
+
/* @__PURE__ */ jsx4("h2", { className: "font-semibold", children: title }),
|
|
684
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex items-center space-x-4", children: [
|
|
685
|
+
onPrint && /* @__PURE__ */ jsxs4(
|
|
686
|
+
"button",
|
|
687
|
+
{
|
|
688
|
+
type: "button",
|
|
689
|
+
onClick: onPrint,
|
|
690
|
+
className: "flex items-center gap-1 hover:text-gray-300 text-sm border p-1 rounded",
|
|
691
|
+
children: [
|
|
692
|
+
/* @__PURE__ */ jsx4(FaPrint, {}),
|
|
693
|
+
/* @__PURE__ */ jsx4("span", { children: "Print" })
|
|
694
|
+
]
|
|
695
|
+
}
|
|
696
|
+
),
|
|
697
|
+
onExport && /* @__PURE__ */ jsxs4(
|
|
698
|
+
"button",
|
|
699
|
+
{
|
|
700
|
+
type: "button",
|
|
701
|
+
onClick: onExport,
|
|
702
|
+
className: "flex items-center gap-1 hover:text-gray-300 text-sm border p-1 rounded",
|
|
703
|
+
children: [
|
|
704
|
+
/* @__PURE__ */ jsx4(FaFileExport, {}),
|
|
705
|
+
/* @__PURE__ */ jsx4("span", { children: "Export" })
|
|
706
|
+
]
|
|
707
|
+
}
|
|
708
|
+
),
|
|
709
|
+
/* @__PURE__ */ jsx4(
|
|
710
|
+
"button",
|
|
711
|
+
{
|
|
712
|
+
type: "button",
|
|
713
|
+
onClick: onClose,
|
|
714
|
+
className: "px-2 hover:opacity-70 transition-opacity",
|
|
715
|
+
children: /* @__PURE__ */ jsx4(IoCloseCircleOutline, { color: "#8898AA", size: 25 })
|
|
716
|
+
}
|
|
717
|
+
)
|
|
718
|
+
] })
|
|
719
|
+
] }),
|
|
720
|
+
/* @__PURE__ */ jsx4(
|
|
721
|
+
"div",
|
|
722
|
+
{
|
|
723
|
+
className: cn(
|
|
724
|
+
"overflow-y-auto px-8 pb-8 flex-grow scroll",
|
|
725
|
+
modalBodyWrapperClass,
|
|
726
|
+
modalBodyClassName
|
|
727
|
+
),
|
|
728
|
+
children
|
|
729
|
+
}
|
|
730
|
+
),
|
|
731
|
+
footer && /* @__PURE__ */ jsx4("div", { className: "sticky bottom-0 flex justify-end p-4 space-x-4 border-t bg-white rounded-b-3xl", children: footer })
|
|
732
|
+
]
|
|
733
|
+
}
|
|
734
|
+
)
|
|
735
|
+
}
|
|
736
|
+
) });
|
|
737
|
+
let modalRoot = document.getElementById("modal-root");
|
|
738
|
+
if (!modalRoot) {
|
|
739
|
+
modalRoot = document.createElement("div");
|
|
740
|
+
modalRoot.id = "modal-root";
|
|
741
|
+
document.body.appendChild(modalRoot);
|
|
742
|
+
}
|
|
743
|
+
return createPortal(modalContent, modalRoot);
|
|
744
|
+
}
|
|
745
|
+
|
|
594
746
|
export {
|
|
595
747
|
EztrakTabs,
|
|
596
748
|
ResetColumnsButton,
|
|
597
749
|
TableLayoutToolbarControls,
|
|
598
750
|
CustomPagination,
|
|
599
|
-
ResetFiltersButton
|
|
751
|
+
ResetFiltersButton,
|
|
752
|
+
Modal
|
|
600
753
|
};
|
|
601
|
-
//# sourceMappingURL=chunk-
|
|
754
|
+
//# sourceMappingURL=chunk-ET7TMD3D.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/tabs/EztrakTabs.tsx","../src/components/pagination/CustomPagination.tsx","../src/components/search-filters/ResetFiltersButton.tsx","../src/components/modal/Modal.tsx"],"sourcesContent":["import {\r\n useCallback,\r\n useEffect,\r\n useId,\r\n useRef,\r\n useState,\r\n type KeyboardEvent,\r\n} from \"react\";\r\nimport { cn } from \"../../utils/cn\";\r\nimport type { EztrakTab, EztrakTabsProps } from \"./types\";\r\n\r\nfunction getInitialTabId(\r\n tabs: EztrakTab[],\r\n defaultTabId?: string\r\n): string | undefined {\r\n if (defaultTabId && tabs.some((t) => t.id === defaultTabId && !t.disabled)) {\r\n return defaultTabId;\r\n }\r\n return tabs.find((t) => !t.disabled)?.id;\r\n}\r\n\r\nfunction getEnabledTabIds(tabs: EztrakTab[]): string[] {\r\n return tabs.filter((t) => !t.disabled).map((t) => t.id);\r\n}\r\n\r\nexport function EztrakTabs({\r\n tabs,\r\n activeTab,\r\n defaultTabId,\r\n onTabChange,\r\n showPanels = true,\r\n keepMounted = false,\r\n classNames,\r\n className,\r\n}: EztrakTabsProps) {\r\n const baseId = useId().replace(/:/g, \"\");\r\n const isControlled = activeTab !== undefined && activeTab !== null;\r\n const [uncontrolledActive, setUncontrolledActive] = useState(() =>\r\n getInitialTabId(tabs, defaultTabId)\r\n );\r\n const tabRefs = useRef<Map<string, HTMLButtonElement>>(new Map());\r\n\r\n const displayActive = isControlled ? activeTab : uncontrolledActive;\r\n\r\n useEffect(() => {\r\n if (isControlled) return;\r\n const enabledIds = getEnabledTabIds(tabs);\r\n if (!displayActive || !enabledIds.includes(displayActive)) {\r\n const next = getInitialTabId(tabs, defaultTabId);\r\n if (next !== displayActive) {\r\n setUncontrolledActive(next);\r\n }\r\n }\r\n }, [tabs, defaultTabId, isControlled, displayActive]);\r\n\r\n const handleTabClick = useCallback(\r\n (tabId: string, disabled?: boolean) => {\r\n if (disabled) return;\r\n if (!isControlled) {\r\n setUncontrolledActive(tabId);\r\n }\r\n onTabChange?.(tabId);\r\n },\r\n [isControlled, onTabChange]\r\n );\r\n\r\n const focusTab = useCallback((tabId: string) => {\r\n tabRefs.current.get(tabId)?.focus();\r\n }, []);\r\n\r\n const handleListKeyDown = useCallback(\r\n (event: KeyboardEvent<HTMLUListElement>) => {\r\n const enabledIds = getEnabledTabIds(tabs);\r\n if (enabledIds.length === 0) return;\r\n\r\n const currentIndex = displayActive\r\n ? enabledIds.indexOf(displayActive)\r\n : -1;\r\n let nextIndex = currentIndex;\r\n\r\n switch (event.key) {\r\n case \"ArrowRight\":\r\n case \"ArrowDown\":\r\n event.preventDefault();\r\n nextIndex =\r\n currentIndex < 0\r\n ? 0\r\n : (currentIndex + 1) % enabledIds.length;\r\n break;\r\n case \"ArrowLeft\":\r\n case \"ArrowUp\":\r\n event.preventDefault();\r\n nextIndex =\r\n currentIndex < 0\r\n ? enabledIds.length - 1\r\n : (currentIndex - 1 + enabledIds.length) % enabledIds.length;\r\n break;\r\n case \"Home\":\r\n event.preventDefault();\r\n nextIndex = 0;\r\n break;\r\n case \"End\":\r\n event.preventDefault();\r\n nextIndex = enabledIds.length - 1;\r\n break;\r\n default:\r\n return;\r\n }\r\n\r\n const nextId = enabledIds[nextIndex];\r\n if (nextId) {\r\n handleTabClick(nextId);\r\n focusTab(nextId);\r\n }\r\n },\r\n [tabs, displayActive, handleTabClick, focusTab]\r\n );\r\n\r\n if (!tabs.length) {\r\n return null;\r\n }\r\n\r\n const wrapperClass = cn(\r\n \"eztrak-tabs-wrapper\",\r\n classNames?.wrapper,\r\n className\r\n );\r\n\r\n return (\r\n <div className={wrapperClass}>\r\n <div className={cn(\"eztrak-tabs-container\", classNames?.container)}>\r\n <nav\r\n className={cn(\"eztrak-tabs-nav\", classNames?.nav)}\r\n aria-label=\"Tabs\"\r\n >\r\n <ul\r\n role=\"tablist\"\r\n className={cn(\"eztrak-tabs-list\", classNames?.list)}\r\n onKeyDown={handleListKeyDown}\r\n >\r\n {tabs.map((tab) => {\r\n const isActive = displayActive === tab.id;\r\n const tabId = `${baseId}-tab-${tab.id}`;\r\n const panelId = `${baseId}-panel-${tab.id}`;\r\n\r\n return (\r\n <li\r\n key={tab.id}\r\n role=\"presentation\"\r\n className={cn(\r\n \"eztrak-tabs-item\",\r\n isActive && \"eztrak-tabs-item-active\",\r\n classNames?.item,\r\n isActive && classNames?.itemActive\r\n )}\r\n >\r\n <button\r\n ref={(el) => {\r\n if (el) {\r\n tabRefs.current.set(tab.id, el);\r\n } else {\r\n tabRefs.current.delete(tab.id);\r\n }\r\n }}\r\n type=\"button\"\r\n role=\"tab\"\r\n id={tabId}\r\n aria-selected={isActive}\r\n aria-controls={showPanels ? panelId : undefined}\r\n tabIndex={isActive ? 0 : -1}\r\n disabled={tab.disabled}\r\n className={cn(\r\n \"eztrak-tabs-button\",\r\n isActive && \"eztrak-tabs-button-active\",\r\n classNames?.button,\r\n isActive && classNames?.buttonActive\r\n )}\r\n onClick={() => handleTabClick(tab.id, tab.disabled)}\r\n >\r\n {tab.icon ? (\r\n <span\r\n className={cn(\"eztrak-tabs-icon\", classNames?.icon)}\r\n aria-hidden\r\n >\r\n {tab.icon}\r\n </span>\r\n ) : null}\r\n <span\r\n className={cn(\"eztrak-tabs-label\", classNames?.label)}\r\n >\r\n {tab.label}\r\n </span>\r\n {isActive ? (\r\n <span\r\n className={cn(\r\n \"eztrak-tabs-underline\",\r\n classNames?.underline\r\n )}\r\n aria-hidden\r\n />\r\n ) : null}\r\n </button>\r\n </li>\r\n );\r\n })}\r\n </ul>\r\n </nav>\r\n\r\n {showPanels ? (\r\n <div className={cn(\"eztrak-tabs-content\", classNames?.content)}>\r\n {tabs.map((tab) => {\r\n const isActive = displayActive === tab.id;\r\n const panelId = `${baseId}-panel-${tab.id}`;\r\n const tabId = `${baseId}-tab-${tab.id}`;\r\n\r\n if (!keepMounted && !isActive) {\r\n return null;\r\n }\r\n\r\n return (\r\n <div\r\n key={tab.id}\r\n id={panelId}\r\n role=\"tabpanel\"\r\n aria-labelledby={tabId}\r\n hidden={!isActive}\r\n className={cn(\"eztrak-tabs-panel\", classNames?.panel)}\r\n >\r\n {tab.content}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n ) : null}\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { type ChangeEvent, type ReactNode } from \"react\";\r\nimport { useSearchParams } from \"react-router-dom\";\r\nimport { cn } from \"../../utils/cn\";\r\nimport { confirmationAlert } from \"../../utils/handleApiError\";\r\nimport type {\r\n CustomPaginationProps,\r\n ResetColumnsButtonProps,\r\n TableLayoutToolbarControlsProps,\r\n} from \"./types\";\r\n\r\nconst DEFAULT_PAGE_SIZE_OPTIONS = [10, 20, 30, 50, 100];\r\nconst ALL_PAGES_VALUE = -1;\r\n\r\nfunction padCount(num: number) {\r\n return num.toString().padStart(2, \"0\");\r\n}\r\n\r\nfunction RefreshIcon({\r\n size = 14,\r\n className,\r\n}: {\r\n size?: number;\r\n className?: string;\r\n}) {\r\n return (\r\n <svg\r\n width={size}\r\n height={size}\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n aria-hidden=\"true\"\r\n className={className}\r\n >\r\n <path d=\"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\" />\r\n <path d=\"M21 3v5h-5\" />\r\n <path d=\"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16\" />\r\n <path d=\"M8 16H3v5\" />\r\n </svg>\r\n );\r\n}\r\n\r\nexport function ResetColumnsButton({\r\n onReset,\r\n disabled = false,\r\n isLoading = false,\r\n}: ResetColumnsButtonProps) {\r\n const handleClick = () => {\r\n confirmationAlert(onReset, {\r\n text: \"Reset column order, widths, and visibility to defaults?\",\r\n icon: \"warning\",\r\n title: \"Reset column layout to default\",\r\n });\r\n };\r\n\r\n return (\r\n <button\r\n type=\"button\"\r\n onClick={handleClick}\r\n disabled={disabled || isLoading}\r\n title=\"Reset column layout to default\"\r\n className=\"inline-flex items-center gap-1.5 rounded-xl border border-primary-150 bg-white px-3 py-1.5 text-sm font-medium text-primary-150 hover:bg-gray-50 focus:outline-none disabled:hover:bg-white\"\r\n >\r\n <RefreshIcon size={14} className={cn(isLoading ? \"animate-spin\" : \"\")} />\r\n Reset columns\r\n </button>\r\n );\r\n}\r\n\r\nexport function TableLayoutToolbarControls({\r\n layoutStatus = {},\r\n onResetLayout,\r\n renderResetControl,\r\n isLoading = false,\r\n}: TableLayoutToolbarControlsProps) {\r\n const { isLayoutLoading, isLayoutSaving, isLayoutResetting } = layoutStatus;\r\n const isLayoutBusy = isLayoutLoading || isLayoutSaving || isLayoutResetting;\r\n\r\n return (\r\n <div className=\"flex items-center gap-3\">\r\n {onResetLayout &&\r\n (renderResetControl ? (\r\n renderResetControl(onResetLayout)\r\n ) : (\r\n <ResetColumnsButton\r\n onReset={onResetLayout}\r\n disabled={isLayoutBusy}\r\n isLoading={isLoading}\r\n />\r\n ))}\r\n </div>\r\n );\r\n}\r\n\r\nexport function CustomPagination({\r\n paginationData,\r\n paginationPageSize,\r\n pageSizeOptions: pageSizeOptionsProp,\r\n isLoading = false,\r\n paramNames,\r\n onPageChange,\r\n onPageSizeChange,\r\n onResetLayout,\r\n renderResetControl,\r\n layoutStatus,\r\n showAllPagesOption = false,\r\n classNames,\r\n className,\r\n}: CustomPaginationProps) {\r\n const [searchParams, setSearchParams] = useSearchParams();\r\n const pageKey = paramNames?.page ?? \"page\";\r\n const perPageKey = paramNames?.perPage ?? \"perPage\";\r\n const pageSizeOptions =\r\n pageSizeOptionsProp ?? paginationPageSize ?? DEFAULT_PAGE_SIZE_OPTIONS;\r\n const perPageParam = searchParams.get(perPageKey);\r\n const perPageNumber =\r\n perPageParam !== null && perPageParam !== \"\"\r\n ? parseInt(perPageParam, 10)\r\n : NaN;\r\n const isShowingAll = perPageNumber === ALL_PAGES_VALUE;\r\n\r\n const currentPage = paginationData\r\n ? Math.max(0, paginationData.currentPage - 1)\r\n : 0;\r\n\r\n const handlePageChange = (pageNumber: number) => {\r\n if (\r\n !paginationData ||\r\n pageNumber < 0 ||\r\n pageNumber >= paginationData.pageCount\r\n ) {\r\n return;\r\n }\r\n\r\n const safePage = Math.max(\r\n 1,\r\n Math.min(pageNumber + 1, paginationData.pageCount)\r\n );\r\n const newParams = new URLSearchParams(searchParams);\r\n newParams.set(pageKey, String(safePage));\r\n setSearchParams(newParams, { replace: true });\r\n onPageChange?.(safePage);\r\n };\r\n\r\n const handlePageSizeChange = (event: ChangeEvent<HTMLSelectElement>) => {\r\n const parsed = parseInt(event.target.value, 10);\r\n if (\r\n !Number.isFinite(parsed) ||\r\n (parsed < 1 && parsed !== ALL_PAGES_VALUE)\r\n ) {\r\n return;\r\n }\r\n\r\n const newParams = new URLSearchParams(searchParams);\r\n newParams.set(pageKey, \"1\");\r\n newParams.set(perPageKey, String(parsed));\r\n setSearchParams(newParams, { replace: true });\r\n onPageSizeChange?.(parsed);\r\n };\r\n\r\n const createPageButtons = () => {\r\n const buttons: ReactNode[] = [];\r\n const maxButtons = 5;\r\n const totalPages = Math.max(1, paginationData?.pageCount ?? 1);\r\n\r\n let startPage = Math.max(0, currentPage - Math.floor(maxButtons / 2));\r\n let endPage = Math.min(totalPages - 1, startPage + maxButtons - 1);\r\n\r\n if (endPage - startPage + 1 < maxButtons) {\r\n startPage = Math.max(0, endPage - maxButtons + 1);\r\n }\r\n\r\n if (startPage > 0) {\r\n buttons.push(\r\n <button\r\n key=\"1\"\r\n type=\"button\"\r\n onClick={() => handlePageChange(0)}\r\n aria-label=\"Page 1\"\r\n className={cn(\r\n \"px-3 py-2 text-sm text-gray-600 hover:text-blue-600 hover:bg-blue-50 rounded-md transition-colors\",\r\n classNames?.pageButton\r\n )}\r\n >\r\n 1\r\n </button>\r\n );\r\n\r\n if (startPage > 1) {\r\n buttons.push(\r\n <span\r\n key=\"ellipsis1\"\r\n aria-hidden=\"true\"\r\n className=\"px-2 py-2 text-gray-400\"\r\n >\r\n ...\r\n </span>\r\n );\r\n }\r\n }\r\n\r\n for (let i = startPage; i <= endPage; i++) {\r\n const isActive = currentPage === i;\r\n buttons.push(\r\n <button\r\n key={i + 1}\r\n type=\"button\"\r\n onClick={() => handlePageChange(i)}\r\n aria-label={`Page ${i + 1}`}\r\n aria-current={isActive ? \"page\" : undefined}\r\n className={cn(\r\n \"px-3 py-2 text-sm rounded-md transition-colors\",\r\n isActive\r\n ? cn(\"bg-gray-400 text-white\", classNames?.activePageButton)\r\n : cn(\r\n \"text-gray-600 hover:text-gray-600 hover:bg-gray-50\",\r\n classNames?.pageButton\r\n )\r\n )}\r\n >\r\n {i + 1}\r\n </button>\r\n );\r\n }\r\n\r\n if (endPage < totalPages - 1) {\r\n if (endPage < totalPages - 2) {\r\n buttons.push(\r\n <span\r\n key=\"ellipsis2\"\r\n aria-hidden=\"true\"\r\n className=\"px-2 py-2 text-gray-400\"\r\n >\r\n ...\r\n </span>\r\n );\r\n }\r\n\r\n buttons.push(\r\n <button\r\n key={totalPages}\r\n type=\"button\"\r\n onClick={() => handlePageChange(totalPages - 1)}\r\n aria-label={`Page ${totalPages}`}\r\n className={cn(\r\n \"px-3 py-2 text-sm text-gray-600 hover:text-gray-600 hover:bg-gray-50 rounded-md transition-colors\",\r\n classNames?.pageButton\r\n )}\r\n >\r\n {totalPages}\r\n </button>\r\n );\r\n }\r\n\r\n return buttons;\r\n };\r\n\r\n if (isLoading || !paginationData) {\r\n return (\r\n <div className=\"flex items-center justify-center p-6 bg-gray-50\">\r\n <span className=\"text-gray-500\">\r\n {isLoading ? \"Loading...\" : \"No pagination data\"}\r\n </span>\r\n </div>\r\n );\r\n }\r\n\r\n const effectiveSizeOptions =\r\n paginationData.perPage > 0 &&\r\n !pageSizeOptions.includes(paginationData.perPage)\r\n ? [...pageSizeOptions, paginationData.perPage].sort((a, b) => a - b)\r\n : pageSizeOptions;\r\n\r\n const selectValue = isShowingAll\r\n ? ALL_PAGES_VALUE\r\n : paginationData.perPage ||\r\n (Number.isFinite(perPageNumber) && perPageNumber > 0\r\n ? perPageNumber\r\n : 10);\r\n\r\n const startItem =\r\n paginationData.totalCount === 0\r\n ? 0\r\n : (paginationData.currentPage - 1) * paginationData.perPage + 1;\r\n const endItem = Math.min(\r\n startItem + paginationData.perPage - 1,\r\n paginationData.totalCount\r\n );\r\n\r\n const { isLayoutLoading, isLayoutSaving, isLayoutResetting } =\r\n layoutStatus ?? {};\r\n const isLayoutBusy =\r\n isLayoutLoading || isLayoutSaving || isLayoutResetting;\r\n\r\n return (\r\n <div\r\n className={cn(\r\n \"flex items-center justify-between pb-4\",\r\n className,\r\n classNames?.root\r\n )}\r\n >\r\n <div className={cn(\"flex-1\", classNames?.info)}>\r\n <span className=\"text-xs font-medium text-neutral-400\">\r\n {isShowingAll\r\n ? `Showing All ${paginationData.totalCount ?? 0} Results`\r\n : `Showing ${padCount(startItem)} - ${padCount(endItem)} of ${paginationData.totalCount ?? 0} results`}\r\n </span>\r\n </div>\r\n\r\n <nav\r\n aria-label=\"Pagination\"\r\n className={cn(\"flex items-center space-x-1\", classNames?.nav)}\r\n >\r\n <button\r\n type=\"button\"\r\n onClick={() => handlePageChange(currentPage - 1)}\r\n disabled={currentPage === 0 || isShowingAll}\r\n className=\"p-2 text-gray-400 hover:text-gray-600 disabled:opacity-30 disabled:cursor-not-allowed transition-colors\"\r\n aria-label=\"Previous page\"\r\n >\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\r\n <path d=\"M10.7 2.3a1 1 0 0 1 0 1.4L6.4 8l4.3 4.3a1 1 0 1 1-1.4 1.4l-5-5a1 1 0 0 1 0-1.4l5-5a1 1 0 0 1 1.4 0z\" />\r\n </svg>\r\n </button>\r\n\r\n <div className=\"flex items-center space-x-1\">\r\n {isShowingAll ? (\r\n <span className=\"px-3 py-2 text-sm text-gray-400\" aria-hidden=\"true\">\r\n All\r\n </span>\r\n ) : (\r\n createPageButtons()\r\n )}\r\n </div>\r\n\r\n <button\r\n type=\"button\"\r\n onClick={() => handlePageChange(currentPage + 1)}\r\n disabled={\r\n currentPage >= paginationData.pageCount - 1 || isShowingAll\r\n }\r\n className=\"p-2 text-gray-400 hover:text-gray-600 disabled:opacity-30 disabled:cursor-not-allowed transition-colors\"\r\n aria-label=\"Next page\"\r\n >\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\r\n <path d=\"M5.3 13.7a1 1 0 0 1 0-1.4L9.6 8 5.3 3.7a1 1 0 0 1 1.4-1.4l5 5a1 1 0 0 1 0 1.4l-5 5a1 1 0 0 1-1.4 0z\" />\r\n </svg>\r\n </button>\r\n </nav>\r\n\r\n <div className=\"flex-1 flex justify-end\">\r\n <div className=\"flex items-center gap-3\">\r\n {onResetLayout &&\r\n (renderResetControl ? (\r\n renderResetControl(onResetLayout)\r\n ) : (\r\n <ResetColumnsButton\r\n onReset={onResetLayout}\r\n disabled={isLayoutBusy}\r\n isLoading={isLoading}\r\n />\r\n ))}\r\n <div className=\"flex items-center space-x-2\">\r\n <label\r\n htmlFor=\"pagination-per-page\"\r\n className=\"text-sm text-gray-600\"\r\n >\r\n Items per page\r\n </label>\r\n <select\r\n id=\"pagination-per-page\"\r\n value={selectValue}\r\n onChange={handlePageSizeChange}\r\n className={cn(\r\n \"px-3 py-1.5 text-sm border border-gray-300 rounded-md bg-white text-gray-700 hover:border-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors\",\r\n classNames?.select\r\n )}\r\n >\r\n {showAllPagesOption && (\r\n <option value={ALL_PAGES_VALUE}>All</option>\r\n )}\r\n {effectiveSizeOptions.map((option) => (\r\n <option key={option} value={option}>\r\n {option}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport default CustomPagination;\r\n","import { useSearchParams } from \"react-router-dom\";\r\nimport { cn } from \"../../utils/cn\";\r\nimport type {\r\n ResetFiltersButtonProps,\r\n ResetFiltersButtonVariant,\r\n} from \"./types\";\r\n\r\nconst BASE_STYLES =\r\n \"inline-flex items-center gap-1.5 px-5 py-3 rounded-md text-sm font-medium transition-colors duration-200 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50\";\r\n\r\nconst VARIANTS: Record<ResetFiltersButtonVariant, string> = {\r\n primary:\r\n \"bg-white text-secondary border border-secondary hover:bg-lightGray hover:text-black\",\r\n \"primary-outline\":\r\n \"bg-white text-primary-150 border border-primary-150 font-bold hover:bg-primary-100 hover:text-white\",\r\n \"primary-fill\":\r\n \"bg-primary-150 text-white border border-primary-150 hover:bg-primary/90\",\r\n secondary:\r\n \"bg-primary-150 text-white border border-primary-150 hover:bg-primary/90\",\r\n danger: \"bg-red-600 text-white border border-red-600 hover:bg-red-700\",\r\n outline: \"bg-white text-primary border border-primary hover:bg-primary/10\",\r\n ghost:\r\n \"bg-transparent text-secondary border border-transparent hover:bg-primary/10\",\r\n};\r\n\r\nfunction ResetIcon({\r\n size = 16,\r\n className,\r\n}: {\r\n size?: number;\r\n className?: string;\r\n}) {\r\n return (\r\n <svg\r\n width={size}\r\n height={size}\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n aria-hidden=\"true\"\r\n className={className}\r\n >\r\n <path d=\"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\" />\r\n <path d=\"M21 3v5h-5\" />\r\n <path d=\"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16\" />\r\n <path d=\"M8 16H3v5\" />\r\n </svg>\r\n );\r\n}\r\n\r\nexport function ResetFiltersButton({\r\n label = \"Reset Filters\",\r\n icon,\r\n variant = \"primary-outline\",\r\n className,\r\n onReset,\r\n disabled = false,\r\n}: ResetFiltersButtonProps) {\r\n const [, setSearchParams] = useSearchParams();\r\n\r\n const handleReset = () => {\r\n setSearchParams({}, { replace: true });\r\n onReset?.();\r\n };\r\n\r\n const resolvedIcon = icon === undefined ? <ResetIcon size={16} /> : icon;\r\n\r\n return (\r\n <button\r\n type=\"button\"\r\n onClick={handleReset}\r\n disabled={disabled}\r\n className={cn(BASE_STYLES, VARIANTS[variant], className)}\r\n >\r\n {resolvedIcon}\r\n {label}\r\n </button>\r\n );\r\n}\r\n","import { AnimatePresence, motion } from \"framer-motion\";\r\nimport { useEffect, useRef, type MouseEvent } from \"react\";\r\nimport { createPortal } from \"react-dom\";\r\nimport { FaFileExport, FaPrint } from \"react-icons/fa\";\r\nimport { IoCloseCircleOutline } from \"react-icons/io5\";\r\nimport { cn } from \"../../utils/cn\";\r\nimport type { ModalProps } from \"./types\";\r\n\r\nexport function Modal({\r\n isOpen,\r\n onClose,\r\n title,\r\n children,\r\n footer,\r\n className = \"w-2/3\",\r\n width,\r\n onPrint,\r\n onExport,\r\n modalBodyClassName,\r\n modalBodyWrapperClass,\r\n closeOnBackdropClick = false,\r\n closeOnEscape = true,\r\n zIndex = 1000,\r\n}: ModalProps) {\r\n const modalRef = useRef<HTMLDivElement>(null);\r\n\r\n const handleBackdropClick = (e: MouseEvent<HTMLDivElement>) => {\r\n if (e.target === e.currentTarget && closeOnBackdropClick) {\r\n onClose();\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n const handleEscape = (e: KeyboardEvent) => {\r\n if (e.key === \"Escape\" && isOpen && closeOnEscape) {\r\n onClose();\r\n }\r\n };\r\n\r\n if (isOpen) {\r\n document.addEventListener(\"keydown\", handleEscape);\r\n document.body.style.overflow = \"hidden\";\r\n }\r\n\r\n return () => {\r\n document.removeEventListener(\"keydown\", handleEscape);\r\n document.body.style.overflow = \"unset\";\r\n };\r\n }, [isOpen, onClose, closeOnEscape]);\r\n\r\n const modalContent = (\r\n <AnimatePresence>\r\n {isOpen && (\r\n <div\r\n className=\"fixed inset-0 bg-gray-500 bg-opacity-50 flex justify-center items-center p-4\"\r\n onClick={handleBackdropClick}\r\n style={{\r\n position: \"fixed\",\r\n top: 0,\r\n left: 0,\r\n right: 0,\r\n bottom: 0,\r\n width: \"100vw\",\r\n height: \"100vh\",\r\n margin: 0,\r\n padding: \"1rem\",\r\n zIndex,\r\n }}\r\n >\r\n <motion.div\r\n ref={modalRef}\r\n initial={{ y: \"-100vh\", opacity: 0 }}\r\n animate={{ y: 0, opacity: 1 }}\r\n exit={{ y: \"100vh\", opacity: 0 }}\r\n transition={{ duration: 0.3 }}\r\n className={cn(\r\n \"bg-white rounded-3xl shadow-lg max-h-[90vh] flex flex-col mx-auto\",\r\n className,\r\n width\r\n )}\r\n onClick={(e) => e.stopPropagation()}\r\n style={{\r\n maxWidth: \"95vw\",\r\n maxHeight: \"90vh\",\r\n }}\r\n >\r\n <div className=\"sticky top-0 z-10 flex justify-between items-center bg-white text-2xl p-8 pb-4 rounded-t-3xl\">\r\n <h2 className=\"font-semibold\">{title}</h2>\r\n <div className=\"flex items-center space-x-4\">\r\n {onPrint && (\r\n <button\r\n type=\"button\"\r\n onClick={onPrint}\r\n className=\"flex items-center gap-1 hover:text-gray-300 text-sm border p-1 rounded\"\r\n >\r\n <FaPrint />\r\n <span>Print</span>\r\n </button>\r\n )}\r\n {onExport && (\r\n <button\r\n type=\"button\"\r\n onClick={onExport}\r\n className=\"flex items-center gap-1 hover:text-gray-300 text-sm border p-1 rounded\"\r\n >\r\n <FaFileExport />\r\n <span>Export</span>\r\n </button>\r\n )}\r\n <button\r\n type=\"button\"\r\n onClick={onClose}\r\n className=\"px-2 hover:opacity-70 transition-opacity\"\r\n >\r\n <IoCloseCircleOutline color=\"#8898AA\" size={25} />\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div\r\n className={cn(\r\n \"overflow-y-auto px-8 pb-8 flex-grow scroll\",\r\n modalBodyWrapperClass,\r\n modalBodyClassName\r\n )}\r\n >\r\n {children}\r\n </div>\r\n\r\n {footer && (\r\n <div className=\"sticky bottom-0 flex justify-end p-4 space-x-4 border-t bg-white rounded-b-3xl\">\r\n {footer}\r\n </div>\r\n )}\r\n </motion.div>\r\n </div>\r\n )}\r\n </AnimatePresence>\r\n );\r\n\r\n let modalRoot = document.getElementById(\"modal-root\");\r\n if (!modalRoot) {\r\n modalRoot = document.createElement(\"div\");\r\n modalRoot.id = \"modal-root\";\r\n document.body.appendChild(modalRoot);\r\n }\r\n\r\n return createPortal(modalContent, modalRoot);\r\n}\r\n"],"mappings":"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","names":["jsx","jsxs","useSearchParams","jsx","jsxs","useSearchParams","useEffect","useRef","jsx","jsxs","useRef","useEffect"]}
|
|
@@ -94,11 +94,14 @@ declare function ResetColumnsButton({ onReset, disabled, isLoading, }: ResetColu
|
|
|
94
94
|
declare function TableLayoutToolbarControls({ layoutStatus, onResetLayout, renderResetControl, isLoading, }: TableLayoutToolbarControlsProps): react.JSX.Element;
|
|
95
95
|
declare function CustomPagination({ paginationData, paginationPageSize, pageSizeOptions: pageSizeOptionsProp, isLoading, paramNames, onPageChange, onPageSizeChange, onResetLayout, renderResetControl, layoutStatus, showAllPagesOption, classNames, className, }: CustomPaginationProps): react.JSX.Element;
|
|
96
96
|
|
|
97
|
+
type ResetFiltersButtonVariant = "primary" | "primary-outline" | "primary-fill" | "secondary" | "danger" | "outline" | "ghost";
|
|
97
98
|
interface ResetFiltersButtonProps {
|
|
98
99
|
/** Button label text. Defaults to "Reset Filters". */
|
|
99
100
|
label?: string;
|
|
100
101
|
/** Leading icon. Defaults to a reset icon; pass `null` to hide it. */
|
|
101
102
|
icon?: ReactNode;
|
|
103
|
+
/** Visual style variant. Defaults to "primary-outline". */
|
|
104
|
+
variant?: ResetFiltersButtonVariant;
|
|
102
105
|
/** Extra classes merged with the default button styles. */
|
|
103
106
|
className?: string;
|
|
104
107
|
/** Called after the search params are cleared. */
|
|
@@ -106,6 +109,25 @@ interface ResetFiltersButtonProps {
|
|
|
106
109
|
disabled?: boolean;
|
|
107
110
|
}
|
|
108
111
|
|
|
109
|
-
declare function ResetFiltersButton({ label, icon, className, onReset, disabled, }: ResetFiltersButtonProps): react.JSX.Element;
|
|
112
|
+
declare function ResetFiltersButton({ label, icon, variant, className, onReset, disabled, }: ResetFiltersButtonProps): react.JSX.Element;
|
|
110
113
|
|
|
111
|
-
|
|
114
|
+
interface ModalProps {
|
|
115
|
+
isOpen: boolean;
|
|
116
|
+
onClose: () => void;
|
|
117
|
+
title?: ReactNode;
|
|
118
|
+
children?: ReactNode;
|
|
119
|
+
footer?: ReactNode;
|
|
120
|
+
className?: string;
|
|
121
|
+
width?: string;
|
|
122
|
+
onPrint?: () => void;
|
|
123
|
+
onExport?: () => void;
|
|
124
|
+
modalBodyClassName?: string;
|
|
125
|
+
modalBodyWrapperClass?: string;
|
|
126
|
+
closeOnBackdropClick?: boolean;
|
|
127
|
+
closeOnEscape?: boolean;
|
|
128
|
+
zIndex?: number;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
declare function Modal({ isOpen, onClose, title, children, footer, className, width, onPrint, onExport, modalBodyClassName, modalBodyWrapperClass, closeOnBackdropClick, closeOnEscape, zIndex, }: ModalProps): react.ReactPortal;
|
|
132
|
+
|
|
133
|
+
export { CustomPagination, type CustomPaginationClassNames, type CustomPaginationProps, type EztrakTab, EztrakTabs, type EztrakTabsClassNames, type EztrakTabsProps, type LayoutStatus, Modal, type ModalProps, type PaginationData, ResetColumnsButton, type ResetColumnsButtonProps, ResetFiltersButton, type ResetFiltersButtonProps, TableLayoutToolbarControls, type TableLayoutToolbarControlsProps };
|
|
@@ -94,11 +94,14 @@ declare function ResetColumnsButton({ onReset, disabled, isLoading, }: ResetColu
|
|
|
94
94
|
declare function TableLayoutToolbarControls({ layoutStatus, onResetLayout, renderResetControl, isLoading, }: TableLayoutToolbarControlsProps): react.JSX.Element;
|
|
95
95
|
declare function CustomPagination({ paginationData, paginationPageSize, pageSizeOptions: pageSizeOptionsProp, isLoading, paramNames, onPageChange, onPageSizeChange, onResetLayout, renderResetControl, layoutStatus, showAllPagesOption, classNames, className, }: CustomPaginationProps): react.JSX.Element;
|
|
96
96
|
|
|
97
|
+
type ResetFiltersButtonVariant = "primary" | "primary-outline" | "primary-fill" | "secondary" | "danger" | "outline" | "ghost";
|
|
97
98
|
interface ResetFiltersButtonProps {
|
|
98
99
|
/** Button label text. Defaults to "Reset Filters". */
|
|
99
100
|
label?: string;
|
|
100
101
|
/** Leading icon. Defaults to a reset icon; pass `null` to hide it. */
|
|
101
102
|
icon?: ReactNode;
|
|
103
|
+
/** Visual style variant. Defaults to "primary-outline". */
|
|
104
|
+
variant?: ResetFiltersButtonVariant;
|
|
102
105
|
/** Extra classes merged with the default button styles. */
|
|
103
106
|
className?: string;
|
|
104
107
|
/** Called after the search params are cleared. */
|
|
@@ -106,6 +109,25 @@ interface ResetFiltersButtonProps {
|
|
|
106
109
|
disabled?: boolean;
|
|
107
110
|
}
|
|
108
111
|
|
|
109
|
-
declare function ResetFiltersButton({ label, icon, className, onReset, disabled, }: ResetFiltersButtonProps): react.JSX.Element;
|
|
112
|
+
declare function ResetFiltersButton({ label, icon, variant, className, onReset, disabled, }: ResetFiltersButtonProps): react.JSX.Element;
|
|
110
113
|
|
|
111
|
-
|
|
114
|
+
interface ModalProps {
|
|
115
|
+
isOpen: boolean;
|
|
116
|
+
onClose: () => void;
|
|
117
|
+
title?: ReactNode;
|
|
118
|
+
children?: ReactNode;
|
|
119
|
+
footer?: ReactNode;
|
|
120
|
+
className?: string;
|
|
121
|
+
width?: string;
|
|
122
|
+
onPrint?: () => void;
|
|
123
|
+
onExport?: () => void;
|
|
124
|
+
modalBodyClassName?: string;
|
|
125
|
+
modalBodyWrapperClass?: string;
|
|
126
|
+
closeOnBackdropClick?: boolean;
|
|
127
|
+
closeOnEscape?: boolean;
|
|
128
|
+
zIndex?: number;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
declare function Modal({ isOpen, onClose, title, children, footer, className, width, onPrint, onExport, modalBodyClassName, modalBodyWrapperClass, closeOnBackdropClick, closeOnEscape, zIndex, }: ModalProps): react.ReactPortal;
|
|
132
|
+
|
|
133
|
+
export { CustomPagination, type CustomPaginationClassNames, type CustomPaginationProps, type EztrakTab, EztrakTabs, type EztrakTabsClassNames, type EztrakTabsProps, type LayoutStatus, Modal, type ModalProps, type PaginationData, ResetColumnsButton, type ResetColumnsButtonProps, ResetFiltersButton, type ResetFiltersButtonProps, TableLayoutToolbarControls, type TableLayoutToolbarControlsProps };
|
package/dist/components/index.js
CHANGED
|
@@ -32,6 +32,7 @@ var components_exports = {};
|
|
|
32
32
|
__export(components_exports, {
|
|
33
33
|
CustomPagination: () => CustomPagination,
|
|
34
34
|
EztrakTabs: () => EztrakTabs,
|
|
35
|
+
Modal: () => Modal,
|
|
35
36
|
ResetColumnsButton: () => ResetColumnsButton,
|
|
36
37
|
ResetFiltersButton: () => ResetFiltersButton,
|
|
37
38
|
TableLayoutToolbarControls: () => TableLayoutToolbarControls
|
|
@@ -593,6 +594,16 @@ function CustomPagination({
|
|
|
593
594
|
// src/components/search-filters/ResetFiltersButton.tsx
|
|
594
595
|
var import_react_router_dom2 = require("react-router-dom");
|
|
595
596
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
597
|
+
var BASE_STYLES = "inline-flex items-center gap-1.5 px-5 py-3 rounded-md text-sm font-medium transition-colors duration-200 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50";
|
|
598
|
+
var VARIANTS = {
|
|
599
|
+
primary: "bg-white text-secondary border border-secondary hover:bg-lightGray hover:text-black",
|
|
600
|
+
"primary-outline": "bg-white text-primary-150 border border-primary-150 font-bold hover:bg-primary-100 hover:text-white",
|
|
601
|
+
"primary-fill": "bg-primary-150 text-white border border-primary-150 hover:bg-primary/90",
|
|
602
|
+
secondary: "bg-primary-150 text-white border border-primary-150 hover:bg-primary/90",
|
|
603
|
+
danger: "bg-red-600 text-white border border-red-600 hover:bg-red-700",
|
|
604
|
+
outline: "bg-white text-primary border border-primary hover:bg-primary/10",
|
|
605
|
+
ghost: "bg-transparent text-secondary border border-transparent hover:bg-primary/10"
|
|
606
|
+
};
|
|
596
607
|
function ResetIcon({
|
|
597
608
|
size = 16,
|
|
598
609
|
className
|
|
@@ -622,6 +633,7 @@ function ResetIcon({
|
|
|
622
633
|
function ResetFiltersButton({
|
|
623
634
|
label = "Reset Filters",
|
|
624
635
|
icon,
|
|
636
|
+
variant = "primary-outline",
|
|
625
637
|
className,
|
|
626
638
|
onReset,
|
|
627
639
|
disabled = false
|
|
@@ -638,10 +650,7 @@ function ResetFiltersButton({
|
|
|
638
650
|
type: "button",
|
|
639
651
|
onClick: handleReset,
|
|
640
652
|
disabled,
|
|
641
|
-
className: cn(
|
|
642
|
-
"inline-flex items-center gap-1.5 rounded-xl border border-primary-150 bg-white px-3 py-1.5 text-sm font-medium text-primary-150 hover:bg-gray-50 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-white",
|
|
643
|
-
className
|
|
644
|
-
),
|
|
653
|
+
className: cn(BASE_STYLES, VARIANTS[variant], className),
|
|
645
654
|
children: [
|
|
646
655
|
resolvedIcon,
|
|
647
656
|
label
|
|
@@ -649,10 +658,155 @@ function ResetFiltersButton({
|
|
|
649
658
|
}
|
|
650
659
|
);
|
|
651
660
|
}
|
|
661
|
+
|
|
662
|
+
// src/components/modal/Modal.tsx
|
|
663
|
+
var import_framer_motion = require("framer-motion");
|
|
664
|
+
var import_react2 = require("react");
|
|
665
|
+
var import_react_dom = require("react-dom");
|
|
666
|
+
var import_fa = require("react-icons/fa");
|
|
667
|
+
var import_io5 = require("react-icons/io5");
|
|
668
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
669
|
+
function Modal({
|
|
670
|
+
isOpen,
|
|
671
|
+
onClose,
|
|
672
|
+
title,
|
|
673
|
+
children,
|
|
674
|
+
footer,
|
|
675
|
+
className = "w-2/3",
|
|
676
|
+
width,
|
|
677
|
+
onPrint,
|
|
678
|
+
onExport,
|
|
679
|
+
modalBodyClassName,
|
|
680
|
+
modalBodyWrapperClass,
|
|
681
|
+
closeOnBackdropClick = false,
|
|
682
|
+
closeOnEscape = true,
|
|
683
|
+
zIndex = 1e3
|
|
684
|
+
}) {
|
|
685
|
+
const modalRef = (0, import_react2.useRef)(null);
|
|
686
|
+
const handleBackdropClick = (e) => {
|
|
687
|
+
if (e.target === e.currentTarget && closeOnBackdropClick) {
|
|
688
|
+
onClose();
|
|
689
|
+
}
|
|
690
|
+
};
|
|
691
|
+
(0, import_react2.useEffect)(() => {
|
|
692
|
+
const handleEscape = (e) => {
|
|
693
|
+
if (e.key === "Escape" && isOpen && closeOnEscape) {
|
|
694
|
+
onClose();
|
|
695
|
+
}
|
|
696
|
+
};
|
|
697
|
+
if (isOpen) {
|
|
698
|
+
document.addEventListener("keydown", handleEscape);
|
|
699
|
+
document.body.style.overflow = "hidden";
|
|
700
|
+
}
|
|
701
|
+
return () => {
|
|
702
|
+
document.removeEventListener("keydown", handleEscape);
|
|
703
|
+
document.body.style.overflow = "unset";
|
|
704
|
+
};
|
|
705
|
+
}, [isOpen, onClose, closeOnEscape]);
|
|
706
|
+
const modalContent = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_framer_motion.AnimatePresence, { children: isOpen && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
707
|
+
"div",
|
|
708
|
+
{
|
|
709
|
+
className: "fixed inset-0 bg-gray-500 bg-opacity-50 flex justify-center items-center p-4",
|
|
710
|
+
onClick: handleBackdropClick,
|
|
711
|
+
style: {
|
|
712
|
+
position: "fixed",
|
|
713
|
+
top: 0,
|
|
714
|
+
left: 0,
|
|
715
|
+
right: 0,
|
|
716
|
+
bottom: 0,
|
|
717
|
+
width: "100vw",
|
|
718
|
+
height: "100vh",
|
|
719
|
+
margin: 0,
|
|
720
|
+
padding: "1rem",
|
|
721
|
+
zIndex
|
|
722
|
+
},
|
|
723
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
724
|
+
import_framer_motion.motion.div,
|
|
725
|
+
{
|
|
726
|
+
ref: modalRef,
|
|
727
|
+
initial: { y: "-100vh", opacity: 0 },
|
|
728
|
+
animate: { y: 0, opacity: 1 },
|
|
729
|
+
exit: { y: "100vh", opacity: 0 },
|
|
730
|
+
transition: { duration: 0.3 },
|
|
731
|
+
className: cn(
|
|
732
|
+
"bg-white rounded-3xl shadow-lg max-h-[90vh] flex flex-col mx-auto",
|
|
733
|
+
className,
|
|
734
|
+
width
|
|
735
|
+
),
|
|
736
|
+
onClick: (e) => e.stopPropagation(),
|
|
737
|
+
style: {
|
|
738
|
+
maxWidth: "95vw",
|
|
739
|
+
maxHeight: "90vh"
|
|
740
|
+
},
|
|
741
|
+
children: [
|
|
742
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "sticky top-0 z-10 flex justify-between items-center bg-white text-2xl p-8 pb-4 rounded-t-3xl", children: [
|
|
743
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "font-semibold", children: title }),
|
|
744
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center space-x-4", children: [
|
|
745
|
+
onPrint && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
746
|
+
"button",
|
|
747
|
+
{
|
|
748
|
+
type: "button",
|
|
749
|
+
onClick: onPrint,
|
|
750
|
+
className: "flex items-center gap-1 hover:text-gray-300 text-sm border p-1 rounded",
|
|
751
|
+
children: [
|
|
752
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_fa.FaPrint, {}),
|
|
753
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Print" })
|
|
754
|
+
]
|
|
755
|
+
}
|
|
756
|
+
),
|
|
757
|
+
onExport && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
758
|
+
"button",
|
|
759
|
+
{
|
|
760
|
+
type: "button",
|
|
761
|
+
onClick: onExport,
|
|
762
|
+
className: "flex items-center gap-1 hover:text-gray-300 text-sm border p-1 rounded",
|
|
763
|
+
children: [
|
|
764
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_fa.FaFileExport, {}),
|
|
765
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Export" })
|
|
766
|
+
]
|
|
767
|
+
}
|
|
768
|
+
),
|
|
769
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
770
|
+
"button",
|
|
771
|
+
{
|
|
772
|
+
type: "button",
|
|
773
|
+
onClick: onClose,
|
|
774
|
+
className: "px-2 hover:opacity-70 transition-opacity",
|
|
775
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_io5.IoCloseCircleOutline, { color: "#8898AA", size: 25 })
|
|
776
|
+
}
|
|
777
|
+
)
|
|
778
|
+
] })
|
|
779
|
+
] }),
|
|
780
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
781
|
+
"div",
|
|
782
|
+
{
|
|
783
|
+
className: cn(
|
|
784
|
+
"overflow-y-auto px-8 pb-8 flex-grow scroll",
|
|
785
|
+
modalBodyWrapperClass,
|
|
786
|
+
modalBodyClassName
|
|
787
|
+
),
|
|
788
|
+
children
|
|
789
|
+
}
|
|
790
|
+
),
|
|
791
|
+
footer && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "sticky bottom-0 flex justify-end p-4 space-x-4 border-t bg-white rounded-b-3xl", children: footer })
|
|
792
|
+
]
|
|
793
|
+
}
|
|
794
|
+
)
|
|
795
|
+
}
|
|
796
|
+
) });
|
|
797
|
+
let modalRoot = document.getElementById("modal-root");
|
|
798
|
+
if (!modalRoot) {
|
|
799
|
+
modalRoot = document.createElement("div");
|
|
800
|
+
modalRoot.id = "modal-root";
|
|
801
|
+
document.body.appendChild(modalRoot);
|
|
802
|
+
}
|
|
803
|
+
return (0, import_react_dom.createPortal)(modalContent, modalRoot);
|
|
804
|
+
}
|
|
652
805
|
// Annotate the CommonJS export names for ESM import in node:
|
|
653
806
|
0 && (module.exports = {
|
|
654
807
|
CustomPagination,
|
|
655
808
|
EztrakTabs,
|
|
809
|
+
Modal,
|
|
656
810
|
ResetColumnsButton,
|
|
657
811
|
ResetFiltersButton,
|
|
658
812
|
TableLayoutToolbarControls
|