|
1 | | -import { useEffect, useState } from "react"; |
| 1 | +import { useEffect, useMemo, useState } from "react"; |
2 | 2 |
|
3 | 3 | import { Meta, StoryObj } from "@storybook/react-vite"; |
4 | 4 |
|
@@ -94,3 +94,44 @@ export const Selectable: StoryObj<typeof Table> = { |
94 | 94 | ); |
95 | 95 | }, |
96 | 96 | }; |
| 97 | + |
| 98 | +export const Sortable: StoryObj<typeof Table> = { |
| 99 | + args: { |
| 100 | + headers, |
| 101 | + rows, |
| 102 | + }, |
| 103 | + render: ({ rows, headers, ...props }) => { |
| 104 | + const [sort, setSort] = useState<[number, "asc" | "desc"]>([0, "asc"]); |
| 105 | + |
| 106 | + const sortedHeaders = useMemo( |
| 107 | + () => |
| 108 | + headers.map((header, headerIndex) => ({ |
| 109 | + ...header, |
| 110 | + isSortable: true, |
| 111 | + sortDir: sort[0] === headerIndex ? sort[1] : undefined, |
| 112 | + })), |
| 113 | + [headers, sort] |
| 114 | + ); |
| 115 | + |
| 116 | + const sortedRows = useMemo( |
| 117 | + () => |
| 118 | + [...rows].sort((a, b) => { |
| 119 | + const [cellIdx, sortDir] = sort; |
| 120 | + const cellA = a.items[cellIdx]?.label?.toString() || ""; |
| 121 | + const cellB = b.items[cellIdx]?.label?.toString() || ""; |
| 122 | + const result = cellA.localeCompare(cellB, "en", { numeric: true }); |
| 123 | + return sortDir === "asc" ? result : -result; |
| 124 | + }), |
| 125 | + [rows, sort] |
| 126 | + ); |
| 127 | + |
| 128 | + return ( |
| 129 | + <Table |
| 130 | + {...props} |
| 131 | + headers={sortedHeaders} |
| 132 | + rows={sortedRows} |
| 133 | + onSort={(dir, _, idx) => void setSort([idx, dir])} |
| 134 | + /> |
| 135 | + ); |
| 136 | + }, |
| 137 | +}; |
0 commit comments