@eztrak/shared 0.14.0 → 0.15.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.
@@ -1522,7 +1522,8 @@ function PopupCellRenderer({
1522
1522
  params,
1523
1523
  onAction,
1524
1524
  placement = "bottom-end",
1525
- tippyProps
1525
+ tippyProps,
1526
+ ariaLabel = "Row actions"
1526
1527
  }) {
1527
1528
  const [visible, setVisible] = useState4(false);
1528
1529
  const show = () => setVisible(true);
@@ -1558,7 +1559,7 @@ function PopupCellRenderer({
1558
1559
  "flex items-center justify-center gap-2 rounded-full text-gray-500 hover:text-gray-800",
1559
1560
  className
1560
1561
  ),
1561
- "aria-label": "Row actions",
1562
+ "aria-label": ariaLabel,
1562
1563
  children: [
1563
1564
  !hideTitle && title,
1564
1565
  /* @__PURE__ */ jsx12(ActionIcon, { "aria-hidden": true })
@@ -1569,10 +1570,311 @@ function PopupCellRenderer({
1569
1570
  ) });
1570
1571
  }
1571
1572
 
1573
+ // src/components/row-actions/presets.ts
1574
+ import {
1575
+ FaArchive,
1576
+ FaCheckCircle,
1577
+ FaDownload,
1578
+ FaEdit,
1579
+ FaEye,
1580
+ FaFileAlt,
1581
+ FaHistory,
1582
+ FaTrashAlt
1583
+ } from "react-icons/fa";
1584
+ var ROW_ACTION_ITEM_HOVER_CLASS = "hover:bg-primary-50 hover:text-primary-150";
1585
+ var ROW_ACTION_ITEM_TEXT_CLASS = "text-secondary";
1586
+ var ROW_ACTION_DEFAULT_ICON_SIZE = 16;
1587
+ var ROW_ACTION_DEFAULT_MENU_TOOLTIP_STYLE = {
1588
+ zIndex: 1e4
1589
+ };
1590
+ var ROW_ACTION_PRESETS = {
1591
+ edit: { label: "Edit", icon: FaEdit },
1592
+ delete: { label: "Delete", icon: FaTrashAlt, danger: true, iconClassName: "text-red-500" },
1593
+ view: { label: "View", icon: FaEye },
1594
+ notes: { label: "Notes", icon: FaFileAlt },
1595
+ history: { label: "History", icon: FaHistory },
1596
+ download: { label: "Download", icon: FaDownload },
1597
+ archive: { label: "Archive", icon: FaArchive },
1598
+ resolve: { label: "Resolve", icon: FaCheckCircle }
1599
+ };
1600
+
1601
+ // src/components/row-actions/ActionMenuItem.tsx
1602
+ import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
1603
+ function ActionMenuItem({
1604
+ label,
1605
+ icon: Icon,
1606
+ iconSize = ROW_ACTION_DEFAULT_ICON_SIZE,
1607
+ iconClassName,
1608
+ labelClassName,
1609
+ tooltip,
1610
+ tooltipPlacement = "top",
1611
+ tooltipDelayShow,
1612
+ tooltipDelayHide,
1613
+ tooltipClassName,
1614
+ tooltipStyle,
1615
+ disabled = false,
1616
+ danger = false,
1617
+ highlight = false,
1618
+ showLabel = true,
1619
+ className,
1620
+ onClick
1621
+ }) {
1622
+ const tooltipText = tooltip ?? label;
1623
+ return /* @__PURE__ */ jsx13(
1624
+ ToolTip,
1625
+ {
1626
+ text: tooltipText,
1627
+ disabled: !tooltipText,
1628
+ placement: tooltipPlacement,
1629
+ delayShow: tooltipDelayShow,
1630
+ delayHide: tooltipDelayHide,
1631
+ tooltipClassName,
1632
+ tooltipStyle: { ...ROW_ACTION_DEFAULT_MENU_TOOLTIP_STYLE, ...tooltipStyle },
1633
+ className: showLabel ? "block w-full" : "inline-flex",
1634
+ children: /* @__PURE__ */ jsxs10(
1635
+ "button",
1636
+ {
1637
+ type: "button",
1638
+ disabled,
1639
+ "aria-label": label,
1640
+ onClick: (event) => {
1641
+ event.stopPropagation();
1642
+ if (disabled) return;
1643
+ onClick();
1644
+ },
1645
+ className: cn(
1646
+ "flex items-center gap-2 text-sm transition-colors duration-150",
1647
+ ROW_ACTION_ITEM_TEXT_CLASS,
1648
+ showLabel ? "w-full rounded-xl px-3 py-2 text-left" : "justify-center rounded-md p-1",
1649
+ disabled ? "cursor-not-allowed opacity-50" : ROW_ACTION_ITEM_HOVER_CLASS,
1650
+ highlight && !danger && "text-primary-150",
1651
+ className
1652
+ ),
1653
+ children: [
1654
+ Icon ? /* @__PURE__ */ jsx13(
1655
+ Icon,
1656
+ {
1657
+ className: cn("shrink-0", iconClassName),
1658
+ "aria-hidden": true,
1659
+ size: iconSize
1660
+ }
1661
+ ) : null,
1662
+ showLabel ? /* @__PURE__ */ jsx13("span", { className: labelClassName, children: label }) : null
1663
+ ]
1664
+ }
1665
+ )
1666
+ }
1667
+ );
1668
+ }
1669
+
1670
+ // src/components/row-actions/resolveActions.ts
1671
+ function evalFlag(flag, data) {
1672
+ if (typeof flag === "function") return Boolean(flag(data));
1673
+ return Boolean(flag);
1674
+ }
1675
+ function mergePreset(name, overrides) {
1676
+ if (!name) return void 0;
1677
+ const base = ROW_ACTION_PRESETS[name];
1678
+ const extra = overrides?.[name];
1679
+ if (!extra) return base;
1680
+ return { ...base, ...extra };
1681
+ }
1682
+ function resolveActions(actions, data, hasPermission, presets) {
1683
+ const list = typeof actions === "function" ? actions(data) : actions;
1684
+ return list.flatMap((action, index) => {
1685
+ const type = action.type ?? "item";
1686
+ const preset = mergePreset(action.preset, presets);
1687
+ const key = action.key ?? action.preset ?? `action-${index}`;
1688
+ const label = action.label ?? preset?.label ?? key;
1689
+ if (action.permission && hasPermission && !hasPermission(action.permission)) {
1690
+ return [];
1691
+ }
1692
+ if (evalFlag(action.hidden, data)) {
1693
+ return [];
1694
+ }
1695
+ const tooltip = action.tooltip === false ? void 0 : action.tooltip ?? (type === "divider" ? void 0 : label);
1696
+ const resolved = {
1697
+ key,
1698
+ type,
1699
+ label,
1700
+ icon: action.icon ?? preset?.icon,
1701
+ iconSize: action.iconSize,
1702
+ content: action.content,
1703
+ onClick: action.onClick,
1704
+ disabled: evalFlag(action.disabled, data),
1705
+ danger: action.danger ?? preset?.danger ?? false,
1706
+ highlight: evalFlag(action.highlight, data),
1707
+ tooltip,
1708
+ tooltipPlacement: action.tooltipPlacement,
1709
+ confirm: action.confirm,
1710
+ closeOnClick: action.closeOnClick !== false,
1711
+ className: action.className,
1712
+ iconClassName: cn(preset?.iconClassName, action.iconClassName) || void 0,
1713
+ labelClassName: action.labelClassName
1714
+ };
1715
+ return [resolved];
1716
+ });
1717
+ }
1718
+
1719
+ // src/components/row-actions/RowActions.tsx
1720
+ import { Fragment as Fragment3, jsx as jsx14 } from "react/jsx-runtime";
1721
+ function runAction(action, data, hide, confirmFn = confirmationAlert) {
1722
+ if (!action.onClick) {
1723
+ if (action.closeOnClick) hide?.();
1724
+ return;
1725
+ }
1726
+ const execute = () => action.onClick?.(data);
1727
+ if (action.confirm) {
1728
+ confirmFn?.(execute, action.confirm);
1729
+ } else {
1730
+ execute();
1731
+ }
1732
+ if (action.closeOnClick) {
1733
+ hide?.();
1734
+ }
1735
+ }
1736
+ function RowActions({
1737
+ actions,
1738
+ data,
1739
+ mode = "menu",
1740
+ actionIcon,
1741
+ className,
1742
+ menuClassName,
1743
+ itemClassName,
1744
+ itemIconClassName,
1745
+ itemLabelClassName,
1746
+ iconSize = ROW_ACTION_DEFAULT_ICON_SIZE,
1747
+ triggerTooltip = "Actions",
1748
+ triggerAriaLabel = "Row actions",
1749
+ hasPermission,
1750
+ placement = "bottom-end",
1751
+ tippyProps,
1752
+ presets,
1753
+ confirmFn = confirmationAlert,
1754
+ tooltipPlacement = "top",
1755
+ tooltipDelayShow,
1756
+ tooltipDelayHide,
1757
+ tooltipClassName,
1758
+ tooltipStyle,
1759
+ renderItem,
1760
+ renderMenu,
1761
+ renderTrigger
1762
+ }) {
1763
+ const resolved = resolveActions(actions, data, hasPermission, presets);
1764
+ if (resolved.length === 0) {
1765
+ return null;
1766
+ }
1767
+ const mergedTooltipStyle = {
1768
+ ...ROW_ACTION_DEFAULT_MENU_TOOLTIP_STYLE,
1769
+ ...tooltipStyle
1770
+ };
1771
+ const renderDefaultItem = (action, hide, showLabel = true) => {
1772
+ if (action.type === "divider") {
1773
+ return /* @__PURE__ */ jsx14(
1774
+ "div",
1775
+ {
1776
+ role: "separator",
1777
+ className: cn("my-1 h-px bg-gray-100", action.className)
1778
+ },
1779
+ action.key
1780
+ );
1781
+ }
1782
+ if (action.content) {
1783
+ return /* @__PURE__ */ jsx14("div", { className: action.className, children: action.content }, action.key);
1784
+ }
1785
+ return /* @__PURE__ */ jsx14(
1786
+ ActionMenuItem,
1787
+ {
1788
+ label: action.label,
1789
+ icon: action.icon,
1790
+ iconSize: action.iconSize ?? iconSize,
1791
+ iconClassName: cn(itemIconClassName, action.iconClassName),
1792
+ labelClassName: cn(itemLabelClassName, action.labelClassName),
1793
+ tooltip: action.tooltip,
1794
+ tooltipPlacement: action.tooltipPlacement ?? tooltipPlacement,
1795
+ tooltipDelayShow,
1796
+ tooltipDelayHide,
1797
+ tooltipClassName,
1798
+ tooltipStyle: mergedTooltipStyle,
1799
+ disabled: action.disabled,
1800
+ danger: action.danger,
1801
+ highlight: action.highlight,
1802
+ showLabel,
1803
+ className: cn(itemClassName, action.className),
1804
+ onClick: () => runAction(action, data, hide, confirmFn)
1805
+ },
1806
+ action.key
1807
+ );
1808
+ };
1809
+ const renderItems = (hide, showLabel = true) => resolved.map((action) => {
1810
+ const defaultItem = renderDefaultItem(action, hide, showLabel);
1811
+ if (!renderItem) return defaultItem;
1812
+ return /* @__PURE__ */ jsx14("div", { children: renderItem(action, { data, hide: hide ?? (() => void 0), defaultItem }) }, action.key);
1813
+ });
1814
+ if (mode === "inline") {
1815
+ const inlineItems = renderItems(void 0, false);
1816
+ return /* @__PURE__ */ jsx14("div", { className: cn("flex h-full items-center justify-center gap-1", className), children: inlineItems });
1817
+ }
1818
+ const triggerTooltipText = triggerTooltip === false ? void 0 : triggerTooltip;
1819
+ const buildMenu = (hide) => {
1820
+ const defaultMenu = /* @__PURE__ */ jsx14(
1821
+ "div",
1822
+ {
1823
+ className: cn(
1824
+ "flex min-w-[180px] flex-col rounded-lg border border-gray-100 bg-white p-2 shadow-lg",
1825
+ menuClassName
1826
+ ),
1827
+ children: renderItems(hide, true)
1828
+ }
1829
+ );
1830
+ if (!renderMenu) return defaultMenu;
1831
+ return renderMenu({
1832
+ data,
1833
+ actions: resolved,
1834
+ hide,
1835
+ defaultMenu
1836
+ });
1837
+ };
1838
+ if (renderTrigger) {
1839
+ return /* @__PURE__ */ jsx14(Fragment3, { children: renderTrigger({
1840
+ data,
1841
+ actions: resolved,
1842
+ hide: () => void 0,
1843
+ defaultMenu: buildMenu(() => void 0)
1844
+ }) });
1845
+ }
1846
+ return /* @__PURE__ */ jsx14(
1847
+ ToolTip,
1848
+ {
1849
+ text: triggerTooltipText,
1850
+ disabled: !triggerTooltipText,
1851
+ placement: tooltipPlacement,
1852
+ delayShow: tooltipDelayShow,
1853
+ delayHide: tooltipDelayHide,
1854
+ tooltipClassName,
1855
+ tooltipStyle,
1856
+ className: "flex h-full items-center justify-center",
1857
+ children: /* @__PURE__ */ jsx14(
1858
+ PopupCellRenderer,
1859
+ {
1860
+ params: { data },
1861
+ actionIcon,
1862
+ hideTitle: true,
1863
+ className,
1864
+ placement,
1865
+ tippyProps,
1866
+ ariaLabel: triggerAriaLabel,
1867
+ dropDownContent: (handleAction) => buildMenu(() => handleAction("close"))
1868
+ }
1869
+ )
1870
+ }
1871
+ );
1872
+ }
1873
+
1572
1874
  // src/components/table-error-boundary/TableErrorBoundary.tsx
1573
1875
  import { useMemo as useMemo2 } from "react";
1574
1876
  import { FaArrowsRotate, FaTriangleExclamation } from "react-icons/fa6";
1575
- import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
1877
+ import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
1576
1878
  var TableErrorBoundary = ({
1577
1879
  isError,
1578
1880
  isLoading = false,
@@ -1589,7 +1891,7 @@ var TableErrorBoundary = ({
1589
1891
  return "Unable to load table data. Please try again.";
1590
1892
  }, [error, errorMessage]);
1591
1893
  if (isLoading && !isError) {
1592
- return /* @__PURE__ */ jsx13(
1894
+ return /* @__PURE__ */ jsx15(
1593
1895
  "div",
1594
1896
  {
1595
1897
  className: cn(
@@ -1600,12 +1902,12 @@ var TableErrorBoundary = ({
1600
1902
  role: "status",
1601
1903
  "aria-live": "polite",
1602
1904
  "aria-busy": "true",
1603
- children: /* @__PURE__ */ jsx13(Loader, { size: "40px" })
1905
+ children: /* @__PURE__ */ jsx15(Loader, { size: "40px" })
1604
1906
  }
1605
1907
  );
1606
1908
  }
1607
1909
  if (isError) {
1608
- return /* @__PURE__ */ jsxs10(
1910
+ return /* @__PURE__ */ jsxs11(
1609
1911
  "div",
1610
1912
  {
1611
1913
  className: cn(
@@ -1616,7 +1918,7 @@ var TableErrorBoundary = ({
1616
1918
  role: "alert",
1617
1919
  "aria-live": "assertive",
1618
1920
  children: [
1619
- /* @__PURE__ */ jsx13(
1921
+ /* @__PURE__ */ jsx15(
1620
1922
  FaTriangleExclamation,
1621
1923
  {
1622
1924
  className: "text-red-500",
@@ -1624,11 +1926,11 @@ var TableErrorBoundary = ({
1624
1926
  "aria-hidden": true
1625
1927
  }
1626
1928
  ),
1627
- /* @__PURE__ */ jsxs10("div", { className: "max-w-md space-y-1", children: [
1628
- /* @__PURE__ */ jsx13("p", { className: "text-base font-semibold text-gray-800", children: "Failed to load data" }),
1629
- /* @__PURE__ */ jsx13("p", { className: "text-sm text-gray-600", children: message })
1929
+ /* @__PURE__ */ jsxs11("div", { className: "max-w-md space-y-1", children: [
1930
+ /* @__PURE__ */ jsx15("p", { className: "text-base font-semibold text-gray-800", children: "Failed to load data" }),
1931
+ /* @__PURE__ */ jsx15("p", { className: "text-sm text-gray-600", children: message })
1630
1932
  ] }),
1631
- refetch && /* @__PURE__ */ jsxs10(
1933
+ refetch && /* @__PURE__ */ jsxs11(
1632
1934
  "button",
1633
1935
  {
1634
1936
  type: "button",
@@ -1636,7 +1938,7 @@ var TableErrorBoundary = ({
1636
1938
  disabled: isLoading,
1637
1939
  className: "inline-flex items-center gap-2 rounded-lg bg-primary-150 px-4 py-2 text-sm font-medium text-white transition-colors hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-60",
1638
1940
  children: [
1639
- /* @__PURE__ */ jsx13(FaArrowsRotate, { className: cn(isLoading && "animate-spin") }),
1941
+ /* @__PURE__ */ jsx15(FaArrowsRotate, { className: cn(isLoading && "animate-spin") }),
1640
1942
  isLoading ? "Retrying..." : "Try again"
1641
1943
  ]
1642
1944
  }
@@ -1645,7 +1947,7 @@ var TableErrorBoundary = ({
1645
1947
  }
1646
1948
  );
1647
1949
  }
1648
- return /* @__PURE__ */ jsx13(Fragment3, { children });
1950
+ return /* @__PURE__ */ jsx15(Fragment4, { children });
1649
1951
  };
1650
1952
 
1651
1953
  export {
@@ -1664,6 +1966,14 @@ export {
1664
1966
  TooltipText,
1665
1967
  CustomCellEditor,
1666
1968
  PopupCellRenderer,
1969
+ ROW_ACTION_ITEM_HOVER_CLASS,
1970
+ ROW_ACTION_ITEM_TEXT_CLASS,
1971
+ ROW_ACTION_DEFAULT_ICON_SIZE,
1972
+ ROW_ACTION_DEFAULT_MENU_TOOLTIP_STYLE,
1973
+ ROW_ACTION_PRESETS,
1974
+ ActionMenuItem,
1975
+ resolveActions,
1976
+ RowActions,
1667
1977
  TableErrorBoundary
1668
1978
  };
1669
- //# sourceMappingURL=chunk-JATUZDLG.mjs.map
1979
+ //# sourceMappingURL=chunk-HQPQ6TOE.mjs.map