all-purpose-table 1.0.10 → 1.1.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.mjs CHANGED
@@ -1,4 +1,5 @@
1
- import { useState, useRef, useMemo, useEffect, Fragment as Fragment$1 } from 'react';
1
+ import { useState, useRef, useMemo, useEffect, useLayoutEffect, Fragment as Fragment$1 } from 'react';
2
+ import { createPortal } from 'react-dom';
2
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
4
 
4
5
  // #style-inject:#style-inject
@@ -24,7 +25,239 @@ function styleInject(css, { insertAt } = {}) {
24
25
  }
25
26
 
26
27
  // src/styles.css
27
- styleInject(":root {\n --apt-color-primary: #371f1f;\n --apt-color-border: #d1d5db;\n --apt-color-bg: white;\n --apt-color-bg-secondary: #e5e7eb;\n --apt-color-bg-hover: #f3f4f6;\n --apt-color-text: #1f2937;\n --apt-color-text-muted: #6b7280;\n --apt-color-text-muted-light: #9ca3af;\n --apt-color-accent: #9333ea;\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 --apt-resizer-color: #bbb;\n --apt-resizer-hover-color: #888;\n --apt-th-sortable-hover: #d1d5db;\n --apt-btn-bg: white;\n --apt-btn-hover-bg: #d1d5db;\n}\n@media (prefers-color-scheme: dark) {\n :root {\n --apt-color-primary: #eee;\n --apt-color-border: #333;\n --apt-color-bg: #1e1e1e;\n --apt-color-bg-secondary: #333;\n --apt-color-bg-hover: rgba(126, 126, 126, 0.15);\n --apt-color-text: #eee;\n --apt-color-text-muted: #d1d5db;\n --apt-color-text-muted-light: #444;\n --apt-color-accent: #a855f7;\n --apt-resizer-color: #666;\n --apt-resizer-hover-color: #999;\n --apt-th-sortable-hover: #444;\n --apt-btn-bg: #444;\n --apt-btn-hover-bg: #555;\n }\n}\nhtml.dark,\n.dark,\n:root.dark {\n --apt-color-primary: #eee;\n --apt-color-border: #333;\n --apt-color-bg: #1e1e1e;\n --apt-color-bg-secondary: #333;\n --apt-color-bg-hover: rgba(126, 126, 126, 0.15);\n --apt-color-text: #eee;\n --apt-color-text-muted: #d1d5db;\n --apt-color-text-muted-light: #444;\n --apt-color-accent: #a855f7;\n --apt-resizer-color: #666;\n --apt-resizer-hover-color: #999;\n --apt-th-sortable-hover: #444;\n --apt-btn-bg: #444;\n --apt-btn-hover-bg: #555;\n}\nhtml.light,\n.light,\n:root.light {\n --apt-color-primary: #371f1f;\n --apt-color-border: #d1d5db;\n --apt-color-bg: white;\n --apt-color-bg-secondary: #e5e7eb;\n --apt-color-bg-hover: #f3f4f6;\n --apt-color-text: #1f2937;\n --apt-color-text-muted: #6b7280;\n --apt-color-text-muted-light: #9ca3af;\n --apt-color-accent: #9333ea;\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 --apt-resizer-color: #bbb;\n --apt-resizer-hover-color: #888;\n --apt-th-sortable-hover: #d1d5db;\n --apt-btn-bg: white;\n --apt-btn-hover-bg: #d1d5db;\n}\n.apt-table-container {\n color: var(--apt-color-text);\n border-radius: 6px;\n margin: 0;\n padding: 0;\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.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: var(--apt-color-text-muted-light);\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 table-layout: fixed;\n border-collapse: collapse;\n border-spacing: 0;\n margin: 0;\n padding: 0;\n}\n.apt-thead {\n position: sticky;\n top: 0;\n background-color: var(--apt-color-bg-secondary);\n z-index: 10;\n}\n.apt-th {\n position: relative;\n padding: 12px 8px;\n border: none;\n}\n.apt-th-sortable {\n cursor: pointer;\n}\n.apt-th-sortable:hover {\n background-color: var(--apt-th-sortable-hover);\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: 4px;\n height: 80%;\n width: 3px;\n border-radius: 2px;\n cursor: col-resize;\n user-select: none;\n touch-action: none;\n background-color: var(--apt-resizer-color);\n}\n.apt-resizer:hover,\n.apt-th:hover .apt-resizer {\n background-color: var(--apt-resizer-hover-color);\n}\n.apt-tbody {\n border: none;\n}\n.apt-tbody tr {\n border: none;\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.apt-row-expanded {\n background-color: var(--apt-color-bg-hover);\n}\n.apt-td {\n padding: 4px 8px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n border: none;\n}\n.apt-td-actions {\n padding: 4px 8px;\n border: none;\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.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: var(--apt-color-text);\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: var(--apt-color-text-muted);\n}\n.apt-rows-select {\n padding: 4px 8px;\n font-size: 0.875rem;\n border-radius: 4px;\n background-color: var(--apt-btn-bg);\n color: var(--apt-color-text);\n border: 1px solid var(--apt-color-border);\n}\n.apt-btn {\n padding: 4px 12px;\n font-size: 0.875rem;\n border-radius: 4px;\n background-color: var(--apt-btn-bg);\n color: var(--apt-color-text);\n border: 0;\n cursor: pointer;\n transition: background-color 0.15s;\n}\n.apt-btn:hover:not(:disabled) {\n background-color: var(--apt-btn-hover-bg);\n}\n.apt-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.apt-sort-icon {\n display: inline-block;\n margin-left: 4px;\n width: 14px;\n height: 14px;\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: var(--apt-color-bg-hover);\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: var(--apt-color-bg-secondary);\n}\n.apt-column-toggle-btn:focus {\n outline: none;\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: var(--apt-color-bg);\n box-shadow: var(--apt-shadow-lg);\n z-index: 50;\n max-height: 384px;\n overflow-y: auto;\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 var(--apt-color-border);\n padding-bottom: 8px;\n}\n.apt-column-toggle-title {\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--apt-color-primary);\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.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: var(--apt-color-bg-hover);\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.apt-flex {\n display: flex;\n}\n.apt-items-center {\n align-items: center;\n}\n.apt-gap-2 {\n gap: 8px;\n}\n");
28
+ styleInject(':root {\n --apt-color-primary: #371f1f;\n --apt-color-border: #d1d5db;\n --apt-color-border-subtle: #eceff3;\n --apt-color-bg: white;\n --apt-color-bg-secondary: #e5e7eb;\n --apt-color-bg-hover: #f3f4f6;\n --apt-color-row-stripe: #f9fafb;\n --apt-color-text: #1f2937;\n --apt-color-text-muted: #6b7280;\n --apt-color-text-muted-light: #9ca3af;\n --apt-color-accent: #9333ea;\n --apt-color-accent-soft: rgba(147, 51, 234, 0.12);\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 --apt-resizer-color: #bbb;\n --apt-resizer-hover-color: #888;\n --apt-th-sortable-hover: #d1d5db;\n --apt-btn-bg: white;\n --apt-btn-hover-bg: #d1d5db;\n}\n@media (prefers-color-scheme: dark) {\n :root {\n --apt-color-primary: #eee;\n --apt-color-border: #333;\n --apt-color-border-subtle: #2a2a2a;\n --apt-color-bg: #1e1e1e;\n --apt-color-bg-secondary: #333;\n --apt-color-bg-hover: rgba(126, 126, 126, 0.15);\n --apt-color-row-stripe: rgba(255, 255, 255, 0.03);\n --apt-color-text: #eee;\n --apt-color-text-muted: #d1d5db;\n --apt-color-text-muted-light: #444;\n --apt-color-accent: #a855f7;\n --apt-color-accent-soft: rgba(168, 85, 247, 0.2);\n --apt-resizer-color: #666;\n --apt-resizer-hover-color: #999;\n --apt-th-sortable-hover: #444;\n --apt-btn-bg: #444;\n --apt-btn-hover-bg: #555;\n }\n}\nhtml.dark,\n.dark,\n:root.dark {\n --apt-color-primary: #eee;\n --apt-color-border: #333;\n --apt-color-border-subtle: #2a2a2a;\n --apt-color-bg: #1e1e1e;\n --apt-color-bg-secondary: #333;\n --apt-color-bg-hover: rgba(126, 126, 126, 0.15);\n --apt-color-row-stripe: rgba(255, 255, 255, 0.03);\n --apt-color-text: #eee;\n --apt-color-text-muted: #d1d5db;\n --apt-color-text-muted-light: #444;\n --apt-color-accent: #a855f7;\n --apt-color-accent-soft: rgba(168, 85, 247, 0.2);\n --apt-resizer-color: #666;\n --apt-resizer-hover-color: #999;\n --apt-th-sortable-hover: #444;\n --apt-btn-bg: #444;\n --apt-btn-hover-bg: #555;\n}\nhtml.light,\n.light,\n:root.light {\n --apt-color-primary: #371f1f;\n --apt-color-border: #d1d5db;\n --apt-color-border-subtle: #eceff3;\n --apt-color-bg: white;\n --apt-color-bg-secondary: #e5e7eb;\n --apt-color-bg-hover: #f3f4f6;\n --apt-color-row-stripe: #f9fafb;\n --apt-color-text: #1f2937;\n --apt-color-text-muted: #6b7280;\n --apt-color-text-muted-light: #9ca3af;\n --apt-color-accent: #9333ea;\n --apt-color-accent-soft: rgba(147, 51, 234, 0.12);\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 --apt-resizer-color: #bbb;\n --apt-resizer-hover-color: #888;\n --apt-th-sortable-hover: #d1d5db;\n --apt-btn-bg: white;\n --apt-btn-hover-bg: #d1d5db;\n}\n.apt-table-container {\n color: var(--apt-color-text);\n border-radius: 6px;\n margin: 0;\n padding: 0;\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.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: var(--apt-color-text-muted-light);\n}\n.apt-scroll-area {\n flex-grow: 1;\n overflow: auto;\n}\n.apt-no-matches {\n text-align: center;\n padding: 32px 8px;\n color: var(--apt-color-text-muted-light);\n white-space: normal;\n}\n.apt-table {\n width: 100%;\n text-align: left;\n font-size: 0.75rem;\n table-layout: fixed;\n border-collapse: collapse;\n border-spacing: 0;\n margin: 0;\n padding: 0;\n}\n.apt-thead {\n position: sticky;\n top: 0;\n background-color: var(--apt-color-bg-secondary);\n z-index: 10;\n}\n.apt-th {\n position: relative;\n padding: 10px 12px;\n border: none;\n border-bottom: 2px solid var(--apt-color-border);\n font-weight: 600;\n font-size: 0.7rem;\n letter-spacing: 0.03em;\n text-transform: uppercase;\n color: var(--apt-color-text-muted);\n user-select: none;\n}\n.apt-th-sortable {\n cursor: pointer;\n}\n.apt-th-sortable:hover {\n background-color: var(--apt-th-sortable-hover);\n}\n.apt-th-content {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: 2px;\n}\n.apt-th-label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.apt-resizer {\n position: absolute;\n right: -3px;\n top: 0;\n height: 100%;\n width: 7px;\n cursor: col-resize;\n user-select: none;\n touch-action: none;\n z-index: 2;\n background-color: transparent;\n}\n.apt-resizer::after {\n content: "";\n position: absolute;\n right: 3px;\n top: 20%;\n height: 60%;\n width: 2px;\n border-radius: 2px;\n background-color: transparent;\n transition: background-color 0.15s;\n}\n.apt-th:hover .apt-resizer::after {\n background-color: var(--apt-resizer-color);\n}\n.apt-resizer:hover::after {\n background-color: var(--apt-color-accent);\n}\n.apt-th-spacer,\n.apt-td-spacer {\n padding: 0;\n border: none;\n}\n.apt-tbody {\n border: none;\n}\n.apt-tbody tr {\n border: none;\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.apt-row-expanded {\n background-color: var(--apt-color-bg-hover);\n}\n.apt-td {\n padding: 6px 12px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n border: none;\n}\n.apt-td-actions {\n padding: 6px 12px;\n border: none;\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.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: var(--apt-color-text);\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: var(--apt-color-text-muted);\n}\n.apt-rows-select {\n padding: 4px 8px;\n font-size: 0.875rem;\n border-radius: 4px;\n background-color: var(--apt-btn-bg);\n color: var(--apt-color-text);\n border: 1px solid var(--apt-color-border);\n}\n.apt-btn {\n padding: 4px 12px;\n font-size: 0.875rem;\n border-radius: 4px;\n background-color: var(--apt-btn-bg);\n color: var(--apt-color-text);\n border: 0;\n cursor: pointer;\n transition: background-color 0.15s;\n}\n.apt-btn:hover:not(:disabled) {\n background-color: var(--apt-btn-hover-bg);\n}\n.apt-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.apt-sort-icon {\n display: inline-block;\n margin-left: 4px;\n width: 14px;\n height: 14px;\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: var(--apt-color-bg-hover);\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: var(--apt-color-bg-secondary);\n}\n.apt-column-toggle-btn:focus {\n outline: none;\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: var(--apt-color-bg);\n box-shadow: var(--apt-shadow-lg);\n z-index: 50;\n max-height: 384px;\n overflow-y: auto;\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 var(--apt-color-border);\n padding-bottom: 8px;\n}\n.apt-column-toggle-title {\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--apt-color-primary);\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.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: var(--apt-color-bg-hover);\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.apt-striped .apt-row.apt-row-alt {\n background-color: var(--apt-color-row-stripe);\n}\n.apt-dividers .apt-tbody .apt-row > td {\n border-bottom: 1px solid var(--apt-color-border-subtle);\n}\n.apt-bordered .apt-th:not(.apt-th-spacer),\n.apt-bordered .apt-td:not(.apt-td-spacer) {\n border-right: 1px solid var(--apt-color-border-subtle);\n}\n.apt-bordered .apt-th:not(.apt-th-spacer) {\n border-right-color: var(--apt-color-border);\n}\n.apt-compact .apt-th {\n padding: 6px 8px;\n}\n.apt-compact .apt-td,\n.apt-compact .apt-td-actions {\n padding: 2px 8px;\n}\n.apt-row:hover,\n.apt-striped .apt-row.apt-row-alt:hover {\n background-color: var(--apt-color-bg-hover);\n}\n.apt-filter-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n margin-left: auto;\n padding: 2px;\n width: 18px;\n height: 18px;\n border: none;\n border-radius: 4px;\n background: transparent;\n color: var(--apt-color-text-muted-light);\n cursor: pointer;\n opacity: 0.6;\n transition:\n background-color 0.15s,\n color 0.15s,\n opacity 0.15s;\n}\n.apt-th:hover .apt-filter-btn {\n opacity: 1;\n}\n.apt-filter-btn:hover {\n background-color: var(--apt-color-accent-soft);\n color: var(--apt-color-accent);\n}\n.apt-filter-btn-active {\n opacity: 1;\n color: var(--apt-color-accent);\n background-color: var(--apt-color-accent-soft);\n}\n.apt-filter-icon {\n display: block;\n width: 12px;\n height: 12px;\n}\n.apt-filter-popover {\n position: fixed;\n z-index: 1000;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--apt-color-border);\n border-radius: 8px;\n background-color: var(--apt-color-bg);\n color: var(--apt-color-text);\n box-shadow: var(--apt-shadow-lg);\n padding: 8px;\n font-size: 0.8125rem;\n text-transform: none;\n letter-spacing: normal;\n font-weight: 400;\n}\n.apt-filter-sort-row {\n display: flex;\n gap: 6px;\n margin-bottom: 8px;\n}\n.apt-filter-sort-btn {\n flex: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n padding: 5px 8px;\n border: 1px solid var(--apt-color-border);\n border-radius: 6px;\n background-color: var(--apt-btn-bg);\n color: var(--apt-color-text);\n font-size: 0.75rem;\n cursor: pointer;\n transition: background-color 0.15s, border-color 0.15s;\n}\n.apt-filter-sort-btn:hover {\n background-color: var(--apt-color-bg-hover);\n}\n.apt-filter-sort-btn-active {\n border-color: var(--apt-color-accent);\n color: var(--apt-color-accent);\n background-color: var(--apt-color-accent-soft);\n}\n.apt-filter-sort-icon {\n width: 11px;\n height: 11px;\n}\n.apt-filter-search-wrap {\n margin-bottom: 6px;\n}\n.apt-filter-search {\n width: 100%;\n box-sizing: border-box;\n padding: 6px 8px;\n border: 1px solid var(--apt-color-border);\n border-radius: 6px;\n background-color: var(--apt-color-bg);\n color: var(--apt-color-text);\n font-size: 0.8125rem;\n outline: none;\n}\n.apt-filter-search:focus {\n border-color: var(--apt-color-accent);\n box-shadow: 0 0 0 2px var(--apt-color-accent-soft);\n}\n.apt-filter-list {\n max-height: 200px;\n overflow-y: auto;\n margin: 2px 0;\n}\n.apt-filter-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 6px;\n border-radius: 4px;\n cursor: pointer;\n}\n.apt-filter-item:hover {\n background-color: var(--apt-color-bg-hover);\n}\n.apt-filter-item-all {\n border-bottom: 1px solid var(--apt-color-border-subtle);\n border-radius: 0;\n margin-bottom: 2px;\n padding-bottom: 6px;\n font-weight: 600;\n}\n.apt-filter-checkbox {\n width: 15px;\n height: 15px;\n flex-shrink: 0;\n cursor: pointer;\n accent-color: var(--apt-color-accent);\n}\n.apt-filter-item-label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.apt-filter-empty {\n padding: 12px 6px;\n text-align: center;\n color: var(--apt-color-text-muted);\n font-size: 0.75rem;\n}\n.apt-filter-footer {\n display: flex;\n justify-content: space-between;\n gap: 6px;\n margin-top: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--apt-color-border-subtle);\n}\n.apt-filter-clear {\n padding: 5px 10px;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--apt-color-accent);\n font-size: 0.75rem;\n cursor: pointer;\n}\n.apt-filter-clear:hover:not(:disabled) {\n text-decoration: underline;\n}\n.apt-filter-clear:disabled {\n color: var(--apt-color-text-muted-light);\n cursor: not-allowed;\n}\n.apt-filter-done {\n padding: 5px 14px;\n border: none;\n border-radius: 6px;\n background-color: var(--apt-color-accent);\n color: #fff;\n font-size: 0.75rem;\n cursor: pointer;\n transition: opacity 0.15s;\n}\n.apt-filter-done:hover {\n opacity: 0.9;\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');
29
+ var FilterIcon = ({ className }) => /* @__PURE__ */ jsx(
30
+ "svg",
31
+ {
32
+ className,
33
+ width: "12",
34
+ height: "12",
35
+ viewBox: "0 0 12 12",
36
+ fill: "currentColor",
37
+ children: /* @__PURE__ */ jsx("path", { d: "M1 2h10L7 6.5V11L5 9.5V6.5L1 2z" })
38
+ }
39
+ );
40
+ var SortAscIcon = ({ className }) => /* @__PURE__ */ jsx(
41
+ "svg",
42
+ {
43
+ className,
44
+ width: "12",
45
+ height: "12",
46
+ viewBox: "0 0 12 12",
47
+ fill: "currentColor",
48
+ children: /* @__PURE__ */ jsx("path", { d: "M6 2L2 7h8L6 2z" })
49
+ }
50
+ );
51
+ var SortDescIcon = ({ className }) => /* @__PURE__ */ jsx(
52
+ "svg",
53
+ {
54
+ className,
55
+ width: "12",
56
+ height: "12",
57
+ viewBox: "0 0 12 12",
58
+ fill: "currentColor",
59
+ children: /* @__PURE__ */ jsx("path", { d: "M6 10l4-5H2l4 5z" })
60
+ }
61
+ );
62
+ var POPOVER_WIDTH = 240;
63
+ var ColumnFilter = ({
64
+ columnKey,
65
+ label,
66
+ distinctValues,
67
+ search,
68
+ excluded,
69
+ sortConfig,
70
+ isSortable = true,
71
+ onSort,
72
+ onSearchChange,
73
+ onExcludedChange,
74
+ onClear
75
+ }) => {
76
+ const [open, setOpen] = useState(false);
77
+ const [pos, setPos] = useState(null);
78
+ const buttonRef = useRef(null);
79
+ const popoverRef = useRef(null);
80
+ const masterRef = useRef(null);
81
+ const isActive = search.trim() !== "" || excluded.size > 0;
82
+ const sortDir = sortConfig && sortConfig.key === columnKey ? sortConfig.direction : null;
83
+ const visibleValues = useMemo(() => {
84
+ const q = search.trim().toLowerCase();
85
+ if (!q) return distinctValues;
86
+ return distinctValues.filter((v) => v.toLowerCase().includes(q));
87
+ }, [distinctValues, search]);
88
+ const allVisibleSelected = visibleValues.length > 0 && visibleValues.every((v) => !excluded.has(v));
89
+ const someVisibleSelected = visibleValues.some((v) => !excluded.has(v));
90
+ useLayoutEffect(() => {
91
+ if (!open || !buttonRef.current) return;
92
+ const rect = buttonRef.current.getBoundingClientRect();
93
+ let left = rect.right - POPOVER_WIDTH;
94
+ const maxLeft = window.innerWidth - POPOVER_WIDTH - 8;
95
+ if (left > maxLeft) left = maxLeft;
96
+ if (left < 8) left = 8;
97
+ setPos({ top: rect.bottom + 6, left });
98
+ }, [open]);
99
+ useEffect(() => {
100
+ if (masterRef.current) {
101
+ masterRef.current.indeterminate = someVisibleSelected && !allVisibleSelected;
102
+ }
103
+ }, [someVisibleSelected, allVisibleSelected, open]);
104
+ useEffect(() => {
105
+ if (!open) return void 0;
106
+ const onDown = (e) => {
107
+ const target = e.target;
108
+ if (popoverRef.current?.contains(target)) return;
109
+ if (buttonRef.current?.contains(target)) return;
110
+ setOpen(false);
111
+ };
112
+ const onKey = (e) => {
113
+ if (e.key === "Escape") setOpen(false);
114
+ };
115
+ const onScroll = () => setOpen(false);
116
+ document.addEventListener("mousedown", onDown);
117
+ document.addEventListener("keydown", onKey);
118
+ window.addEventListener("scroll", onScroll, true);
119
+ window.addEventListener("resize", onScroll);
120
+ return () => {
121
+ document.removeEventListener("mousedown", onDown);
122
+ document.removeEventListener("keydown", onKey);
123
+ window.removeEventListener("scroll", onScroll, true);
124
+ window.removeEventListener("resize", onScroll);
125
+ };
126
+ }, [open]);
127
+ const toggleValue = (value) => {
128
+ const next = new Set(excluded);
129
+ if (next.has(value)) next.delete(value);
130
+ else next.add(value);
131
+ onExcludedChange(next);
132
+ };
133
+ const toggleAllVisible = () => {
134
+ const next = new Set(excluded);
135
+ if (allVisibleSelected) {
136
+ visibleValues.forEach((v) => next.add(v));
137
+ } else {
138
+ visibleValues.forEach((v) => next.delete(v));
139
+ }
140
+ onExcludedChange(next);
141
+ };
142
+ const handleClear = () => {
143
+ onClear();
144
+ };
145
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
146
+ /* @__PURE__ */ jsx(
147
+ "button",
148
+ {
149
+ ref: buttonRef,
150
+ type: "button",
151
+ className: `apt-filter-btn ${isActive ? "apt-filter-btn-active" : ""}`,
152
+ "aria-label": `Filter ${label}`,
153
+ "aria-expanded": open,
154
+ onClick: (e) => {
155
+ e.stopPropagation();
156
+ setOpen((v) => !v);
157
+ },
158
+ children: /* @__PURE__ */ jsx(FilterIcon, { className: "apt-filter-icon" })
159
+ }
160
+ ),
161
+ open && pos && typeof document !== "undefined" && createPortal(
162
+ /* @__PURE__ */ jsxs(
163
+ "div",
164
+ {
165
+ ref: popoverRef,
166
+ className: "apt-filter-popover",
167
+ style: { top: pos.top, left: pos.left, width: POPOVER_WIDTH },
168
+ onClick: (e) => e.stopPropagation(),
169
+ children: [
170
+ isSortable && /* @__PURE__ */ jsxs("div", { className: "apt-filter-sort-row", children: [
171
+ /* @__PURE__ */ jsxs(
172
+ "button",
173
+ {
174
+ type: "button",
175
+ className: `apt-filter-sort-btn ${sortDir === "asc" ? "apt-filter-sort-btn-active" : ""}`,
176
+ onClick: () => onSort("asc"),
177
+ children: [
178
+ /* @__PURE__ */ jsx(SortAscIcon, { className: "apt-filter-sort-icon" }),
179
+ /* @__PURE__ */ jsx("span", { children: "Asc" })
180
+ ]
181
+ }
182
+ ),
183
+ /* @__PURE__ */ jsxs(
184
+ "button",
185
+ {
186
+ type: "button",
187
+ className: `apt-filter-sort-btn ${sortDir === "desc" ? "apt-filter-sort-btn-active" : ""}`,
188
+ onClick: () => onSort("desc"),
189
+ children: [
190
+ /* @__PURE__ */ jsx(SortDescIcon, { className: "apt-filter-sort-icon" }),
191
+ /* @__PURE__ */ jsx("span", { children: "Desc" })
192
+ ]
193
+ }
194
+ )
195
+ ] }),
196
+ /* @__PURE__ */ jsx("div", { className: "apt-filter-search-wrap", children: /* @__PURE__ */ jsx(
197
+ "input",
198
+ {
199
+ type: "text",
200
+ className: "apt-filter-search",
201
+ placeholder: "Search\u2026",
202
+ value: search,
203
+ autoFocus: true,
204
+ onChange: (e) => onSearchChange(e.target.value)
205
+ }
206
+ ) }),
207
+ /* @__PURE__ */ jsxs("label", { className: "apt-filter-item apt-filter-item-all", children: [
208
+ /* @__PURE__ */ jsx(
209
+ "input",
210
+ {
211
+ ref: masterRef,
212
+ type: "checkbox",
213
+ className: "apt-filter-checkbox",
214
+ checked: allVisibleSelected,
215
+ onChange: toggleAllVisible
216
+ }
217
+ ),
218
+ /* @__PURE__ */ jsx("span", { className: "apt-filter-item-label", children: search.trim() ? "Select all (filtered)" : "Select all" })
219
+ ] }),
220
+ /* @__PURE__ */ jsx("div", { className: "apt-filter-list", children: visibleValues.length === 0 ? /* @__PURE__ */ jsx("div", { className: "apt-filter-empty", children: "No matches" }) : visibleValues.map((value) => /* @__PURE__ */ jsxs("label", { className: "apt-filter-item", children: [
221
+ /* @__PURE__ */ jsx(
222
+ "input",
223
+ {
224
+ type: "checkbox",
225
+ className: "apt-filter-checkbox",
226
+ checked: !excluded.has(value),
227
+ onChange: () => toggleValue(value)
228
+ }
229
+ ),
230
+ /* @__PURE__ */ jsx("span", { className: "apt-filter-item-label", title: value, children: value === "" ? "(Blanks)" : value })
231
+ ] }, value)) }),
232
+ /* @__PURE__ */ jsxs("div", { className: "apt-filter-footer", children: [
233
+ /* @__PURE__ */ jsx(
234
+ "button",
235
+ {
236
+ type: "button",
237
+ className: "apt-filter-clear",
238
+ onClick: handleClear,
239
+ disabled: !isActive,
240
+ children: "Clear filter"
241
+ }
242
+ ),
243
+ /* @__PURE__ */ jsx(
244
+ "button",
245
+ {
246
+ type: "button",
247
+ className: "apt-filter-done",
248
+ onClick: () => setOpen(false),
249
+ children: "Done"
250
+ }
251
+ )
252
+ ] })
253
+ ]
254
+ }
255
+ ),
256
+ document.body
257
+ )
258
+ ] });
259
+ };
260
+ var ColumnFilter_default = ColumnFilter;
28
261
  var SortIcon = ({ className }) => /* @__PURE__ */ jsx(
29
262
  "svg",
30
263
  {
@@ -58,21 +291,31 @@ var SortDownIcon = ({ className }) => /* @__PURE__ */ jsx(
58
291
  children: /* @__PURE__ */ jsx("path", { d: "M6 10l4-5H2l4 5z" })
59
292
  }
60
293
  );
294
+ function parseNumericWidth(value) {
295
+ if (typeof value === "number" && !Number.isNaN(value)) return value;
296
+ if (typeof value === "string") {
297
+ const parsed = parseFloat(value);
298
+ if (!Number.isNaN(parsed)) return parsed;
299
+ }
300
+ return null;
301
+ }
61
302
  function loadStoredColumnWidths(columnWidthsStorageKey, fallback) {
62
- if (!columnWidthsStorageKey || typeof window === "undefined") return fallback;
303
+ if (!columnWidthsStorageKey || typeof window === "undefined")
304
+ return { widths: fallback, hadStored: false };
63
305
  try {
64
306
  const raw = window.localStorage.getItem(columnWidthsStorageKey);
65
- if (!raw) return fallback;
307
+ if (!raw) return { widths: fallback, hadStored: false };
66
308
  const parsed = JSON.parse(raw);
67
- if (!parsed || typeof parsed !== "object") return fallback;
309
+ if (!parsed || typeof parsed !== "object")
310
+ return { widths: fallback, hadStored: false };
68
311
  const next = { ...fallback };
69
- Object.keys(next).forEach((key) => {
70
- const val = parsed[key];
71
- if (typeof val === "number" || typeof val === "string") next[key] = val;
312
+ Object.keys(parsed).forEach((key) => {
313
+ const num = parseNumericWidth(parsed[key]);
314
+ if (num !== null) next[key] = num;
72
315
  });
73
- return next;
316
+ return { widths: next, hadStored: true };
74
317
  } catch {
75
- return fallback;
318
+ return { widths: fallback, hadStored: false };
76
319
  }
77
320
  }
78
321
  var Table = ({
@@ -93,17 +336,25 @@ var Table = ({
93
336
  onRowsPerPageChange,
94
337
  expandedRowId,
95
338
  renderExpandedRow,
96
- renderFullRow
339
+ renderFullRow,
340
+ filterable = false,
341
+ striped = false,
342
+ dividers = false,
343
+ bordered = false,
344
+ density = "default"
97
345
  }) => {
98
346
  const [sortConfig, setSortConfig] = useState(
99
347
  initialSort || null
100
348
  );
101
349
  const [currentPage, setCurrentPage] = useState(1);
102
350
  const [columnWidths, setColumnWidths] = useState({});
351
+ const [columnsFrozen, setColumnsFrozen] = useState(false);
352
+ const [columnFilters, setColumnFilters] = useState({});
103
353
  const [expandedColumns, setExpandedColumns] = useState(
104
354
  () => /* @__PURE__ */ new Set()
105
355
  );
106
356
  const initialColumnWidthsRef = useRef({});
357
+ const suppressHeaderClickRef = useRef(false);
107
358
  const tableRef = useRef(null);
108
359
  const textMeasureContextRef = useRef(null);
109
360
  const [isMobile, setIsMobile] = useState(() => {
@@ -114,15 +365,34 @@ var Table = ({
114
365
  useEffect(() => {
115
366
  const initialWidths = {};
116
367
  headers.forEach((header) => {
117
- initialWidths[header.accessor] = header.width;
368
+ const w = parseNumericWidth(header.width);
369
+ if (w !== null) initialWidths[header.accessor] = w;
118
370
  });
119
371
  initialColumnWidthsRef.current = initialWidths;
120
- setColumnWidths(
121
- loadStoredColumnWidths(columnWidthsStorageKey, initialWidths)
372
+ const { widths, hadStored } = loadStoredColumnWidths(
373
+ columnWidthsStorageKey,
374
+ initialWidths
122
375
  );
376
+ setColumnWidths(widths);
377
+ setColumnsFrozen(hadStored);
123
378
  setExpandedColumns(/* @__PURE__ */ new Set());
379
+ setColumnFilters({});
124
380
  setCurrentPage(1);
125
381
  }, [headers, columnWidthsStorageKey]);
382
+ useLayoutEffect(() => {
383
+ if (!columnsFrozen || !tableRef.current) return;
384
+ const missing = headers.some((h) => columnWidths[h.accessor] == null);
385
+ if (!missing) return;
386
+ const cells = tableRef.current.tHead?.rows?.[0]?.cells;
387
+ const next = { ...columnWidths };
388
+ headers.forEach((header, idx) => {
389
+ if (next[header.accessor] == null) {
390
+ const cell = cells?.[idx];
391
+ if (cell) next[header.accessor] = cell.offsetWidth;
392
+ }
393
+ });
394
+ setColumnWidths(next);
395
+ }, [columnsFrozen, headers, columnWidths]);
126
396
  useEffect(() => {
127
397
  if (!columnWidthsStorageKey || typeof window === "undefined") return;
128
398
  if (Object.keys(columnWidths).length === 0) return;
@@ -151,14 +421,6 @@ var Table = ({
151
421
  })();
152
422
  return ctx ? ctx.measureText(String(text ?? "")).width : 0;
153
423
  };
154
- const parseWidthValue = (value, fallback) => {
155
- if (typeof value === "number" && !Number.isNaN(value)) return value;
156
- if (typeof value === "string") {
157
- const parsed = parseFloat(value);
158
- if (!Number.isNaN(parsed)) return parsed;
159
- }
160
- return fallback;
161
- };
162
424
  const rows = useMemo(() => {
163
425
  if (!Array.isArray(manualRowData)) return [];
164
426
  const src = manualRowData.filter(Boolean).filter((r) => typeof r === "object");
@@ -186,11 +448,43 @@ var Table = ({
186
448
  return base;
187
449
  });
188
450
  }, [manualRowData, headers]);
451
+ const distinctValuesByColumn = useMemo(() => {
452
+ const map = {};
453
+ const anyFilterable = headers.some((h) => h.isFilterable ?? filterable);
454
+ if (!anyFilterable) return map;
455
+ headers.forEach((header) => {
456
+ if (!(header.isFilterable ?? filterable)) return;
457
+ const set = /* @__PURE__ */ new Set();
458
+ rows.forEach((r) => set.add(String(r[header.accessor] ?? "")));
459
+ const arr = Array.from(set);
460
+ arr.sort(
461
+ (a, b) => a.localeCompare(b, void 0, { numeric: true, sensitivity: "base" })
462
+ );
463
+ map[header.accessor] = arr;
464
+ });
465
+ return map;
466
+ }, [rows, headers, filterable]);
467
+ const filteredRows = useMemo(() => {
468
+ const active = Object.entries(columnFilters).filter(
469
+ ([, f]) => f.search.trim() !== "" || f.excluded.size > 0
470
+ );
471
+ if (active.length === 0) return rows;
472
+ return rows.filter(
473
+ (row) => active.every(([accessor, filter]) => {
474
+ const val = String(row[accessor] ?? "");
475
+ if (filter.search.trim() !== "" && !val.toLowerCase().includes(filter.search.trim().toLowerCase())) {
476
+ return false;
477
+ }
478
+ if (filter.excluded.size > 0 && filter.excluded.has(val)) return false;
479
+ return true;
480
+ })
481
+ );
482
+ }, [rows, columnFilters]);
189
483
  const sortedRows = useMemo(() => {
190
484
  if (!sortConfig || !sortConfig.key) {
191
- return rows;
485
+ return filteredRows;
192
486
  }
193
- const sortableRows = [...rows];
487
+ const sortableRows = [...filteredRows];
194
488
  sortableRows.sort((a, b) => {
195
489
  const aVal = a[sortConfig.key];
196
490
  const bVal = b[sortConfig.key];
@@ -203,7 +497,7 @@ var Table = ({
203
497
  return 0;
204
498
  });
205
499
  return sortableRows;
206
- }, [rows, sortConfig]);
500
+ }, [filteredRows, sortConfig]);
207
501
  const effectiveShouldPaginate = shouldPaginate && sortedRows.length > rowsPerPage;
208
502
  const totalPages = effectiveShouldPaginate ? Math.ceil(sortedRows.length / rowsPerPage) : 1;
209
503
  const safePage = totalPages > 0 ? Math.min(currentPage, totalPages) : 1;
@@ -221,6 +515,50 @@ var Table = ({
221
515
  setSortConfig({ key, direction });
222
516
  setCurrentPage(1);
223
517
  };
518
+ const setColumnSearch = (accessor, value) => {
519
+ setColumnFilters((prev) => ({
520
+ ...prev,
521
+ [accessor]: {
522
+ search: value,
523
+ excluded: prev[accessor]?.excluded ?? /* @__PURE__ */ new Set()
524
+ }
525
+ }));
526
+ setCurrentPage(1);
527
+ };
528
+ const setColumnExcluded = (accessor, next) => {
529
+ setColumnFilters((prev) => ({
530
+ ...prev,
531
+ [accessor]: {
532
+ search: prev[accessor]?.search ?? "",
533
+ excluded: next
534
+ }
535
+ }));
536
+ setCurrentPage(1);
537
+ };
538
+ const clearColumnFilter = (accessor) => {
539
+ setColumnFilters((prev) => {
540
+ if (!prev[accessor]) return prev;
541
+ const next = { ...prev };
542
+ delete next[accessor];
543
+ return next;
544
+ });
545
+ setCurrentPage(1);
546
+ };
547
+ const setColumnSort = (accessor, direction) => {
548
+ setSortConfig({ key: accessor, direction });
549
+ setCurrentPage(1);
550
+ };
551
+ const freezeCurrentWidths = () => {
552
+ const next = { ...columnWidths };
553
+ const cells = tableRef.current?.tHead?.rows?.[0]?.cells;
554
+ headers.forEach((header, idx) => {
555
+ if (next[header.accessor] == null) {
556
+ const cell = cells?.[idx];
557
+ if (cell) next[header.accessor] = cell.offsetWidth;
558
+ }
559
+ });
560
+ return next;
561
+ };
224
562
  const autoSizeColumn = (colIndex, header) => {
225
563
  if (!tableRef.current) return;
226
564
  const tableEl = tableRef.current;
@@ -244,15 +582,11 @@ var Table = ({
244
582
  Math.ceil(measureTextWidth(r[header.accessor]))
245
583
  );
246
584
  });
247
- const minWidthPx = parseWidthValue(
248
- header?.minWidth,
249
- parseWidthValue(minColWidth, 50)
250
- );
585
+ const minWidthPx = parseNumericWidth(header?.minWidth) ?? minColWidth;
251
586
  const finalWidth = Math.max(maxWidth + 12, minWidthPx);
252
- setColumnWidths((prev) => ({
253
- ...prev,
254
- [header.accessor]: `${finalWidth}px`
255
- }));
587
+ const frozen = freezeCurrentWidths();
588
+ setColumnsFrozen(true);
589
+ setColumnWidths({ ...frozen, [header.accessor]: finalWidth });
256
590
  };
257
591
  const resetColumnWidth = (accessor) => {
258
592
  const regularWidth = initialColumnWidthsRef.current[accessor];
@@ -266,6 +600,10 @@ var Table = ({
266
600
  });
267
601
  };
268
602
  const handleHeaderClick = (header, colIndex) => {
603
+ if (suppressHeaderClickRef.current) {
604
+ suppressHeaderClickRef.current = false;
605
+ return;
606
+ }
269
607
  if (mobileAutoSizeOnHeaderClick && isMobile) {
270
608
  const isExpanded = expandedColumns.has(header.accessor);
271
609
  if (isExpanded) {
@@ -296,12 +634,16 @@ var Table = ({
296
634
  };
297
635
  const handleMouseDown = (e, accessor) => {
298
636
  e.preventDefault();
637
+ suppressHeaderClickRef.current = true;
299
638
  const startX = e.clientX;
300
639
  const th = e.target.closest("th");
301
640
  if (!th) return;
302
641
  const header = headers.find((h) => h.accessor === accessor);
303
- const minResizeWidth = parseWidthValue(header?.minWidth, minColWidth);
304
- const startWidth = th.offsetWidth;
642
+ const minResizeWidth = parseNumericWidth(header?.minWidth) ?? minColWidth;
643
+ const frozen = freezeCurrentWidths();
644
+ const startWidth = frozen[accessor] ?? th.offsetWidth;
645
+ setColumnsFrozen(true);
646
+ setColumnWidths(frozen);
305
647
  document.body.style.cursor = "col-resize";
306
648
  document.body.style.userSelect = "none";
307
649
  const handleMouseMove = (moveEvent) => {
@@ -310,7 +652,7 @@ var Table = ({
310
652
  const finalWidth = Math.max(newWidth, minResizeWidth);
311
653
  setColumnWidths((prev) => ({
312
654
  ...prev,
313
- [accessor]: `${finalWidth}px`
655
+ [accessor]: finalWidth
314
656
  }));
315
657
  };
316
658
  const handleMouseUp = () => {
@@ -318,106 +660,147 @@ var Table = ({
318
660
  document.body.style.userSelect = "";
319
661
  document.removeEventListener("mousemove", handleMouseMove);
320
662
  document.removeEventListener("mouseup", handleMouseUp);
663
+ window.setTimeout(() => {
664
+ suppressHeaderClickRef.current = false;
665
+ }, 0);
321
666
  };
322
667
  document.addEventListener("mousemove", handleMouseMove);
323
668
  document.addEventListener("mouseup", handleMouseUp);
324
669
  };
670
+ const containerClassName = [
671
+ "apt-table-container",
672
+ striped && "apt-striped",
673
+ dividers && "apt-dividers",
674
+ bordered && "apt-bordered",
675
+ density === "compact" && "apt-compact"
676
+ ].filter(Boolean).join(" ");
677
+ const noData = rows.length === 0;
678
+ const noMatches = !noData && sortedRows.length === 0;
325
679
  const containerStyle = {
326
- height: sortedRows.length === 0 ? height : !effectiveShouldPaginate ? "auto" : height,
680
+ height: noData ? height : !effectiveShouldPaginate ? "auto" : height,
327
681
  maxHeight: !effectiveShouldPaginate ? height : void 0
328
682
  };
329
- return /* @__PURE__ */ jsx("div", { className: "apt-table-container", style: containerStyle, children: sortedRows.length === 0 ? /* @__PURE__ */ jsx("div", { className: "apt-empty-state", children: "No rows to display." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
683
+ const spanCount = headers.length + (columnsFrozen ? 1 : 0);
684
+ return /* @__PURE__ */ jsx("div", { className: containerClassName, style: containerStyle, children: noData ? /* @__PURE__ */ jsx("div", { className: "apt-empty-state", children: "No rows to display." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
330
685
  /* @__PURE__ */ jsx("div", { className: "apt-scroll-area", children: /* @__PURE__ */ jsxs("table", { className: "apt-table", ref: tableRef, children: [
331
- /* @__PURE__ */ jsx("colgroup", { children: headers.map((header) => /* @__PURE__ */ jsx(
332
- "col",
333
- {
334
- style: {
335
- width: columnWidths[header.accessor],
336
- minWidth: `${parseWidthValue(
337
- header.minWidth,
338
- minColWidth
339
- )}px`
340
- }
341
- },
342
- `col-${header.accessor}`
343
- )) }),
344
- /* @__PURE__ */ jsx("thead", { className: "apt-thead", children: /* @__PURE__ */ jsx("tr", { children: headers.map((header, idx) => {
345
- const isHeaderClickable = mobileAutoSizeOnHeaderClick && isMobile || header.isSortable;
346
- return /* @__PURE__ */ jsxs(
347
- "th",
686
+ /* @__PURE__ */ jsxs("colgroup", { children: [
687
+ headers.map((header) => /* @__PURE__ */ jsx(
688
+ "col",
348
689
  {
349
- onClick: () => handleHeaderClick(header, idx),
350
- className: `apt-th ${isHeaderClickable ? "apt-th-sortable" : ""}`,
351
- children: [
352
- /* @__PURE__ */ jsxs("div", { className: "apt-th-content", children: [
353
- header.label,
354
- header.isSortable && !(mobileAutoSizeOnHeaderClick && isMobile) && getSortIcon(header.accessor)
355
- ] }),
356
- /* @__PURE__ */ jsx(
357
- "div",
358
- {
359
- className: "apt-resizer",
360
- onMouseDown: (e) => {
361
- e.stopPropagation();
362
- handleMouseDown(e, header.accessor);
363
- }
364
- }
365
- )
366
- ]
367
- },
368
- header.accessor
369
- );
370
- }) }) }),
371
- /* @__PURE__ */ jsx("tbody", { className: "apt-tbody", children: paginatedRows.map((row) => {
372
- const isExpanded = expandedRowId === row.id;
373
- const isFullRow = typeof renderFullRow === "function" && row?._meta?.fullRow;
374
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [
375
- isFullRow ? /* @__PURE__ */ jsx(
376
- "tr",
377
- {
378
- className: `apt-row ${rowClassName ? rowClassName(row) : ""}`,
379
- onClick: () => onRowClick && onRowClick(row),
380
- children: /* @__PURE__ */ jsx(
381
- "td",
382
- {
383
- colSpan: headers.length,
384
- className: "apt-td",
385
- style: { padding: 0 },
386
- children: renderFullRow(row)
387
- }
388
- )
690
+ style: {
691
+ width: columnWidths[header.accessor] != null ? `${columnWidths[header.accessor]}px` : void 0,
692
+ minWidth: `${parseNumericWidth(header.minWidth) ?? minColWidth}px`
389
693
  }
390
- ) : /* @__PURE__ */ jsx(
391
- "tr",
694
+ },
695
+ `col-${header.accessor}`
696
+ )),
697
+ columnsFrozen && /* @__PURE__ */ jsx("col", { className: "apt-col-spacer" })
698
+ ] }),
699
+ /* @__PURE__ */ jsx("thead", { className: "apt-thead", children: /* @__PURE__ */ jsxs("tr", { children: [
700
+ headers.map((header, idx) => {
701
+ const columnFilterable = header.isFilterable ?? filterable;
702
+ const isHeaderClickable = mobileAutoSizeOnHeaderClick && isMobile || header.isSortable;
703
+ return /* @__PURE__ */ jsxs(
704
+ "th",
392
705
  {
393
- className: `apt-row ${rowClassName ? rowClassName(row) : ""}`,
394
- onClick: () => onRowClick && onRowClick(row),
395
- style: { height: `${rowHeight}px` },
396
- children: headers.map((header) => {
397
- const value = row[header.accessor];
398
- const cellContent = header.cellRenderer ? header.cellRenderer({ row, value }) : value;
399
- return /* @__PURE__ */ jsx(
706
+ onClick: () => handleHeaderClick(header, idx),
707
+ className: `apt-th ${isHeaderClickable ? "apt-th-sortable" : ""}`,
708
+ children: [
709
+ /* @__PURE__ */ jsxs("div", { className: "apt-th-content", children: [
710
+ /* @__PURE__ */ jsx("span", { className: "apt-th-label", children: header.label }),
711
+ header.isSortable && !(mobileAutoSizeOnHeaderClick && isMobile) && getSortIcon(header.accessor),
712
+ columnFilterable && /* @__PURE__ */ jsx(
713
+ ColumnFilter_default,
714
+ {
715
+ columnKey: header.accessor,
716
+ label: header.label,
717
+ distinctValues: distinctValuesByColumn[header.accessor] || [],
718
+ search: columnFilters[header.accessor]?.search ?? "",
719
+ excluded: columnFilters[header.accessor]?.excluded ?? /* @__PURE__ */ new Set(),
720
+ sortConfig,
721
+ isSortable: header.isSortable,
722
+ onSort: (dir) => setColumnSort(header.accessor, dir),
723
+ onSearchChange: (value) => setColumnSearch(header.accessor, value),
724
+ onExcludedChange: (next) => setColumnExcluded(header.accessor, next),
725
+ onClear: () => clearColumnFilter(header.accessor)
726
+ }
727
+ )
728
+ ] }),
729
+ /* @__PURE__ */ jsx(
730
+ "div",
731
+ {
732
+ className: "apt-resizer",
733
+ onMouseDown: (e) => {
734
+ e.stopPropagation();
735
+ handleMouseDown(e, header.accessor);
736
+ },
737
+ onClick: (e) => e.stopPropagation()
738
+ }
739
+ )
740
+ ]
741
+ },
742
+ header.accessor
743
+ );
744
+ }),
745
+ columnsFrozen && /* @__PURE__ */ jsx("th", { className: "apt-th apt-th-spacer", "aria-hidden": "true" })
746
+ ] }) }),
747
+ /* @__PURE__ */ jsxs("tbody", { className: "apt-tbody", children: [
748
+ noMatches && /* @__PURE__ */ jsx("tr", { className: "apt-row", children: /* @__PURE__ */ jsx("td", { colSpan: spanCount, className: "apt-td apt-no-matches", children: "No rows match the current filters." }) }),
749
+ paginatedRows.map((row, rowIdx) => {
750
+ const isExpanded = expandedRowId === row.id;
751
+ const isFullRow = typeof renderFullRow === "function" && row?._meta?.fullRow;
752
+ const altClass = rowIdx % 2 === 1 ? "apt-row-alt" : "";
753
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
754
+ isFullRow ? /* @__PURE__ */ jsx(
755
+ "tr",
756
+ {
757
+ className: `apt-row ${altClass} ${rowClassName ? rowClassName(row) : ""}`,
758
+ onClick: () => onRowClick && onRowClick(row),
759
+ children: /* @__PURE__ */ jsx(
400
760
  "td",
401
761
  {
402
- className: header.accessor === "actions" ? "apt-td-actions" : "apt-td",
403
- children: header.accessor === "actions" ? /* @__PURE__ */ jsx("div", { onClick: (e) => e.stopPropagation(), children: cellContent }) : cellContent
404
- },
405
- `${row.id}-${header.accessor}`
406
- );
407
- })
408
- }
409
- ),
410
- isExpanded && typeof renderExpandedRow === "function" && /* @__PURE__ */ jsx("tr", { className: "apt-row-expanded", children: /* @__PURE__ */ jsx(
411
- "td",
412
- {
413
- colSpan: headers.length,
414
- className: "apt-td",
415
- style: { padding: 0 },
416
- children: renderExpandedRow(row)
417
- }
418
- ) })
419
- ] }, row.id);
420
- }) })
762
+ colSpan: spanCount,
763
+ className: "apt-td",
764
+ style: { padding: 0 },
765
+ children: renderFullRow(row)
766
+ }
767
+ )
768
+ }
769
+ ) : /* @__PURE__ */ jsxs(
770
+ "tr",
771
+ {
772
+ className: `apt-row ${altClass} ${rowClassName ? rowClassName(row) : ""}`,
773
+ onClick: () => onRowClick && onRowClick(row),
774
+ style: { height: `${rowHeight}px` },
775
+ children: [
776
+ headers.map((header) => {
777
+ const value = row[header.accessor];
778
+ const cellContent = header.cellRenderer ? header.cellRenderer({ row, value }) : value;
779
+ return /* @__PURE__ */ jsx(
780
+ "td",
781
+ {
782
+ className: header.accessor === "actions" ? "apt-td-actions" : "apt-td",
783
+ children: header.accessor === "actions" ? /* @__PURE__ */ jsx("div", { onClick: (e) => e.stopPropagation(), children: cellContent }) : cellContent
784
+ },
785
+ `${row.id}-${header.accessor}`
786
+ );
787
+ }),
788
+ columnsFrozen && /* @__PURE__ */ jsx("td", { className: "apt-td apt-td-spacer", "aria-hidden": "true" })
789
+ ]
790
+ }
791
+ ),
792
+ isExpanded && typeof renderExpandedRow === "function" && /* @__PURE__ */ jsx("tr", { className: "apt-row-expanded", children: /* @__PURE__ */ jsx(
793
+ "td",
794
+ {
795
+ colSpan: spanCount,
796
+ className: "apt-td",
797
+ style: { padding: 0 },
798
+ children: renderExpandedRow(row)
799
+ }
800
+ ) })
801
+ ] }, row.id);
802
+ })
803
+ ] })
421
804
  ] }) }),
422
805
  shouldPaginate && totalPages > 1 || Array.isArray(rowsPerPageOptions) && rowsPerPageOptions.length > 0 && onRowsPerPageChange ? /* @__PURE__ */ jsxs("div", { className: "apt-footer", children: [
423
806
  /* @__PURE__ */ jsx("div", { className: "apt-footer-left", children: Array.isArray(rowsPerPageOptions) && rowsPerPageOptions.length > 0 && onRowsPerPageChange && /* @__PURE__ */ jsxs(Fragment, { children: [