all-purpose-table 1.0.0

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/index.js ADDED
@@ -0,0 +1,580 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+
6
+ // #style-inject:#style-inject
7
+ function styleInject(css, { insertAt } = {}) {
8
+ if (typeof document === "undefined") return;
9
+ const head = document.head || document.getElementsByTagName("head")[0];
10
+ const style = document.createElement("style");
11
+ style.type = "text/css";
12
+ if (insertAt === "top") {
13
+ if (head.firstChild) {
14
+ head.insertBefore(style, head.firstChild);
15
+ } else {
16
+ head.appendChild(style);
17
+ }
18
+ } else {
19
+ head.appendChild(style);
20
+ }
21
+ if (style.styleSheet) {
22
+ style.styleSheet.cssText = css;
23
+ } else {
24
+ style.appendChild(document.createTextNode(css));
25
+ }
26
+ }
27
+
28
+ // src/styles.css
29
+ styleInject(":root {\n --apt-color-primary: #1f2937;\n --apt-color-border: #d1d5db;\n --apt-color-border-dark: #333;\n --apt-color-bg: white;\n --apt-color-bg-secondary: #e5e7eb;\n --apt-color-bg-hover: #f3f4f6;\n --apt-color-bg-dark: #1e1e1e;\n --apt-color-bg-dark-secondary: #333;\n --apt-color-bg-dark-hover: rgba(136, 136, 136, 0.2);\n --apt-color-text: #1f2937;\n --apt-color-text-dark: #eee;\n --apt-color-text-muted: #6b7280;\n --apt-color-text-muted-dark: #444;\n --apt-color-accent: #9333ea;\n --apt-color-accent-dark: #a855f7;\n --apt-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);\n --apt-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);\n}\n.apt-table-container {\n color: var(--apt-color-text);\n border-radius: 6px;\n margin: 0 6px;\n border: 1px solid var(--apt-color-border);\n background-color: var(--apt-color-bg);\n box-shadow: var(--apt-shadow);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n@media (prefers-color-scheme: dark) {\n .apt-table-container {\n color: var(--apt-color-text-dark);\n border-color: var(--apt-color-border-dark);\n background-color: var(--apt-color-bg-dark);\n }\n}\n.apt-empty-state {\n flex-grow: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 48px 0;\n color: #9ca3af;\n}\n@media (prefers-color-scheme: dark) {\n .apt-empty-state {\n color: var(--apt-color-text-muted-dark);\n }\n}\n.apt-scroll-area {\n flex-grow: 1;\n overflow: auto;\n}\n.apt-table {\n width: 100%;\n text-align: left;\n font-size: 0.75rem;\n line-height: 1rem;\n table-layout: fixed;\n}\n.apt-thead {\n position: sticky;\n top: 0;\n background-color: var(--apt-color-bg-secondary);\n z-index: 10;\n}\n@media (prefers-color-scheme: dark) {\n .apt-thead {\n background-color: var(--apt-color-bg-dark-secondary);\n }\n}\n.apt-th {\n position: relative;\n padding: 12px 8px;\n}\n.apt-th-sortable {\n cursor: pointer;\n}\n.apt-th-sortable:hover {\n background-color: #d1d5db;\n}\n@media (prefers-color-scheme: dark) {\n .apt-th-sortable:hover {\n background-color: #444;\n }\n}\n.apt-th-content {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.apt-resizer {\n position: absolute;\n right: 0;\n top: 0;\n height: 100%;\n width: 4px;\n cursor: col-resize;\n user-select: none;\n touch-action: none;\n background: transparent;\n}\n.apt-resizer:hover {\n background-color: var(--apt-color-accent);\n}\n@media (prefers-color-scheme: dark) {\n .apt-resizer:hover {\n background-color: var(--apt-color-accent-dark);\n }\n}\n.apt-tbody {\n border-top: 1px solid var(--apt-color-border);\n}\n@media (prefers-color-scheme: dark) {\n .apt-tbody {\n border-color: var(--apt-color-border-dark);\n }\n}\n.apt-tbody tr {\n border-bottom: 1px solid var(--apt-color-border);\n}\n@media (prefers-color-scheme: dark) {\n .apt-tbody tr {\n border-color: var(--apt-color-border-dark);\n }\n}\n.apt-row {\n transition: background-color 0.15s;\n}\n.apt-row:hover {\n background-color: var(--apt-color-bg-hover);\n}\n@media (prefers-color-scheme: dark) {\n .apt-row:hover {\n background-color: var(--apt-color-bg-dark-hover);\n }\n}\n.apt-row-expanded {\n background-color: #f9fafb;\n}\n@media (prefers-color-scheme: dark) {\n .apt-row-expanded {\n background-color: #2b2b2b;\n }\n}\n.apt-td {\n padding: 4px 8px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.apt-td-actions {\n padding: 4px 8px;\n}\n.apt-footer {\n display: grid;\n grid-template-columns: 1fr 1fr 1fr;\n align-items: center;\n padding: 8px;\n background-color: var(--apt-color-bg-secondary);\n}\n@media (prefers-color-scheme: dark) {\n .apt-footer {\n background-color: var(--apt-color-bg-dark-secondary);\n }\n}\n.apt-footer-left {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.apt-footer-center {\n justify-self: center;\n font-size: 0.875rem;\n color: #374151;\n}\n@media (prefers-color-scheme: dark) {\n .apt-footer-center {\n color: #d1d5db;\n }\n}\n.apt-footer-right {\n justify-self: end;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.apt-rows-label {\n font-size: 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: #4b5563;\n}\n@media (prefers-color-scheme: dark) {\n .apt-rows-label {\n color: #d1d5db;\n }\n}\n.apt-rows-select {\n padding: 4px 8px;\n font-size: 0.875rem;\n border-radius: 4px;\n background-color: white;\n border: 1px solid var(--apt-color-border);\n}\n@media (prefers-color-scheme: dark) {\n .apt-rows-select {\n background-color: #444;\n border-color: #555;\n color: var(--apt-color-text-dark);\n }\n}\n.apt-btn {\n padding: 4px 12px;\n font-size: 0.875rem;\n border-radius: 4px;\n background-color: white;\n border: 1px solid var(--apt-color-border);\n cursor: pointer;\n transition: background-color 0.15s;\n}\n.apt-btn:hover:not(:disabled) {\n background-color: #d1d5db;\n}\n.apt-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n@media (prefers-color-scheme: dark) {\n .apt-btn {\n background-color: #444;\n color: var(--apt-color-text-dark);\n border-color: #555;\n }\n .apt-btn:hover:not(:disabled) {\n background-color: #555;\n }\n}\n.apt-sort-icon {\n display: inline-block;\n margin-left: 4px;\n width: 12px;\n height: 12px;\n opacity: 0.3;\n}\n.apt-sort-icon-active {\n opacity: 1;\n}\n.apt-column-toggle-container {\n position: relative;\n}\n.apt-column-toggle-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n border-radius: 8px;\n border: 1px solid var(--apt-color-border);\n background-color: #f9fafb;\n padding: 8px 12px;\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--apt-color-primary);\n box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);\n cursor: pointer;\n transition: background-color 0.15s;\n}\n.apt-column-toggle-btn:hover {\n background-color: #f3f4f6;\n}\n.apt-column-toggle-btn:focus {\n outline: none;\n}\n@media (prefers-color-scheme: dark) {\n .apt-column-toggle-btn {\n border-color: #444;\n background-color: #333;\n color: var(--apt-color-text-dark);\n }\n .apt-column-toggle-btn:hover {\n background-color: #444;\n }\n}\n.apt-column-toggle-icon {\n font-size: 1.125rem;\n}\n.apt-column-toggle-count {\n font-size: 0.75rem;\n opacity: 0.7;\n}\n.apt-column-toggle-menu {\n position: absolute;\n right: 0;\n margin-top: 8px;\n width: 288px;\n border-radius: 8px;\n border: 1px solid var(--apt-color-border);\n background-color: white;\n box-shadow: var(--apt-shadow-lg);\n z-index: 50;\n max-height: 384px;\n overflow-y: auto;\n}\n@media (prefers-color-scheme: dark) {\n .apt-column-toggle-menu {\n border-color: #444;\n background-color: #222;\n }\n}\n.apt-column-toggle-menu-inner {\n padding: 12px;\n}\n.apt-column-toggle-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 12px;\n border-bottom: 1px solid #e5e7eb;\n padding-bottom: 8px;\n}\n@media (prefers-color-scheme: dark) {\n .apt-column-toggle-header {\n border-color: #444;\n }\n}\n.apt-column-toggle-title {\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--apt-color-primary);\n}\n@media (prefers-color-scheme: dark) {\n .apt-column-toggle-title {\n color: var(--apt-color-text-dark);\n }\n}\n.apt-column-toggle-select-all {\n font-size: 0.75rem;\n color: var(--apt-color-accent);\n background: none;\n border: none;\n cursor: pointer;\n text-decoration: none;\n}\n.apt-column-toggle-select-all:hover {\n text-decoration: underline;\n}\n@media (prefers-color-scheme: dark) {\n .apt-column-toggle-select-all {\n color: var(--apt-color-accent-dark);\n }\n}\n.apt-column-toggle-list {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.apt-column-toggle-item {\n display: flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n padding: 6px 8px;\n border-radius: 4px;\n transition: background-color 0.15s;\n}\n.apt-column-toggle-item:hover {\n background-color: #f3f4f6;\n}\n@media (prefers-color-scheme: dark) {\n .apt-column-toggle-item:hover {\n background-color: #333;\n }\n}\n.apt-column-toggle-checkbox {\n width: 16px;\n height: 16px;\n color: var(--apt-color-accent);\n border-radius: 12px;\n cursor: pointer;\n accent-color: var(--apt-color-accent);\n}\n.apt-column-toggle-label {\n font-size: 0.875rem;\n color: var(--apt-color-primary);\n flex: 1;\n}\n@media (prefers-color-scheme: dark) {\n .apt-column-toggle-label {\n color: var(--apt-color-text-dark);\n }\n}\n.apt-flex {\n display: flex;\n}\n.apt-items-center {\n align-items: center;\n}\n.apt-gap-2 {\n gap: 8px;\n}\n");
30
+ var SortIcon = ({ className }) => /* @__PURE__ */ jsxRuntime.jsx(
31
+ "svg",
32
+ {
33
+ className,
34
+ width: "12",
35
+ height: "12",
36
+ viewBox: "0 0 12 12",
37
+ fill: "currentColor",
38
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 3L3 6h6L6 3zM6 9l3-3H3l3 3z" })
39
+ }
40
+ );
41
+ var SortUpIcon = ({ className }) => /* @__PURE__ */ jsxRuntime.jsx(
42
+ "svg",
43
+ {
44
+ className,
45
+ width: "12",
46
+ height: "12",
47
+ viewBox: "0 0 12 12",
48
+ fill: "currentColor",
49
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 2L2 7h8L6 2z" })
50
+ }
51
+ );
52
+ var SortDownIcon = ({ className }) => /* @__PURE__ */ jsxRuntime.jsx(
53
+ "svg",
54
+ {
55
+ className,
56
+ width: "12",
57
+ height: "12",
58
+ viewBox: "0 0 12 12",
59
+ fill: "currentColor",
60
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 10l4-5H2l4 5z" })
61
+ }
62
+ );
63
+ var Table = ({
64
+ manualHeaders,
65
+ manualRowData,
66
+ initialSort,
67
+ height = "100%",
68
+ rowHeight = 40,
69
+ rowsPerPage = 60,
70
+ shouldPaginate = true,
71
+ rowClassName,
72
+ onRowClick,
73
+ minColWidth = 50,
74
+ mobileAutoSizeOnHeaderClick = false,
75
+ mobileBreakpoint = 768,
76
+ columnWidthsStorageKey,
77
+ rowsPerPageOptions = [20, 50, 100],
78
+ onRowsPerPageChange,
79
+ expandedRowId,
80
+ renderExpandedRow,
81
+ renderFullRow
82
+ }) => {
83
+ const [sortConfig, setSortConfig] = react.useState(
84
+ initialSort || null
85
+ );
86
+ const [currentPage, setCurrentPage] = react.useState(1);
87
+ const [columnWidths, setColumnWidths] = react.useState({});
88
+ const [expandedColumns, setExpandedColumns] = react.useState(
89
+ () => /* @__PURE__ */ new Set()
90
+ );
91
+ const initialColumnWidthsRef = react.useRef({});
92
+ const tableRef = react.useRef(null);
93
+ const textMeasureContextRef = react.useRef(null);
94
+ const [isMobile, setIsMobile] = react.useState(() => {
95
+ if (typeof window === "undefined") return false;
96
+ return window.innerWidth < mobileBreakpoint;
97
+ });
98
+ const headers = react.useMemo(() => manualHeaders || [], [manualHeaders]);
99
+ const loadStoredColumnWidths = (fallback) => {
100
+ if (!columnWidthsStorageKey || typeof window === "undefined") {
101
+ return fallback;
102
+ }
103
+ try {
104
+ const raw = window.localStorage.getItem(columnWidthsStorageKey);
105
+ if (!raw) return fallback;
106
+ const parsed = JSON.parse(raw);
107
+ if (!parsed || typeof parsed !== "object") return fallback;
108
+ const next = { ...fallback };
109
+ Object.keys(next).forEach((key) => {
110
+ const val = parsed[key];
111
+ if (typeof val === "number" || typeof val === "string") {
112
+ next[key] = val;
113
+ }
114
+ });
115
+ return next;
116
+ } catch {
117
+ return fallback;
118
+ }
119
+ };
120
+ react.useEffect(() => {
121
+ const initialWidths = {};
122
+ headers.forEach((header) => {
123
+ initialWidths[header.accessor] = header.width;
124
+ });
125
+ initialColumnWidthsRef.current = initialWidths;
126
+ setColumnWidths(
127
+ loadStoredColumnWidths(initialWidths)
128
+ );
129
+ setExpandedColumns(/* @__PURE__ */ new Set());
130
+ }, [headers, columnWidthsStorageKey]);
131
+ react.useEffect(() => {
132
+ if (!columnWidthsStorageKey || typeof window === "undefined") return;
133
+ if (Object.keys(columnWidths).length === 0) return;
134
+ window.localStorage.setItem(
135
+ columnWidthsStorageKey,
136
+ JSON.stringify(columnWidths)
137
+ );
138
+ }, [columnWidths, columnWidthsStorageKey]);
139
+ react.useEffect(() => {
140
+ if (typeof window === "undefined") return void 0;
141
+ const handleResize = () => setIsMobile(window.innerWidth < mobileBreakpoint);
142
+ window.addEventListener("resize", handleResize);
143
+ return () => window.removeEventListener("resize", handleResize);
144
+ }, [mobileBreakpoint]);
145
+ react.useEffect(() => {
146
+ setCurrentPage(1);
147
+ }, [rowsPerPage]);
148
+ const measureTextWidth = (text) => {
149
+ if (typeof document === "undefined") return String(text ?? "").length * 8;
150
+ const ctx = textMeasureContextRef.current || (() => {
151
+ const canvas = document.createElement("canvas");
152
+ const context = canvas.getContext("2d");
153
+ if (tableRef.current && context) {
154
+ const font = window.getComputedStyle(tableRef.current).font;
155
+ context.font = font || "12px sans-serif";
156
+ }
157
+ textMeasureContextRef.current = context;
158
+ return context;
159
+ })();
160
+ return ctx ? ctx.measureText(String(text ?? "")).width : 0;
161
+ };
162
+ const parseWidthValue = (value, fallback) => {
163
+ if (typeof value === "number" && !Number.isNaN(value)) return value;
164
+ if (typeof value === "string") {
165
+ const parsed = parseFloat(value);
166
+ if (!Number.isNaN(parsed)) return parsed;
167
+ }
168
+ return fallback;
169
+ };
170
+ const rows = react.useMemo(() => {
171
+ if (!Array.isArray(manualRowData)) return [];
172
+ const src = manualRowData.filter(Boolean).filter((r) => typeof r === "object");
173
+ const makeSafeId = (full, idx) => {
174
+ const rawId = full?.id;
175
+ const v1 = rawId !== void 0 && rawId !== null && String(rawId).trim() !== "" ? String(rawId).trim() : "";
176
+ const v2 = [
177
+ full?.order_id,
178
+ full?.bom_id,
179
+ full?.bom_workstation_status_id,
180
+ full?.bom_data_id,
181
+ full?.unique_task_info_id,
182
+ full?.order_data_id
183
+ ].filter((v) => v !== void 0 && v !== null && String(v) !== "").join("-");
184
+ return v1 || `${v2}-row${idx}`;
185
+ };
186
+ return src.map((full, idx) => {
187
+ const id = makeSafeId(full, idx);
188
+ const base = { id, "#": idx + 1, _meta: full };
189
+ headers.forEach((h) => {
190
+ if (!["#", "details_meta"].includes(h.accessor)) {
191
+ base[h.accessor] = full?.[h.accessor] ?? "";
192
+ }
193
+ });
194
+ return base;
195
+ });
196
+ }, [manualRowData, headers]);
197
+ const sortedRows = react.useMemo(() => {
198
+ if (!sortConfig || !sortConfig.key) {
199
+ return rows;
200
+ }
201
+ const sortableRows = [...rows];
202
+ sortableRows.sort((a, b) => {
203
+ const aVal = a[sortConfig.key];
204
+ const bVal = b[sortConfig.key];
205
+ if (aVal < bVal) {
206
+ return sortConfig.direction === "asc" ? -1 : 1;
207
+ }
208
+ if (aVal > bVal) {
209
+ return sortConfig.direction === "asc" ? 1 : -1;
210
+ }
211
+ return 0;
212
+ });
213
+ return sortableRows;
214
+ }, [rows, sortConfig]);
215
+ const effectiveShouldPaginate = shouldPaginate && sortedRows.length > rowsPerPage;
216
+ const totalPages = effectiveShouldPaginate ? Math.ceil(sortedRows.length / rowsPerPage) : 1;
217
+ if (currentPage > totalPages && totalPages > 0) {
218
+ setCurrentPage(1);
219
+ }
220
+ const paginatedRows = react.useMemo(() => {
221
+ if (!effectiveShouldPaginate) return sortedRows;
222
+ const startIndex = (currentPage - 1) * rowsPerPage;
223
+ return sortedRows.slice(startIndex, startIndex + rowsPerPage);
224
+ }, [sortedRows, currentPage, rowsPerPage, effectiveShouldPaginate]);
225
+ const handleSort = (key, isSortable) => {
226
+ if (!isSortable) return;
227
+ let direction = "asc";
228
+ if (sortConfig && sortConfig.key === key && sortConfig.direction === "asc") {
229
+ direction = "desc";
230
+ }
231
+ setSortConfig({ key, direction });
232
+ setCurrentPage(1);
233
+ };
234
+ const autoSizeColumn = (colIndex, header) => {
235
+ if (!tableRef.current) return;
236
+ const tableEl = tableRef.current;
237
+ let maxWidth = measureTextWidth(header?.label || "");
238
+ const collectCellWidth = (cell) => {
239
+ if (!cell) return;
240
+ const scrollWidth = cell.scrollWidth || cell.offsetWidth || 0;
241
+ const style = window.getComputedStyle(cell);
242
+ const borderWidth = parseFloat(style.borderLeftWidth || "0") + parseFloat(style.borderRightWidth || "0");
243
+ maxWidth = Math.max(maxWidth, Math.ceil(scrollWidth + borderWidth));
244
+ };
245
+ const headerCell = tableEl.tHead?.rows?.[0]?.cells?.[colIndex] || tableEl.querySelector(`thead th:nth-child(${colIndex + 1})`);
246
+ collectCellWidth(headerCell);
247
+ const bodyRows = tableEl.tBodies?.[0]?.rows || [];
248
+ for (const row of bodyRows) {
249
+ collectCellWidth(row.cells?.[colIndex]);
250
+ }
251
+ rows.forEach((r) => {
252
+ maxWidth = Math.max(
253
+ maxWidth,
254
+ Math.ceil(measureTextWidth(r[header.accessor]))
255
+ );
256
+ });
257
+ const minWidthPx = parseWidthValue(
258
+ header?.minWidth,
259
+ parseWidthValue(minColWidth, 50)
260
+ );
261
+ const finalWidth = Math.max(maxWidth + 12, minWidthPx);
262
+ setColumnWidths((prev) => ({
263
+ ...prev,
264
+ [header.accessor]: `${finalWidth}px`
265
+ }));
266
+ };
267
+ const resetColumnWidth = (accessor) => {
268
+ const regularWidth = initialColumnWidthsRef.current[accessor];
269
+ setColumnWidths((prev) => {
270
+ if (regularWidth === void 0) {
271
+ const next = { ...prev };
272
+ delete next[accessor];
273
+ return next;
274
+ }
275
+ return { ...prev, [accessor]: regularWidth };
276
+ });
277
+ };
278
+ const handleHeaderClick = (header, colIndex) => {
279
+ if (mobileAutoSizeOnHeaderClick && isMobile) {
280
+ const isExpanded = expandedColumns.has(header.accessor);
281
+ if (isExpanded) {
282
+ resetColumnWidth(header.accessor);
283
+ setExpandedColumns((prev) => {
284
+ const next = new Set(prev);
285
+ next.delete(header.accessor);
286
+ return next;
287
+ });
288
+ } else {
289
+ autoSizeColumn(colIndex, header);
290
+ setExpandedColumns((prev) => {
291
+ const next = new Set(prev);
292
+ next.add(header.accessor);
293
+ return next;
294
+ });
295
+ }
296
+ return;
297
+ }
298
+ handleSort(header.accessor, header.isSortable);
299
+ };
300
+ const getSortIcon = (key) => {
301
+ if (mobileAutoSizeOnHeaderClick && isMobile) return null;
302
+ if (!sortConfig || sortConfig.key !== key) {
303
+ return /* @__PURE__ */ jsxRuntime.jsx(SortIcon, { className: "apt-sort-icon" });
304
+ }
305
+ return sortConfig.direction === "asc" ? /* @__PURE__ */ jsxRuntime.jsx(SortUpIcon, { className: "apt-sort-icon apt-sort-icon-active" }) : /* @__PURE__ */ jsxRuntime.jsx(SortDownIcon, { className: "apt-sort-icon apt-sort-icon-active" });
306
+ };
307
+ const handleMouseDown = (e, accessor) => {
308
+ e.preventDefault();
309
+ const startX = e.clientX;
310
+ const th = e.target.closest("th");
311
+ if (!th) return;
312
+ const header = headers.find((h) => h.accessor === accessor);
313
+ const minResizeWidth = parseWidthValue(header?.minWidth, minColWidth);
314
+ const startWidth = th.offsetWidth;
315
+ document.body.style.cursor = "col-resize";
316
+ document.body.style.userSelect = "none";
317
+ const handleMouseMove = (moveEvent) => {
318
+ const deltaX = moveEvent.clientX - startX;
319
+ const newWidth = startWidth + deltaX;
320
+ const finalWidth = Math.max(newWidth, minResizeWidth);
321
+ setColumnWidths((prev) => ({
322
+ ...prev,
323
+ [accessor]: `${finalWidth}px`
324
+ }));
325
+ };
326
+ const handleMouseUp = () => {
327
+ document.body.style.cursor = "";
328
+ document.body.style.userSelect = "";
329
+ document.removeEventListener("mousemove", handleMouseMove);
330
+ document.removeEventListener("mouseup", handleMouseUp);
331
+ };
332
+ document.addEventListener("mousemove", handleMouseMove);
333
+ document.addEventListener("mouseup", handleMouseUp);
334
+ };
335
+ const containerStyle = {
336
+ height: sortedRows.length === 0 ? height : !effectiveShouldPaginate ? "auto" : height,
337
+ maxHeight: !effectiveShouldPaginate ? height : void 0
338
+ };
339
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "apt-table-container", style: containerStyle, children: sortedRows.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "apt-empty-state", children: "No rows to display." }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
340
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "apt-scroll-area", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "apt-table", ref: tableRef, children: [
341
+ /* @__PURE__ */ jsxRuntime.jsx("colgroup", { children: headers.map((header) => /* @__PURE__ */ jsxRuntime.jsx(
342
+ "col",
343
+ {
344
+ style: {
345
+ width: columnWidths[header.accessor],
346
+ minWidth: `${parseWidthValue(
347
+ header.minWidth,
348
+ minColWidth
349
+ )}px`
350
+ }
351
+ },
352
+ `col-${header.accessor}`
353
+ )) }),
354
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "apt-thead", children: /* @__PURE__ */ jsxRuntime.jsx("tr", { children: headers.map((header, idx) => {
355
+ const isHeaderClickable = mobileAutoSizeOnHeaderClick && isMobile || header.isSortable;
356
+ return /* @__PURE__ */ jsxRuntime.jsxs(
357
+ "th",
358
+ {
359
+ onClick: () => handleHeaderClick(header, idx),
360
+ className: `apt-th ${isHeaderClickable ? "apt-th-sortable" : ""}`,
361
+ children: [
362
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "apt-th-content", children: [
363
+ header.label,
364
+ header.isSortable && !(mobileAutoSizeOnHeaderClick && isMobile) && getSortIcon(header.accessor)
365
+ ] }),
366
+ /* @__PURE__ */ jsxRuntime.jsx(
367
+ "div",
368
+ {
369
+ className: "apt-resizer",
370
+ onMouseDown: (e) => {
371
+ e.stopPropagation();
372
+ handleMouseDown(e, header.accessor);
373
+ }
374
+ }
375
+ )
376
+ ]
377
+ },
378
+ header.accessor
379
+ );
380
+ }) }) }),
381
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "apt-tbody", children: paginatedRows.map((row) => {
382
+ const isExpanded = expandedRowId === row.id;
383
+ const isFullRow = typeof renderFullRow === "function" && row?._meta?.fullRow;
384
+ return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
385
+ isFullRow ? /* @__PURE__ */ jsxRuntime.jsx(
386
+ "tr",
387
+ {
388
+ className: `apt-row ${rowClassName ? rowClassName(row) : ""}`,
389
+ onClick: () => onRowClick && onRowClick(row),
390
+ children: /* @__PURE__ */ jsxRuntime.jsx(
391
+ "td",
392
+ {
393
+ colSpan: headers.length,
394
+ className: "apt-td",
395
+ style: { padding: 0 },
396
+ children: renderFullRow(row)
397
+ }
398
+ )
399
+ }
400
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
401
+ "tr",
402
+ {
403
+ className: `apt-row ${rowClassName ? rowClassName(row) : ""}`,
404
+ onClick: () => onRowClick && onRowClick(row),
405
+ style: { height: `${rowHeight}px` },
406
+ children: headers.map((header) => {
407
+ const value = row[header.accessor];
408
+ const cellContent = header.cellRenderer ? header.cellRenderer({ row, value }) : value;
409
+ return /* @__PURE__ */ jsxRuntime.jsx(
410
+ "td",
411
+ {
412
+ className: header.accessor === "actions" ? "apt-td-actions" : "apt-td",
413
+ children: header.accessor === "actions" ? /* @__PURE__ */ jsxRuntime.jsx("div", { onClick: (e) => e.stopPropagation(), children: cellContent }) : cellContent
414
+ },
415
+ `${row.id}-${header.accessor}`
416
+ );
417
+ })
418
+ }
419
+ ),
420
+ isExpanded && typeof renderExpandedRow === "function" && /* @__PURE__ */ jsxRuntime.jsx("tr", { className: "apt-row-expanded", children: /* @__PURE__ */ jsxRuntime.jsx(
421
+ "td",
422
+ {
423
+ colSpan: headers.length,
424
+ className: "apt-td",
425
+ style: { padding: 0 },
426
+ children: renderExpandedRow(row)
427
+ }
428
+ ) })
429
+ ] }, row.id);
430
+ }) })
431
+ ] }) }),
432
+ shouldPaginate && totalPages > 1 || Array.isArray(rowsPerPageOptions) && rowsPerPageOptions.length ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "apt-footer", children: [
433
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "apt-footer-left", children: Array.isArray(rowsPerPageOptions) && rowsPerPageOptions.length > 0 && onRowsPerPageChange && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
434
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "apt-rows-label", children: "Rows" }),
435
+ /* @__PURE__ */ jsxRuntime.jsx(
436
+ "select",
437
+ {
438
+ value: rowsPerPage,
439
+ onChange: (e) => onRowsPerPageChange(Number(e.target.value)),
440
+ className: "apt-rows-select",
441
+ children: rowsPerPageOptions.map((opt) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: opt, children: opt }, opt))
442
+ }
443
+ )
444
+ ] }) }),
445
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "apt-footer-center", children: shouldPaginate && totalPages > 1 ? `Page ${currentPage} of ${totalPages}` : "" }),
446
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "apt-footer-right", children: shouldPaginate && totalPages > 1 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
447
+ /* @__PURE__ */ jsxRuntime.jsx(
448
+ "button",
449
+ {
450
+ onClick: () => setCurrentPage((p) => Math.max(1, p - 1)),
451
+ disabled: currentPage === 1,
452
+ className: "apt-btn",
453
+ children: "Previous"
454
+ }
455
+ ),
456
+ /* @__PURE__ */ jsxRuntime.jsx(
457
+ "button",
458
+ {
459
+ onClick: () => setCurrentPage((p) => Math.min(totalPages, p + 1)),
460
+ disabled: currentPage === totalPages,
461
+ className: "apt-btn",
462
+ children: "Next"
463
+ }
464
+ )
465
+ ] }) : null })
466
+ ] }) : null
467
+ ] }) });
468
+ };
469
+ var Table_default = Table;
470
+ var ViewColumnIcon = ({ className }) => /* @__PURE__ */ jsxRuntime.jsx(
471
+ "svg",
472
+ {
473
+ className,
474
+ width: "18",
475
+ height: "18",
476
+ viewBox: "0 0 24 24",
477
+ fill: "currentColor",
478
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 18h5V5h-5v13zm-6 0h5V5H4v13zM16 5v13h5V5h-5z" })
479
+ }
480
+ );
481
+ var ColumnVisibilityToggle = ({
482
+ availableColumns,
483
+ visibleColumns,
484
+ onColumnsChange,
485
+ storageKey
486
+ }) => {
487
+ const [isOpen, setIsOpen] = react.useState(false);
488
+ const menuRef = react.useRef(null);
489
+ react.useEffect(() => {
490
+ const handleClickOutside = (event) => {
491
+ if (menuRef.current && !menuRef.current.contains(event.target)) {
492
+ setIsOpen(false);
493
+ }
494
+ };
495
+ if (isOpen) {
496
+ document.addEventListener("mousedown", handleClickOutside);
497
+ }
498
+ return () => {
499
+ document.removeEventListener("mousedown", handleClickOutside);
500
+ };
501
+ }, [isOpen]);
502
+ const saveToStorage = (columns) => {
503
+ if (storageKey && typeof window !== "undefined") {
504
+ try {
505
+ window.localStorage.setItem(storageKey, JSON.stringify(columns));
506
+ } catch (error) {
507
+ console.warn(
508
+ "Failed to save column visibility to localStorage:",
509
+ error
510
+ );
511
+ }
512
+ }
513
+ };
514
+ const handleToggleColumn = (columnKey) => {
515
+ const newVisibleColumns = visibleColumns.includes(columnKey) ? visibleColumns.filter((key) => key !== columnKey) : [...visibleColumns, columnKey];
516
+ saveToStorage(newVisibleColumns);
517
+ onColumnsChange(newVisibleColumns);
518
+ };
519
+ const handleSelectAll = () => {
520
+ const allKeys = availableColumns.map((col) => col.key);
521
+ saveToStorage(allKeys);
522
+ onColumnsChange(allKeys);
523
+ };
524
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "apt-column-toggle-container", ref: menuRef, children: [
525
+ /* @__PURE__ */ jsxRuntime.jsxs(
526
+ "button",
527
+ {
528
+ type: "button",
529
+ onClick: () => setIsOpen(!isOpen),
530
+ className: "apt-column-toggle-btn",
531
+ "aria-label": "Toggle column visibility",
532
+ "aria-expanded": isOpen,
533
+ children: [
534
+ /* @__PURE__ */ jsxRuntime.jsx(ViewColumnIcon, { className: "apt-column-toggle-icon" }),
535
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Columns" }),
536
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "apt-column-toggle-count", children: [
537
+ "(",
538
+ visibleColumns.length,
539
+ ")"
540
+ ] })
541
+ ]
542
+ }
543
+ ),
544
+ isOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "apt-column-toggle-menu", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "apt-column-toggle-menu-inner", children: [
545
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "apt-column-toggle-header", children: [
546
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "apt-column-toggle-title", children: "Toggle Columns" }),
547
+ /* @__PURE__ */ jsxRuntime.jsx(
548
+ "button",
549
+ {
550
+ type: "button",
551
+ onClick: handleSelectAll,
552
+ className: "apt-column-toggle-select-all",
553
+ children: "Select All"
554
+ }
555
+ )
556
+ ] }),
557
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "apt-column-toggle-list", children: availableColumns.map((column) => {
558
+ const isVisible = visibleColumns.includes(column.key);
559
+ return /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "apt-column-toggle-item", children: [
560
+ /* @__PURE__ */ jsxRuntime.jsx(
561
+ "input",
562
+ {
563
+ type: "checkbox",
564
+ checked: isVisible,
565
+ onChange: () => handleToggleColumn(column.key),
566
+ className: "apt-column-toggle-checkbox"
567
+ }
568
+ ),
569
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "apt-column-toggle-label", children: column.label })
570
+ ] }, column.key);
571
+ }) })
572
+ ] }) })
573
+ ] });
574
+ };
575
+ var ColumnVisibilityToggle_default = ColumnVisibilityToggle;
576
+
577
+ exports.ColumnVisibilityToggle = ColumnVisibilityToggle_default;
578
+ exports.Table = Table_default;
579
+ //# sourceMappingURL=index.js.map
580
+ //# sourceMappingURL=index.js.map