@andreagiugni/tailwind-dashboard-ui 0.5.16 → 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 CHANGED
@@ -171,7 +171,7 @@ Legend: **(+native)** = also extends the element's native HTML attributes.
171
171
  | `DropdownItem` | `variant` (default/primary/outline, like Button), `icon?`, `bgColor`/`textColor`/`borderColor` overrides, `tag` (a/button), `href`, `onClick`, `onItemClick`, `baseClassName` (full override) |
172
172
  | `Modal` | `isOpen`, `onClose`, `title?` (wrapping header aligned with close button), `showCloseButton`, `isFullscreen`, `closeOnBackdrop?`, `closeOnEsc?`; **alert preset** → `variant` (`success`/`info`/`warning`/`danger`) + `title`, `description`, `actionText?`, `onAction?`; (+native div) |
173
173
  | `Table` (composable) | `TableHeader` / `TableBody` / `TableRow` / `TableCell` with `children`, `isHeader` (cell), (+native table elements; `onClick` / `onDoubleClick` on rows & cells) |
174
- | `Table` (data-driven) | pass `data` + `columns` (`key`, `header`, `sortable?`, `align?`, `render?`, `className?`) to get search + per-column sort + pagination: `rowsPerPage?` (max rows/page, default 10), `rowsPerPageOptions?`, `searchKeys?` (**search box shown only when provided**), `searchPlaceholder?`, `defaultSortKey?` / `defaultSortDirection?`, `pagination?`, `paginationAlign?` (`left`/`center`/`right`/`full`, default `right`), `showSizeSelector?`, `onRowClick?`, `getRowId?`, `emptyContent?` |
174
+ | `Table` (data-driven) | pass `data` + `columns` (`key`, `header`, `sortable?`, `align?`, `render?`, `className?`) to get search + three-state per-column sort (neutral/ascending/descending) + pagination: `rowsPerPage?` (max rows/page, default 10), `rowsPerPageOptions?`, `searchKeys?` (**search box shown only when provided**), `searchPlaceholder?`, `defaultSortKey?` / `defaultSortDirection?`, `pagination?`, `paginationAlign?` (`left`/`center`/`right`/`full`, default `right`), `showSizeSelector?`, `onRowClick?`, `getRowId?`, `emptyContent?` |
175
175
  | `Pagination` | `currentPage`, `totalPages`, `onPageChange`, `align?` (`left`/`center`/`right`/`full` — `full` pins Previous/Next to the edges with page indices centered) |
176
176
  | `Breadcrumb` | `pageTitle`, `items?`, (+native) |
177
177
  | `ThemeToggleButton` | `theme?` (controlled), `onToggle?`, (+native button) |
package/dist/index.cjs CHANGED
@@ -739,15 +739,63 @@ var alignClass = {
739
739
  right: "text-right"
740
740
  };
741
741
  function SortIcon({
742
- active,
743
- direction
742
+ state
744
743
  }) {
745
- const on = "text-brand-500";
746
- const off = "text-gray-400 dark:text-gray-600";
747
- return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex flex-col leading-none", children: [
748
- /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "10", height: "6", viewBox: "0 0 10 6", fill: "currentColor", "aria-hidden": "true", className: active && direction === "asc" ? on : off, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 0 9 5H1z" }) }),
749
- /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "10", height: "6", viewBox: "0 0 10 6", fill: "currentColor", "aria-hidden": "true", className: active && direction === "desc" ? on : off, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 6 1 1h8z" }) })
750
- ] });
744
+ const active = "text-brand-500";
745
+ const inactive = "text-gray-400 dark:text-gray-500";
746
+ return /* @__PURE__ */ jsxRuntime.jsxs(
747
+ "span",
748
+ {
749
+ "data-sort-state": state,
750
+ className: "inline-flex shrink-0 flex-col items-center -space-y-1",
751
+ children: [
752
+ /* @__PURE__ */ jsxRuntime.jsx(
753
+ "svg",
754
+ {
755
+ "data-sort-direction": "asc",
756
+ width: "12",
757
+ height: "12",
758
+ viewBox: "0 0 12 12",
759
+ fill: "none",
760
+ "aria-hidden": "true",
761
+ className: state === "asc" ? active : inactive,
762
+ children: /* @__PURE__ */ jsxRuntime.jsx(
763
+ "path",
764
+ {
765
+ d: "M3.5 7.25 6 4.75l2.5 2.5",
766
+ stroke: "currentColor",
767
+ strokeWidth: "1.5",
768
+ strokeLinecap: "round",
769
+ strokeLinejoin: "round"
770
+ }
771
+ )
772
+ }
773
+ ),
774
+ /* @__PURE__ */ jsxRuntime.jsx(
775
+ "svg",
776
+ {
777
+ "data-sort-direction": "desc",
778
+ width: "12",
779
+ height: "12",
780
+ viewBox: "0 0 12 12",
781
+ fill: "none",
782
+ "aria-hidden": "true",
783
+ className: state === "desc" ? active : inactive,
784
+ children: /* @__PURE__ */ jsxRuntime.jsx(
785
+ "path",
786
+ {
787
+ d: "m3.5 4.75 2.5 2.5 2.5-2.5",
788
+ stroke: "currentColor",
789
+ strokeWidth: "1.5",
790
+ strokeLinecap: "round",
791
+ strokeLinejoin: "round"
792
+ }
793
+ )
794
+ }
795
+ )
796
+ ]
797
+ }
798
+ );
751
799
  }
752
800
  function DataDrivenTable({
753
801
  data,
@@ -797,10 +845,14 @@ function DataDrivenTable({
797
845
  const pageRows = pagination ? filtered.slice(start, start + pageSize) : filtered;
798
846
  const toggleSort = (col) => {
799
847
  if (!col.sortable) return;
800
- if (sortKey === col.key) setSortDir((d) => d === "asc" ? "desc" : "asc");
801
- else {
848
+ if (sortKey !== col.key) {
802
849
  setSortKey(col.key);
803
850
  setSortDir("asc");
851
+ } else if (sortDir === "asc") {
852
+ setSortDir("desc");
853
+ } else {
854
+ setSortKey(void 0);
855
+ setSortDir("asc");
804
856
  }
805
857
  setPage(1);
806
858
  };
@@ -878,8 +930,9 @@ function DataDrivenTable({
878
930
  TableCell,
879
931
  {
880
932
  isHeader: true,
933
+ "aria-sort": col.sortable ? isActive ? sortDir === "asc" ? "ascending" : "descending" : "none" : void 0,
881
934
  className: chunkYERNSNT4_cjs.cn(
882
- "whitespace-nowrap px-5 py-3 text-xs font-semibold text-gray-700 dark:text-gray-300",
935
+ "whitespace-nowrap px-5 py-3 text-xs font-semibold text-gray-500 dark:text-gray-400",
883
936
  alignClass[col.align ?? "left"],
884
937
  col.className
885
938
  ),
@@ -889,10 +942,10 @@ function DataDrivenTable({
889
942
  type: "button",
890
943
  onClick: () => toggleSort(col),
891
944
  "aria-label": `Sort by ${typeof col.header === "string" ? col.header : col.key}`,
892
- className: "inline-flex select-none items-center gap-1.5 hover:text-gray-900 dark:hover:text-white",
945
+ 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",
893
946
  children: [
894
- col.header,
895
- /* @__PURE__ */ jsxRuntime.jsx(SortIcon, { active: isActive, direction: isActive ? sortDir : "asc" })
947
+ /* @__PURE__ */ jsxRuntime.jsx(SortIcon, { state: isActive ? sortDir : "none" }),
948
+ col.header
896
949
  ]
897
950
  }
898
951
  ) : col.header