snice 7.8.0 → 7.9.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/README.md +1 -1
- package/adapters/react/SniceProvider.js +1 -1
- package/adapters/react/SniceRouter.js +1 -1
- package/adapters/react/matchRoute.js +1 -1
- package/adapters/react/table.d.ts +1 -0
- package/adapters/react/table.d.ts.map +1 -1
- package/adapters/react/table.js +1 -1
- package/adapters/react/table.js.map +1 -1
- package/adapters/react/table.tsx +2 -1
- package/adapters/react/useRequestHandler.js +1 -1
- package/bin/analyzer-contracts.js +17 -1
- package/custom-elements.json +57 -3
- package/dist/cdn/accordion/snice-accordion.js +1 -1
- package/dist/cdn/action-bar/snice-action-bar.js +1 -1
- package/dist/cdn/activity-feed/snice-activity-feed.js +1 -1
- package/dist/cdn/alert/snice-alert.js +1 -1
- package/dist/cdn/app-tiles/snice-app-tiles.js +1 -1
- package/dist/cdn/approval-flow/snice-approval-flow.js +1 -1
- package/dist/cdn/audio-recorder/snice-audio-recorder.js +1 -1
- package/dist/cdn/availability/snice-availability.js +1 -1
- package/dist/cdn/avatar/snice-avatar.js +1 -1
- package/dist/cdn/avatar-group/snice-avatar-group.js +1 -1
- package/dist/cdn/badge/snice-badge.js +1 -1
- package/dist/cdn/banner/snice-banner.js +1 -1
- package/dist/cdn/binpack/snice-binpack.js +1 -1
- package/dist/cdn/book/snice-book.js +1 -1
- package/dist/cdn/booking/snice-booking.js +1 -1
- package/dist/cdn/breadcrumbs/snice-breadcrumbs.js +1 -1
- package/dist/cdn/button/snice-button.js +1 -1
- package/dist/cdn/calendar/README.md +2 -2
- package/dist/cdn/calendar/snice-calendar.js +537 -44
- package/dist/cdn/calendar/snice-calendar.js.map +1 -1
- package/dist/cdn/calendar/snice-calendar.min.js +2 -2
- package/dist/cdn/calendar/snice-calendar.min.js.map +1 -1
- package/dist/cdn/camera/snice-camera.js +1 -1
- package/dist/cdn/camera-annotate/snice-camera-annotate.js +1 -1
- package/dist/cdn/candlestick/snice-candlestick.js +1 -1
- package/dist/cdn/card/snice-card.js +1 -1
- package/dist/cdn/carousel/snice-carousel.js +1 -1
- package/dist/cdn/cart/snice-cart.js +1 -1
- package/dist/cdn/chart/snice-chart.js +1 -1
- package/dist/cdn/chat/snice-chat.js +1 -1
- package/dist/cdn/checkbox/snice-checkbox.js +1 -1
- package/dist/cdn/chip/snice-chip.js +1 -1
- package/dist/cdn/code-block/README.md +2 -2
- package/dist/cdn/code-block/snice-code-block.js +177 -167
- package/dist/cdn/code-block/snice-code-block.js.map +1 -1
- package/dist/cdn/code-block/snice-code-block.min.js +2 -2
- package/dist/cdn/code-block/snice-code-block.min.js.map +1 -1
- package/dist/cdn/color-display/snice-color-display.js +1 -1
- package/dist/cdn/color-picker/snice-color-picker.js +1 -1
- package/dist/cdn/command-palette/README.md +1 -1
- package/dist/cdn/command-palette/snice-command-palette.js +2 -2
- package/dist/cdn/command-palette/snice-command-palette.js.map +1 -1
- package/dist/cdn/command-palette/snice-command-palette.min.js +1 -1
- package/dist/cdn/command-palette/snice-command-palette.min.js.map +1 -1
- package/dist/cdn/comments/snice-comments.js +1 -1
- package/dist/cdn/countdown/snice-countdown.js +1 -1
- package/dist/cdn/cropper/snice-cropper.js +1 -1
- package/dist/cdn/data-card/snice-data-card.js +1 -1
- package/dist/cdn/date-picker/snice-date-picker.js +1 -1
- package/dist/cdn/date-range-picker/snice-date-range-picker.js +1 -1
- package/dist/cdn/date-time-picker/snice-date-time-picker.js +1 -1
- package/dist/cdn/diff/snice-diff.js +1 -1
- package/dist/cdn/divider/snice-divider.js +1 -1
- package/dist/cdn/doc/snice-doc.js +1 -1
- package/dist/cdn/draw/snice-draw.js +1 -1
- package/dist/cdn/drawer/snice-drawer.js +1 -1
- package/dist/cdn/empty-state/snice-empty-state.js +1 -1
- package/dist/cdn/estimate/snice-estimate.js +1 -1
- package/dist/cdn/file-gallery/snice-file-gallery.js +1 -1
- package/dist/cdn/file-upload/snice-file-upload.js +1 -1
- package/dist/cdn/flip-card/snice-flip-card.js +1 -1
- package/dist/cdn/flow/snice-flow.js +1 -1
- package/dist/cdn/form-layout/snice-form-layout.js +1 -1
- package/dist/cdn/funnel/snice-funnel.js +1 -1
- package/dist/cdn/gantt/snice-gantt.js +1 -1
- package/dist/cdn/gauge/snice-gauge.js +1 -1
- package/dist/cdn/grid/snice-grid.js +1 -1
- package/dist/cdn/heatmap/snice-heatmap.js +1 -1
- package/dist/cdn/image/snice-image.js +1 -1
- package/dist/cdn/input/snice-input.js +1 -1
- package/dist/cdn/invoice/snice-invoice.js +1 -1
- package/dist/cdn/kanban/snice-kanban.js +1 -1
- package/dist/cdn/key-value/snice-key-value.js +1 -1
- package/dist/cdn/kpi/snice-kpi.js +1 -1
- package/dist/cdn/layout/snice-layout.js +1 -1
- package/dist/cdn/leaderboard/snice-leaderboard.js +1 -1
- package/dist/cdn/link/snice-link.js +1 -1
- package/dist/cdn/link-preview/snice-link-preview.js +1 -1
- package/dist/cdn/list/snice-list.js +1 -1
- package/dist/cdn/location/snice-location.js +1 -1
- package/dist/cdn/login/snice-login.js +1 -1
- package/dist/cdn/map/snice-map.js +1 -1
- package/dist/cdn/markdown/snice-markdown.js +1 -1
- package/dist/cdn/masonry/snice-masonry.js +1 -1
- package/dist/cdn/menu/snice-menu.js +1 -1
- package/dist/cdn/message-strip/snice-message-strip.js +1 -1
- package/dist/cdn/modal/snice-modal.js +1 -1
- package/dist/cdn/music-player/snice-music-player.js +1 -1
- package/dist/cdn/nav/snice-nav.js +1 -1
- package/dist/cdn/network-graph/snice-network-graph.js +1 -1
- package/dist/cdn/notification-center/snice-notification-center.js +1 -1
- package/dist/cdn/order-tracker/snice-order-tracker.js +1 -1
- package/dist/cdn/org-chart/snice-org-chart.js +1 -1
- package/dist/cdn/pagination/snice-pagination.js +1 -1
- package/dist/cdn/paint/snice-paint.js +1 -1
- package/dist/cdn/pdf-viewer/snice-pdf-viewer.js +1 -1
- package/dist/cdn/permission-matrix/snice-permission-matrix.js +1 -1
- package/dist/cdn/podcast-player/snice-podcast-player.js +1 -1
- package/dist/cdn/popover/snice-popover.js +1 -1
- package/dist/cdn/pricing-table/snice-pricing-table.js +1 -1
- package/dist/cdn/product-card/snice-product-card.js +1 -1
- package/dist/cdn/progress/snice-progress.js +2 -2
- package/dist/cdn/progress/snice-progress.js.map +1 -1
- package/dist/cdn/progress/snice-progress.min.js +1 -1
- package/dist/cdn/progress/snice-progress.min.js.map +1 -1
- package/dist/cdn/progress-ring/snice-progress-ring.js +1 -1
- package/dist/cdn/qr-code/README.md +2 -2
- package/dist/cdn/qr-code/snice-qr-code.js +19 -3
- package/dist/cdn/qr-code/snice-qr-code.js.map +1 -1
- package/dist/cdn/qr-code/snice-qr-code.min.js +2 -2
- package/dist/cdn/qr-code/snice-qr-code.min.js.map +1 -1
- package/dist/cdn/qr-reader/snice-qr-reader.js +1 -1
- package/dist/cdn/radio/snice-radio.js +1 -1
- package/dist/cdn/range-slider/snice-range-slider.js +1 -1
- package/dist/cdn/rating/snice-rating.js +1 -1
- package/dist/cdn/receipt/snice-receipt.js +5 -2
- package/dist/cdn/receipt/snice-receipt.js.map +1 -1
- package/dist/cdn/receipt/snice-receipt.min.js +1 -1
- package/dist/cdn/receipt/snice-receipt.min.js.map +1 -1
- package/dist/cdn/recipe/snice-recipe.js +1 -1
- package/dist/cdn/runtime/snice-runtime.esm.js +4 -4
- package/dist/cdn/runtime/snice-runtime.esm.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.esm.min.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.js +4 -4
- package/dist/cdn/runtime/snice-runtime.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.min.js.map +1 -1
- package/dist/cdn/sankey/snice-sankey.js +1 -1
- package/dist/cdn/segmented-control/snice-segmented-control.js +1 -1
- package/dist/cdn/select/README.md +2 -2
- package/dist/cdn/select/snice-select.js +6 -9
- package/dist/cdn/select/snice-select.js.map +1 -1
- package/dist/cdn/select/snice-select.min.js +2 -2
- package/dist/cdn/select/snice-select.min.js.map +1 -1
- package/dist/cdn/skeleton/snice-skeleton.js +1 -1
- package/dist/cdn/slider/snice-slider.js +1 -1
- package/dist/cdn/sortable/snice-sortable.js +1 -1
- package/dist/cdn/sparkline/snice-sparkline.js +1 -1
- package/dist/cdn/spinner/snice-spinner.js +1 -1
- package/dist/cdn/split-button/snice-split-button.js +1 -1
- package/dist/cdn/split-pane/snice-split-pane.js +1 -1
- package/dist/cdn/spotlight/snice-spotlight.js +1 -1
- package/dist/cdn/stat-group/snice-stat-group.js +1 -1
- package/dist/cdn/step-input/snice-step-input.js +1 -1
- package/dist/cdn/stepper/snice-stepper.js +1 -1
- package/dist/cdn/switch/snice-switch.js +1 -1
- package/dist/cdn/table/README.md +2 -2
- package/dist/cdn/table/snice-table.esm.js +1940 -407
- package/dist/cdn/table/snice-table.esm.js.map +1 -1
- package/dist/cdn/table/snice-table.esm.min.js +242 -53
- package/dist/cdn/table/snice-table.esm.min.js.map +1 -1
- package/dist/cdn/table/snice-table.js +1940 -407
- package/dist/cdn/table/snice-table.js.map +1 -1
- package/dist/cdn/table/snice-table.min.js +234 -45
- package/dist/cdn/table/snice-table.min.js.map +1 -1
- package/dist/cdn/tabs/snice-tabs.js +1 -1
- package/dist/cdn/tag/snice-tag.js +1 -1
- package/dist/cdn/tag-input/snice-tag-input.js +1 -1
- package/dist/cdn/terminal/snice-terminal.js +1 -1
- package/dist/cdn/testimonial/snice-testimonial.js +1 -1
- package/dist/cdn/textarea/snice-textarea.js +1 -1
- package/dist/cdn/time-picker/snice-time-picker.js +1 -1
- package/dist/cdn/time-range-picker/snice-time-range-picker.js +1 -1
- package/dist/cdn/timeline/snice-timeline.js +1 -1
- package/dist/cdn/timer/snice-timer.js +1 -1
- package/dist/cdn/toast/snice-toast.js +1 -1
- package/dist/cdn/tooltip/snice-tooltip.js +1 -1
- package/dist/cdn/tree/snice-tree.js +1 -1
- package/dist/cdn/treemap/snice-treemap.js +1 -1
- package/dist/cdn/user-card/snice-user-card.js +1 -1
- package/dist/cdn/video-player/snice-video-player.js +1 -1
- package/dist/cdn/virtual-scroller/snice-virtual-scroller.js +1 -1
- package/dist/cdn/waterfall/snice-waterfall.js +1 -1
- package/dist/cdn/weather/snice-weather.js +1 -1
- package/dist/cdn/work-order/snice-work-order.js +1 -1
- package/dist/components/calendar/snice-calendar.d.ts +187 -5
- package/dist/components/calendar/snice-calendar.js +537 -44
- package/dist/components/calendar/snice-calendar.js.map +1 -1
- package/dist/components/calendar/snice-calendar.types.d.ts +2 -1
- package/dist/components/code-block/formatter.d.ts +6 -0
- package/dist/components/code-block/formatter.js +174 -164
- package/dist/components/code-block/formatter.js.map +1 -1
- package/dist/components/code-block/grammars/snice.json +1 -1
- package/dist/components/code-block/grammars/typescript.json +1 -1
- package/dist/components/command-palette/snice-command-palette.js +1 -1
- package/dist/components/command-palette/snice-command-palette.js.map +1 -1
- package/dist/components/progress/snice-progress.js +1 -1
- package/dist/components/progress/snice-progress.js.map +1 -1
- package/dist/components/qr-code/qrcode.d.ts +1 -1
- package/dist/components/qr-code/qrcode.js +18 -2
- package/dist/components/qr-code/qrcode.js.map +1 -1
- package/dist/components/receipt/snice-receipt.js +4 -1
- package/dist/components/receipt/snice-receipt.js.map +1 -1
- package/dist/components/select/snice-select.d.ts +1 -1
- package/dist/components/select/snice-select.js +5 -8
- package/dist/components/select/snice-select.js.map +1 -1
- package/dist/components/table/snice-cell-actions.js +1 -1
- package/dist/components/table/snice-cell-actions.js.map +1 -1
- package/dist/components/table/snice-cell-color.js +1 -1
- package/dist/components/table/snice-cell-color.js.map +1 -1
- package/dist/components/table/snice-cell-date.js +20 -8
- package/dist/components/table/snice-cell-date.js.map +1 -1
- package/dist/components/table/snice-cell-email.js +1 -1
- package/dist/components/table/snice-cell-email.js.map +1 -1
- package/dist/components/table/snice-cell-image.js +1 -1
- package/dist/components/table/snice-cell-image.js.map +1 -1
- package/dist/components/table/snice-cell-json.js +1 -1
- package/dist/components/table/snice-cell-json.js.map +1 -1
- package/dist/components/table/snice-cell-link.js +1 -1
- package/dist/components/table/snice-cell-link.js.map +1 -1
- package/dist/components/table/snice-cell-location.js +1 -1
- package/dist/components/table/snice-cell-location.js.map +1 -1
- package/dist/components/table/snice-cell-phone.js +1 -1
- package/dist/components/table/snice-cell-phone.js.map +1 -1
- package/dist/components/table/snice-cell-status.js +1 -1
- package/dist/components/table/snice-cell-status.js.map +1 -1
- package/dist/components/table/snice-cell.d.ts +10 -0
- package/dist/components/table/snice-cell.js +59 -13
- package/dist/components/table/snice-cell.js.map +1 -1
- package/dist/components/table/snice-row.d.ts +0 -1
- package/dist/components/table/snice-row.js +4 -10
- package/dist/components/table/snice-row.js.map +1 -1
- package/dist/components/table/snice-table.d.ts +170 -2
- package/dist/components/table/snice-table.js +868 -189
- package/dist/components/table/snice-table.js.map +1 -1
- package/dist/components/table/snice-table.types.d.ts +17 -0
- package/dist/components/table/table-cell-presentation.d.ts +17 -4
- package/dist/components/table/table-cell-presentation.js +37 -11
- package/dist/components/table/table-cell-presentation.js.map +1 -1
- package/dist/components/table/table-column-manager.d.ts +153 -2
- package/dist/components/table/table-column-manager.js +364 -43
- package/dist/components/table/table-column-manager.js.map +1 -1
- package/dist/components/table/table-date.d.ts +29 -0
- package/dist/components/table/table-date.js +78 -0
- package/dist/components/table/table-date.js.map +1 -0
- package/dist/components/table/table-export.js +6 -2
- package/dist/components/table/table-export.js.map +1 -1
- package/dist/components/table/table-filter-engine.d.ts +9 -0
- package/dist/components/table/table-filter-engine.js +58 -14
- package/dist/components/table/table-filter-engine.js.map +1 -1
- package/dist/components/table/table-keyboard.d.ts +8 -0
- package/dist/components/table/table-keyboard.js +14 -3
- package/dist/components/table/table-keyboard.js.map +1 -1
- package/dist/components/table/table-toolbar.js +1 -0
- package/dist/components/table/table-toolbar.js.map +1 -1
- package/dist/components/table/table-tree-data.d.ts +2 -0
- package/dist/components/table/table-tree-data.js +35 -9
- package/dist/components/table/table-tree-data.js.map +1 -1
- package/dist/components/table/table-virtualizer.d.ts +44 -7
- package/dist/components/table/table-virtualizer.js +101 -54
- package/dist/components/table/table-virtualizer.js.map +1 -1
- package/dist/components/theme/theme.css +9 -0
- package/dist/index.cjs +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.iife.js +1 -1
- package/dist/react/SniceProvider.js +1 -1
- package/dist/react/SniceRouter.js +1 -1
- package/dist/react/index.js +1 -1
- package/dist/react/matchRoute.js +1 -1
- package/dist/react/useRequestHandler.js +1 -1
- package/dist/symbols.cjs +1 -1
- package/dist/symbols.esm.js +1 -1
- package/dist/testing-dom.cjs +1 -1
- package/dist/testing-dom.esm.js +1 -1
- package/dist/transitions.cjs +1 -1
- package/dist/transitions.esm.js +1 -1
- package/docs/ai/DEVELOPMENT.md +93 -2
- package/docs/ai/components/calendar.md +113 -10
- package/docs/ai/components/code-block.md +4 -0
- package/docs/ai/components/doc.md +1 -1
- package/docs/ai/components/progress.md +1 -0
- package/docs/ai/components/receipt.md +1 -1
- package/docs/ai/components/table.md +29 -30
- package/docs/ai/components/theme.md +1 -0
- package/docs/ai/events.md +30 -0
- package/docs/ai/theme.md +1 -0
- package/docs/components/calendar.md +171 -11
- package/docs/components/code-block.md +2 -0
- package/docs/components/doc.md +1 -1
- package/docs/components/progress.md +13 -0
- package/docs/components/receipt.md +1 -0
- package/docs/components/table.md +274 -15
- package/docs/components/theme.md +5 -0
- package/docs/events.md +49 -0
- package/docs/plans/2026-03-06-date-range-picker-plan.md +4 -4
- package/docs/plans/2026-03-07-table-mui-parity-design.md +1 -1
- package/docs/plans/2026-03-09-action-bar-plan.md +11 -11
- package/docs/superpowers/specs/2026-07-09-table-incredible-design.md +1 -1
- package/docs/superpowers/specs/2026-07-09-table-phase0-implementation.md +2 -2
- package/package.json +3 -1
- package/vscode.html-custom-data.json +13 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table-toolbar.js","sources":["../../../../components/table/table-toolbar.ts"],"sourcesContent":["/**\n * Toolbar for snice-table — MUI X DataGrid pattern.\n *\n * Optional Sort and Filter buttons expose in-flow panels for the same models\n * used by sortable headers and column menus.\n *\n * Filter UI: in-flow panel between toolbar and grid, appears when a column's\n * \"Filter\" menu item is invoked.\n */\nimport type { FilterOperator, FilterLogic } from './table-filter-engine';\nimport { TableFilterEngine } from './table-filter-engine';\nimport { X_MARK, PLUS, ARROW_DOWN_TRAY, ARROWS_POINTING_OUT, FUNNEL, ARROWS_RIGHT_LEFT } from '../icons';\n\nexport interface ToolbarOptions {\n showSearch?: boolean;\n showSort?: boolean;\n showFilter?: boolean;\n showExport?: boolean;\n searchPlaceholder?: string;\n}\n\ninterface FilterRow {\n column: string;\n operator: FilterOperator;\n value: any;\n}\n\nexport class TableToolbar {\n private container: HTMLElement | null = null;\n private options: ToolbarOptions = {};\n private tableElement: any = null;\n private filterEngine: TableFilterEngine | null = null;\n\n private filterPanel: HTMLElement | null = null;\n private filterPanelOpen = false;\n private filters: FilterRow[] = [];\n private logic: FilterLogic = 'and';\n private pendingDebounces: number[] = [];\n private sortPanel: HTMLElement | null = null;\n private sortPanelOpen = false;\n\n onSearch: ((query: string) => void) | null = null;\n onSortColumn: ((columnKey: string, direction: 'asc' | 'desc') => void) | null = null;\n onSetSortModel: ((sortModel: { column: string; direction: 'asc' | 'desc' }[]) => void) | null = null;\n onFilterColumn: ((columnKey: string, operator: FilterOperator, value: any) => void) | null = null;\n onRemoveFilter: ((columnKey: string) => void) | null = null;\n onClearFilters: (() => void) | null = null;\n onSetFilterModel: ((filters: FilterRow[], logic: FilterLogic) => void) | null = null;\n onExportCSV: (() => void) | null = null;\n onFullscreen: (() => void) | null = null;\n\n attach(tableEl: HTMLElement, container: HTMLElement, options: ToolbarOptions = {}) {\n this.tableElement = tableEl;\n this.container = container;\n this.options = options;\n this.render();\n }\n\n setFilterEngine(engine: TableFilterEngine) {\n this.filterEngine = engine;\n }\n\n render() {\n if (!this.container) return;\n this.container.innerHTML = '';\n\n const wrap = document.createElement('div');\n wrap.className = 'tt-wrap';\n wrap.appendChild(this.styleTag());\n\n const toolbar = document.createElement('div');\n toolbar.className = 'table-toolbar';\n toolbar.setAttribute('part', 'toolbar');\n\n if (this.options.showSearch !== false) {\n const searchInput = document.createElement('snice-input') as any;\n searchInput.type = 'search';\n searchInput.placeholder = this.options.searchPlaceholder || 'Search...';\n searchInput.size = 'small';\n searchInput.prefixIcon = 'search';\n searchInput.clearable = true;\n searchInput.className = 'toolbar-search';\n let debounce: number;\n searchInput.addEventListener('input', () => {\n clearTimeout(debounce);\n debounce = window.setTimeout(() => this.onSearch?.(searchInput.value), 300);\n });\n toolbar.appendChild(searchInput);\n }\n\n const actions = document.createElement('div');\n actions.className = 'toolbar-actions';\n\n if (this.options.showSort) {\n const sortBtn = this.mkBtn('Sort', ARROWS_RIGHT_LEFT);\n sortBtn.classList.add('toolbar-sort');\n sortBtn.addEventListener('click', () => this.toggleSortPanel());\n actions.appendChild(sortBtn);\n }\n\n if (this.options.showFilter) {\n const filterBtn = this.mkBtn('Filter', FUNNEL);\n filterBtn.classList.add('toolbar-filter');\n filterBtn.addEventListener('click', () => {\n if (this.filterPanelOpen) this.closeFilterPanel();\n else this.openFilterModal();\n });\n actions.appendChild(filterBtn);\n }\n\n if (this.options.showExport) {\n const exportBtn = this.mkBtn('Export CSV', ARROW_DOWN_TRAY);\n exportBtn.addEventListener('click', () => this.onExportCSV?.());\n actions.appendChild(exportBtn);\n }\n\n const fsBtn = this.mkBtn('Fullscreen', ARROWS_POINTING_OUT);\n fsBtn.addEventListener('click', () => this.onFullscreen?.());\n actions.appendChild(fsBtn);\n\n toolbar.appendChild(actions);\n wrap.appendChild(toolbar);\n\n this.filterPanel = document.createElement('div');\n this.filterPanel.className = 'tt-filter-panel';\n this.filterPanel.hidden = !this.filterPanelOpen;\n wrap.appendChild(this.filterPanel);\n\n this.sortPanel = document.createElement('div');\n this.sortPanel.className = 'tt-sort-panel';\n this.sortPanel.hidden = !this.sortPanelOpen;\n wrap.appendChild(this.sortPanel);\n\n this.container.appendChild(wrap);\n if (this.filterPanelOpen) this.renderFilterPanel();\n if (this.sortPanelOpen) this.renderSortPanel();\n }\n\n /** Public name kept for backwards-compat with snice-table.ts column-menu Filter action. */\n openFilterModal(presetColumn?: string) {\n this.closeSortPanel();\n const engine = this.ensureEngine();\n // When the panel is opening (was closed), resync local filter state from\n // the engine so the panel always reflects the actually-applied filters,\n // not stale local edits from a previous open session.\n if (!this.filterPanelOpen) {\n const model = engine.getFilterModel();\n this.filters = model.filters.map(f => ({ ...f }));\n this.logic = model.logic || 'and';\n }\n if (presetColumn) {\n const columns = this.tableElement?.columns || [];\n const col = columns.find((c: any) => c.key === presetColumn);\n const ops = engine.getOperatorsForType(col?.type || 'text');\n if (col && ops[0] && !this.filters.some(f => f.column === presetColumn)) {\n this.filters.push({ column: presetColumn, operator: ops[0].value as FilterOperator, value: '' });\n }\n }\n if (!this.filterPanelOpen) {\n this.filterPanelOpen = true;\n if (this.filterPanel) this.filterPanel.hidden = false;\n }\n this.renderFilterPanel();\n }\n\n closeFilterPanel() {\n this.cancelPendingDebounces();\n this.filterPanelOpen = false;\n if (this.filterPanel) this.filterPanel.hidden = true;\n }\n\n private toggleSortPanel() {\n if (this.sortPanelOpen) {\n this.closeSortPanel();\n return;\n }\n this.closeFilterPanel();\n this.sortPanelOpen = true;\n if (this.sortPanel) this.sortPanel.hidden = false;\n this.renderSortPanel();\n }\n\n private closeSortPanel() {\n this.sortPanelOpen = false;\n if (this.sortPanel) this.sortPanel.hidden = true;\n }\n\n private renderSortPanel() {\n if (!this.sortPanel) return;\n const columns = (this.tableElement?.columns || []).filter((column: any) => column.sortable !== false);\n let model: Array<{ column: string; direction: 'asc' | 'desc' }> =\n (this.tableElement?.currentSort || []).map((sort: any) => ({ ...sort }));\n\n this.sortPanel.innerHTML = '';\n this.sortPanel.appendChild(this.styleTag());\n const inner = document.createElement('div');\n inner.className = 'tt-filter-inner';\n\n const close = document.createElement('button');\n close.type = 'button';\n close.className = 'tt-filter-corner-close';\n close.setAttribute('aria-label', 'Close sort panel');\n close.innerHTML = X_MARK;\n close.addEventListener('click', () => this.closeSortPanel());\n inner.appendChild(close);\n\n const rows = document.createElement('div');\n rows.className = 'tt-filter-rows';\n inner.appendChild(rows);\n\n const apply = () => this.onSetSortModel?.(model.map((sort) => ({ ...sort })));\n const rerender = () => this.renderSortPanel();\n\n if (model.length === 0) {\n const empty = document.createElement('div');\n empty.className = 'tt-filter-empty';\n empty.textContent = 'No sorting applied';\n rows.appendChild(empty);\n } else {\n model.forEach((sort, index) => {\n const row = document.createElement('div');\n row.className = 'tt-filter-row tt-sort-row';\n\n const remove = document.createElement('button');\n remove.type = 'button';\n remove.className = 'tt-filter-x';\n remove.setAttribute('aria-label', 'Remove sort');\n remove.innerHTML = X_MARK;\n remove.addEventListener('click', () => {\n model.splice(index, 1);\n apply();\n rerender();\n });\n row.appendChild(remove);\n\n const columnSelect = document.createElement('snice-select') as any;\n columnSelect.size = 'small';\n const usedByOtherRows = new Set(model\n .filter((_candidate, candidateIndex) => candidateIndex !== index)\n .map((candidate) => candidate.column));\n columnSelect.options = columns\n .filter((column: any) => column.key === sort.column || !usedByOtherRows.has(column.key))\n .map((column: any) => ({ value: column.key, label: column.label || column.key }));\n columnSelect.value = sort.column;\n columnSelect.style.width = '12rem';\n columnSelect.addEventListener('change', () => {\n sort.column = columnSelect.value;\n apply();\n });\n row.appendChild(columnSelect);\n\n const direction = document.createElement('snice-select') as any;\n direction.size = 'small';\n direction.options = [\n { value: 'asc', label: 'Ascending' },\n { value: 'desc', label: 'Descending' },\n ];\n direction.value = sort.direction;\n direction.style.width = '9rem';\n direction.addEventListener('change', () => {\n sort.direction = direction.value;\n apply();\n });\n row.appendChild(direction);\n rows.appendChild(row);\n });\n }\n\n const footer = document.createElement('div');\n footer.className = 'tt-filter-footer';\n const add = document.createElement('button');\n add.type = 'button';\n add.className = 'tt-filter-add';\n add.innerHTML = `${PLUS}<span>Add sort</span>`;\n add.addEventListener('click', () => {\n const used = new Set(model.map((sort) => sort.column));\n const next = columns.find((column: any) => !used.has(column.key));\n if (!next) return;\n model.push({ column: next.key, direction: 'asc' });\n apply();\n rerender();\n });\n add.disabled = model.length >= columns.length;\n footer.appendChild(add);\n\n if (model.length > 0) {\n const clear = document.createElement('button');\n clear.type = 'button';\n clear.className = 'tt-filter-clear';\n clear.textContent = 'Clear all';\n clear.addEventListener('click', () => {\n model = [];\n apply();\n rerender();\n });\n footer.appendChild(clear);\n }\n inner.appendChild(footer);\n this.sortPanel.appendChild(inner);\n }\n\n // ── Filter panel ─────────────────────────────────────────────────\n\n private ensureEngine(): TableFilterEngine {\n if (!this.filterEngine) this.filterEngine = new TableFilterEngine();\n return this.filterEngine;\n }\n\n // Filter panels can be opened from either the toolbar or a column menu.\n\n private cancelPendingDebounces() {\n for (const t of this.pendingDebounces) clearTimeout(t);\n this.pendingDebounces = [];\n }\n\n private renderFilterPanel() {\n if (!this.filterPanel) return;\n // Stale debounces from a previous render hold refs to old DOM nodes — kill them.\n this.cancelPendingDebounces();\n const engine = this.ensureEngine();\n const columns = this.tableElement?.columns || [];\n\n // First open: pull current filter model into local state\n if (this.filters.length === 0) {\n const model = engine.getFilterModel();\n this.filters = [...model.filters];\n this.logic = model.logic || 'and';\n }\n\n this.filterPanel.innerHTML = '';\n this.filterPanel.appendChild(this.styleTag());\n\n const inner = document.createElement('div');\n inner.className = 'tt-filter-inner';\n\n // Top-right corner close — universal \"exit panel\" affordance\n const cornerClose = document.createElement('button');\n cornerClose.type = 'button';\n cornerClose.className = 'tt-filter-corner-close';\n cornerClose.setAttribute('aria-label', 'Close filter panel');\n cornerClose.setAttribute('title', 'Close');\n cornerClose.innerHTML = X_MARK;\n cornerClose.addEventListener('click', () => this.closeFilterPanel());\n inner.appendChild(cornerClose);\n\n const rows = document.createElement('div');\n rows.className = 'tt-filter-rows';\n inner.appendChild(rows);\n\n const apply = () => {\n const valid = this.filters.filter(f => {\n const colDef = columns.find((c: any) => c.key === f.column);\n const colType = colDef?.type || 'text';\n const opDef = engine.getOperatorsForType(colType).find(o => o.value === f.operator);\n // Operator must be valid for the column type. If user changed columns\n // and the previous operator no longer applies, skip the filter rather\n // than ship a malformed filter to the engine (which would 0-out all rows).\n if (!opDef) return false;\n return opDef.requiresValue === false || (f.value !== null && f.value !== '');\n });\n this.onSetFilterModel?.(valid, this.logic);\n };\n\n const renderRow = (f: FilterRow, idx: number): HTMLElement => {\n const row = document.createElement('div');\n row.className = 'tt-filter-row';\n\n const removeBtn = document.createElement('button');\n removeBtn.type = 'button';\n removeBtn.className = 'tt-filter-x';\n removeBtn.setAttribute('aria-label', 'Remove filter');\n removeBtn.innerHTML = X_MARK;\n removeBtn.addEventListener('click', () => {\n this.filters.splice(idx, 1);\n if (this.filters.length === 0) this.onClearFilters?.();\n else apply();\n this.renderFilterPanel();\n });\n row.appendChild(removeBtn);\n\n const colSel = document.createElement('snice-select') as any;\n colSel.size = 'small';\n colSel.searchable = columns.length > 8;\n colSel.maxHeight = '200px';\n colSel.options = columns.map((c: any) => ({ value: c.key, label: c.label || c.key }));\n colSel.value = f.column;\n colSel.style.width = '11rem';\n row.appendChild(colSel);\n\n const opSel = document.createElement('snice-select') as any;\n opSel.size = 'small';\n opSel.maxHeight = '200px';\n opSel.style.width = '8rem';\n row.appendChild(opSel);\n\n const valWrap = document.createElement('span');\n valWrap.className = 'tt-filter-val-wrap';\n const valInp = document.createElement('snice-input') as any;\n valInp.size = 'small';\n valInp.placeholder = 'Value';\n valInp.style.width = '11rem';\n if (f.value != null) valInp.value = String(f.value);\n valWrap.appendChild(valInp);\n row.appendChild(valWrap);\n\n // Map column type → snice-input HTML5 type so number/date columns get\n // the right keyboard, validation and (for date) native picker.\n const inputTypeForColType = (t: string): string => {\n switch (t) {\n case 'number':\n case 'currency':\n case 'rating':\n case 'progress':\n case 'filesize':\n case 'duration':\n case 'percent':\n case 'percentage':\n return 'number';\n case 'date':\n return 'date';\n default:\n return 'text';\n }\n };\n\n const refreshOps = () => {\n const colDef = columns.find((c: any) => c.key === colSel.value);\n const colType = colDef?.type || 'text';\n const ops = engine.getOperatorsForType(colType);\n opSel.options = ops.map(o => ({ value: o.value, label: o.label }));\n // Preserve the user's chosen operator. If it isn't valid for the new\n // column type, leave the select unselected (placeholder); the user\n // picks a new op. Never rewrite f.operator behind their back.\n if (ops.some(o => o.value === f.operator)) {\n opSel.value = f.operator;\n } else {\n opSel.value = '';\n }\n valInp.type = inputTypeForColType(colType);\n updateValueVis();\n };\n const updateValueVis = () => {\n const colDef = columns.find((c: any) => c.key === colSel.value);\n const colType = colDef?.type || 'text';\n const opDef = engine.getOperatorsForType(colType).find(o => o.value === opSel.value);\n valWrap.style.display = opDef?.requiresValue === false ? 'none' : '';\n };\n\n colSel.addEventListener('change', () => {\n f.column = colSel.value;\n refreshOps();\n apply();\n });\n opSel.addEventListener('change', () => {\n f.operator = opSel.value;\n updateValueVis();\n apply();\n });\n let valDebounce: number;\n valInp.addEventListener('input', () => {\n clearTimeout(valDebounce);\n valDebounce = window.setTimeout(() => {\n this.pendingDebounces = this.pendingDebounces.filter(t => t !== valDebounce);\n f.value = valInp.value;\n apply();\n }, 250);\n this.pendingDebounces.push(valDebounce);\n });\n valInp.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.key === 'Enter') {\n f.value = valInp.value;\n apply();\n }\n });\n\n refreshOps();\n return row;\n };\n\n // Panel-level logic toggle (AND / OR) — appears when 2+ filters\n if (this.filters.length > 1) {\n const logicBar = document.createElement('div');\n logicBar.className = 'tt-filter-logicbar';\n const logicLabel = document.createElement('span');\n logicLabel.className = 'tt-filter-logicbar-label';\n logicLabel.textContent = 'Match';\n const logicSel = document.createElement('snice-select') as any;\n logicSel.size = 'small';\n logicSel.options = [\n { value: 'and', label: 'All filters (AND)' },\n { value: 'or', label: 'Any filter (OR)' },\n ];\n logicSel.value = this.logic;\n logicSel.style.width = '11rem';\n logicSel.addEventListener('change', () => {\n this.logic = logicSel.value;\n apply();\n });\n logicBar.appendChild(logicLabel);\n logicBar.appendChild(logicSel);\n inner.insertBefore(logicBar, rows);\n }\n\n if (this.filters.length === 0) {\n const empty = document.createElement('div');\n empty.className = 'tt-filter-empty';\n empty.textContent = 'No filters applied';\n rows.appendChild(empty);\n } else {\n this.filters.forEach((f, idx) => rows.appendChild(renderRow(f, idx)));\n }\n\n const footer = document.createElement('div');\n footer.className = 'tt-filter-footer';\n\n const addBtn = document.createElement('button');\n addBtn.type = 'button';\n addBtn.className = 'tt-filter-add';\n addBtn.innerHTML = `${PLUS}<span>Add filter</span>`;\n addBtn.addEventListener('click', () => {\n const next = columns[0];\n if (!next) return;\n const ops = engine.getOperatorsForType(next.type || 'text');\n if (!ops[0]) return;\n this.filters.push({ column: next.key, operator: ops[0].value as FilterOperator, value: '' });\n this.renderFilterPanel();\n });\n footer.appendChild(addBtn);\n\n if (this.filters.length > 0) {\n const clearBtn = document.createElement('button');\n clearBtn.type = 'button';\n clearBtn.className = 'tt-filter-clear';\n clearBtn.textContent = 'Clear all';\n clearBtn.addEventListener('click', () => {\n this.cancelPendingDebounces();\n this.filters = [];\n this.logic = 'and';\n this.onClearFilters?.();\n this.renderFilterPanel();\n });\n footer.appendChild(clearBtn);\n }\n\n inner.appendChild(footer);\n this.filterPanel.appendChild(inner);\n }\n\n private mkBtn(label: string, svg: string): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.className = 'toolbar-btn';\n btn.setAttribute('aria-label', label);\n btn.setAttribute('title', label);\n btn.innerHTML = svg;\n return btn;\n }\n\n private styleTag(): HTMLStyleElement {\n const style = document.createElement('style');\n style.textContent = TT_STYLES;\n return style;\n }\n\n setActiveFilterCount(_count: number) {}\n isAttached(): boolean { return this.container !== null; }\n}\n\nconst TT_STYLES = `\n .tt-wrap { display: flex; flex-direction: column; }\n\n .tt-filter-panel {\n border-bottom: 1px solid var(--snice-color-border, rgb(226 226 226));\n background: var(--snice-color-surface-container-low, rgb(250 250 250));\n }\n .tt-sort-panel {\n border-bottom: 1px solid var(--snice-color-border, rgb(226 226 226));\n background: var(--snice-color-surface-container-low, rgb(250 250 250));\n }\n .tt-filter-inner {\n padding: 0.75rem 0.875rem;\n padding-right: 2.5rem;\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n position: relative;\n }\n .tt-filter-corner-close {\n position: absolute;\n top: 0.5rem;\n right: 0.5rem;\n width: 1.75rem;\n height: 1.75rem;\n border: none;\n background: none;\n cursor: pointer;\n color: var(--snice-color-text-tertiary, rgb(115 115 115));\n border-radius: var(--snice-border-radius-md, 0.25rem);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n line-height: 0;\n z-index: 1;\n }\n .tt-filter-corner-close:hover {\n background: var(--snice-color-surface-hover, rgb(245 245 245));\n color: var(--snice-color-text, rgb(23 23 23));\n }\n .tt-filter-corner-close svg {\n width: 1rem;\n height: 1rem;\n }\n .tt-filter-logicbar {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n }\n .tt-filter-logicbar-label {\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--snice-color-text-secondary, rgb(82 82 82));\n flex: 0 0 auto;\n }\n .tt-filter-rows {\n display: flex;\n flex-direction: column;\n gap: 0.375rem;\n }\n .tt-filter-empty {\n padding: 0.625rem 0.5rem;\n font-size: 0.8125rem;\n color: var(--snice-color-text-tertiary, rgb(115 115 115));\n font-style: italic;\n }\n .tt-filter-row {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex-wrap: nowrap;\n }\n .tt-filter-x {\n border: none;\n background: none;\n color: var(--snice-color-text-tertiary, rgb(115 115 115));\n cursor: pointer;\n border-radius: var(--snice-border-radius-md, 0.25rem);\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n padding: 0;\n line-height: 0;\n }\n .tt-filter-x svg {\n width: 1rem;\n height: 1rem;\n }\n .tt-filter-x:hover {\n color: var(--snice-color-danger, rgb(220 38 38));\n background: var(--snice-color-surface-hover, rgb(245 245 245));\n }\n .tt-filter-val-wrap { display: inline-flex; flex: 1 1 auto; min-width: 0; }\n .tt-filter-val-wrap snice-input { width: 100%; }\n .tt-filter-footer {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n margin-top: 0.125rem;\n }\n .tt-filter-add,\n .tt-filter-clear {\n border: none;\n background: none;\n font-family: inherit;\n font-size: 0.8125rem;\n cursor: pointer;\n padding: 0.375rem 0.625rem;\n border-radius: var(--snice-border-radius-md, 0.25rem);\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n line-height: 1;\n }\n .tt-filter-add svg,\n .tt-filter-clear svg {\n width: 0.875rem;\n height: 0.875rem;\n }\n .tt-filter-add { color: var(--snice-color-primary, rgb(37 99 235)); font-weight: 500; }\n .tt-filter-add:hover { background: var(--snice-color-primary-subtle, rgb(219 234 254 / 0.4)); }\n .tt-filter-clear { color: var(--snice-color-text-tertiary, rgb(115 115 115)); margin-left: auto; }\n .tt-filter-clear:hover {\n color: var(--snice-color-danger, rgb(220 38 38));\n background: var(--snice-color-surface-hover, rgb(245 245 245));\n }\n`;\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"table-toolbar.js","sources":["../../../../components/table/table-toolbar.ts"],"sourcesContent":["/**\n * Toolbar for snice-table — MUI X DataGrid pattern.\n *\n * Optional Sort and Filter buttons expose in-flow panels for the same models\n * used by sortable headers and column menus.\n *\n * Filter UI: in-flow panel between toolbar and grid, appears when a column's\n * \"Filter\" menu item is invoked.\n */\nimport type { FilterOperator, FilterLogic } from './table-filter-engine';\nimport { TableFilterEngine } from './table-filter-engine';\nimport { X_MARK, PLUS, ARROW_DOWN_TRAY, ARROWS_POINTING_OUT, FUNNEL, ARROWS_RIGHT_LEFT } from '../icons';\n\nexport interface ToolbarOptions {\n showSearch?: boolean;\n showSort?: boolean;\n showFilter?: boolean;\n showExport?: boolean;\n searchPlaceholder?: string;\n}\n\ninterface FilterRow {\n column: string;\n operator: FilterOperator;\n value: any;\n}\n\nexport class TableToolbar {\n private container: HTMLElement | null = null;\n private options: ToolbarOptions = {};\n private tableElement: any = null;\n private filterEngine: TableFilterEngine | null = null;\n\n private filterPanel: HTMLElement | null = null;\n private filterPanelOpen = false;\n private filters: FilterRow[] = [];\n private logic: FilterLogic = 'and';\n private pendingDebounces: number[] = [];\n private sortPanel: HTMLElement | null = null;\n private sortPanelOpen = false;\n\n onSearch: ((query: string) => void) | null = null;\n onSortColumn: ((columnKey: string, direction: 'asc' | 'desc') => void) | null = null;\n onSetSortModel: ((sortModel: { column: string; direction: 'asc' | 'desc' }[]) => void) | null = null;\n onFilterColumn: ((columnKey: string, operator: FilterOperator, value: any) => void) | null = null;\n onRemoveFilter: ((columnKey: string) => void) | null = null;\n onClearFilters: (() => void) | null = null;\n onSetFilterModel: ((filters: FilterRow[], logic: FilterLogic) => void) | null = null;\n onExportCSV: (() => void) | null = null;\n onFullscreen: (() => void) | null = null;\n\n attach(tableEl: HTMLElement, container: HTMLElement, options: ToolbarOptions = {}) {\n this.tableElement = tableEl;\n this.container = container;\n this.options = options;\n this.render();\n }\n\n setFilterEngine(engine: TableFilterEngine) {\n this.filterEngine = engine;\n }\n\n render() {\n if (!this.container) return;\n this.container.innerHTML = '';\n\n const wrap = document.createElement('div');\n wrap.className = 'tt-wrap';\n wrap.appendChild(this.styleTag());\n\n const toolbar = document.createElement('div');\n toolbar.className = 'table-toolbar';\n toolbar.setAttribute('part', 'toolbar');\n\n if (this.options.showSearch !== false) {\n const searchInput = document.createElement('snice-input') as any;\n searchInput.type = 'search';\n searchInput.placeholder = this.options.searchPlaceholder || 'Search...';\n searchInput.size = 'small';\n searchInput.prefixIcon = 'search';\n searchInput.clearable = true;\n searchInput.className = 'toolbar-search';\n let debounce: number;\n searchInput.addEventListener('input', () => {\n clearTimeout(debounce);\n debounce = window.setTimeout(() => this.onSearch?.(searchInput.value), 300);\n });\n toolbar.appendChild(searchInput);\n }\n\n const actions = document.createElement('div');\n actions.className = 'toolbar-actions';\n\n if (this.options.showSort) {\n const sortBtn = this.mkBtn('Sort', ARROWS_RIGHT_LEFT);\n sortBtn.classList.add('toolbar-sort');\n sortBtn.addEventListener('click', () => this.toggleSortPanel());\n actions.appendChild(sortBtn);\n }\n\n if (this.options.showFilter) {\n const filterBtn = this.mkBtn('Filter', FUNNEL);\n filterBtn.classList.add('toolbar-filter');\n filterBtn.addEventListener('click', () => {\n if (this.filterPanelOpen) this.closeFilterPanel();\n else this.openFilterModal();\n });\n actions.appendChild(filterBtn);\n }\n\n if (this.options.showExport) {\n const exportBtn = this.mkBtn('Export CSV', ARROW_DOWN_TRAY);\n exportBtn.addEventListener('click', () => this.onExportCSV?.());\n actions.appendChild(exportBtn);\n }\n\n const fsBtn = this.mkBtn('Fullscreen', ARROWS_POINTING_OUT);\n fsBtn.addEventListener('click', () => this.onFullscreen?.());\n actions.appendChild(fsBtn);\n\n toolbar.appendChild(actions);\n wrap.appendChild(toolbar);\n\n this.filterPanel = document.createElement('div');\n this.filterPanel.className = 'tt-filter-panel';\n this.filterPanel.hidden = !this.filterPanelOpen;\n wrap.appendChild(this.filterPanel);\n\n this.sortPanel = document.createElement('div');\n this.sortPanel.className = 'tt-sort-panel';\n this.sortPanel.hidden = !this.sortPanelOpen;\n wrap.appendChild(this.sortPanel);\n\n this.container.appendChild(wrap);\n if (this.filterPanelOpen) this.renderFilterPanel();\n if (this.sortPanelOpen) this.renderSortPanel();\n }\n\n /** Public name kept for backwards-compat with snice-table.ts column-menu Filter action. */\n openFilterModal(presetColumn?: string) {\n this.closeSortPanel();\n const engine = this.ensureEngine();\n // When the panel is opening (was closed), resync local filter state from\n // the engine so the panel always reflects the actually-applied filters,\n // not stale local edits from a previous open session.\n if (!this.filterPanelOpen) {\n const model = engine.getFilterModel();\n this.filters = model.filters.map(f => ({ ...f }));\n this.logic = model.logic || 'and';\n }\n if (presetColumn) {\n const columns = this.tableElement?.columns || [];\n const col = columns.find((c: any) => c.key === presetColumn);\n const ops = engine.getOperatorsForType(col?.type || 'text');\n if (col && ops[0] && !this.filters.some(f => f.column === presetColumn)) {\n this.filters.push({ column: presetColumn, operator: ops[0].value as FilterOperator, value: '' });\n }\n }\n if (!this.filterPanelOpen) {\n this.filterPanelOpen = true;\n if (this.filterPanel) this.filterPanel.hidden = false;\n }\n this.renderFilterPanel();\n }\n\n closeFilterPanel() {\n this.cancelPendingDebounces();\n this.filterPanelOpen = false;\n if (this.filterPanel) this.filterPanel.hidden = true;\n }\n\n private toggleSortPanel() {\n if (this.sortPanelOpen) {\n this.closeSortPanel();\n return;\n }\n this.closeFilterPanel();\n this.sortPanelOpen = true;\n if (this.sortPanel) this.sortPanel.hidden = false;\n this.renderSortPanel();\n }\n\n private closeSortPanel() {\n this.sortPanelOpen = false;\n if (this.sortPanel) this.sortPanel.hidden = true;\n }\n\n private renderSortPanel() {\n if (!this.sortPanel) return;\n const columns = (this.tableElement?.columns || []).filter((column: any) => column.sortable !== false);\n let model: Array<{ column: string; direction: 'asc' | 'desc' }> =\n (this.tableElement?.currentSort || []).map((sort: any) => ({ ...sort }));\n\n this.sortPanel.innerHTML = '';\n this.sortPanel.appendChild(this.styleTag());\n const inner = document.createElement('div');\n inner.className = 'tt-filter-inner';\n\n const close = document.createElement('button');\n close.type = 'button';\n close.className = 'tt-filter-corner-close';\n close.setAttribute('aria-label', 'Close sort panel');\n close.innerHTML = X_MARK;\n close.addEventListener('click', () => this.closeSortPanel());\n inner.appendChild(close);\n\n const rows = document.createElement('div');\n rows.className = 'tt-filter-rows';\n inner.appendChild(rows);\n\n const apply = () => this.onSetSortModel?.(model.map((sort) => ({ ...sort })));\n const rerender = () => this.renderSortPanel();\n\n if (model.length === 0) {\n const empty = document.createElement('div');\n empty.className = 'tt-filter-empty';\n empty.textContent = 'No sorting applied';\n rows.appendChild(empty);\n } else {\n model.forEach((sort, index) => {\n const row = document.createElement('div');\n row.className = 'tt-filter-row tt-sort-row';\n\n const remove = document.createElement('button');\n remove.type = 'button';\n remove.className = 'tt-filter-x';\n remove.setAttribute('aria-label', 'Remove sort');\n remove.innerHTML = X_MARK;\n remove.addEventListener('click', () => {\n model.splice(index, 1);\n apply();\n rerender();\n });\n row.appendChild(remove);\n\n const columnSelect = document.createElement('snice-select') as any;\n columnSelect.size = 'small';\n const usedByOtherRows = new Set(model\n .filter((_candidate, candidateIndex) => candidateIndex !== index)\n .map((candidate) => candidate.column));\n columnSelect.options = columns\n .filter((column: any) => column.key === sort.column || !usedByOtherRows.has(column.key))\n .map((column: any) => ({ value: column.key, label: column.label || column.key }));\n columnSelect.value = sort.column;\n columnSelect.style.width = '12rem';\n columnSelect.addEventListener('change', () => {\n sort.column = columnSelect.value;\n apply();\n });\n row.appendChild(columnSelect);\n\n const direction = document.createElement('snice-select') as any;\n direction.size = 'small';\n direction.options = [\n { value: 'asc', label: 'Ascending' },\n { value: 'desc', label: 'Descending' },\n ];\n direction.value = sort.direction;\n direction.style.width = '9rem';\n direction.addEventListener('change', () => {\n sort.direction = direction.value;\n apply();\n });\n row.appendChild(direction);\n rows.appendChild(row);\n });\n }\n\n const footer = document.createElement('div');\n footer.className = 'tt-filter-footer';\n const add = document.createElement('button');\n add.type = 'button';\n add.className = 'tt-filter-add';\n add.innerHTML = `${PLUS}<span>Add sort</span>`;\n add.addEventListener('click', () => {\n const used = new Set(model.map((sort) => sort.column));\n const next = columns.find((column: any) => !used.has(column.key));\n if (!next) return;\n model.push({ column: next.key, direction: 'asc' });\n apply();\n rerender();\n });\n add.disabled = model.length >= columns.length;\n footer.appendChild(add);\n\n if (model.length > 0) {\n const clear = document.createElement('button');\n clear.type = 'button';\n clear.className = 'tt-filter-clear';\n clear.textContent = 'Clear all';\n clear.addEventListener('click', () => {\n model = [];\n apply();\n rerender();\n });\n footer.appendChild(clear);\n }\n inner.appendChild(footer);\n this.sortPanel.appendChild(inner);\n }\n\n // ── Filter panel ─────────────────────────────────────────────────\n\n private ensureEngine(): TableFilterEngine {\n if (!this.filterEngine) this.filterEngine = new TableFilterEngine();\n return this.filterEngine;\n }\n\n // Filter panels can be opened from either the toolbar or a column menu.\n\n private cancelPendingDebounces() {\n for (const t of this.pendingDebounces) clearTimeout(t);\n this.pendingDebounces = [];\n }\n\n private renderFilterPanel() {\n if (!this.filterPanel) return;\n // Stale debounces from a previous render hold refs to old DOM nodes — kill them.\n this.cancelPendingDebounces();\n const engine = this.ensureEngine();\n const columns = this.tableElement?.columns || [];\n\n // First open: pull current filter model into local state\n if (this.filters.length === 0) {\n const model = engine.getFilterModel();\n this.filters = [...model.filters];\n this.logic = model.logic || 'and';\n }\n\n this.filterPanel.innerHTML = '';\n this.filterPanel.appendChild(this.styleTag());\n\n const inner = document.createElement('div');\n inner.className = 'tt-filter-inner';\n\n // Top-right corner close — universal \"exit panel\" affordance\n const cornerClose = document.createElement('button');\n cornerClose.type = 'button';\n cornerClose.className = 'tt-filter-corner-close';\n cornerClose.setAttribute('aria-label', 'Close filter panel');\n cornerClose.setAttribute('title', 'Close');\n cornerClose.innerHTML = X_MARK;\n cornerClose.addEventListener('click', () => this.closeFilterPanel());\n inner.appendChild(cornerClose);\n\n const rows = document.createElement('div');\n rows.className = 'tt-filter-rows';\n inner.appendChild(rows);\n\n const apply = () => {\n const valid = this.filters.filter(f => {\n const colDef = columns.find((c: any) => c.key === f.column);\n const colType = colDef?.type || 'text';\n const opDef = engine.getOperatorsForType(colType).find(o => o.value === f.operator);\n // Operator must be valid for the column type. If user changed columns\n // and the previous operator no longer applies, skip the filter rather\n // than ship a malformed filter to the engine (which would 0-out all rows).\n if (!opDef) return false;\n return opDef.requiresValue === false || (f.value !== null && f.value !== '');\n });\n this.onSetFilterModel?.(valid, this.logic);\n };\n\n const renderRow = (f: FilterRow, idx: number): HTMLElement => {\n const row = document.createElement('div');\n row.className = 'tt-filter-row';\n\n const removeBtn = document.createElement('button');\n removeBtn.type = 'button';\n removeBtn.className = 'tt-filter-x';\n removeBtn.setAttribute('aria-label', 'Remove filter');\n removeBtn.innerHTML = X_MARK;\n removeBtn.addEventListener('click', () => {\n this.filters.splice(idx, 1);\n if (this.filters.length === 0) this.onClearFilters?.();\n else apply();\n this.renderFilterPanel();\n });\n row.appendChild(removeBtn);\n\n const colSel = document.createElement('snice-select') as any;\n colSel.size = 'small';\n colSel.searchable = columns.length > 8;\n colSel.maxHeight = '200px';\n colSel.options = columns.map((c: any) => ({ value: c.key, label: c.label || c.key }));\n colSel.value = f.column;\n colSel.style.width = '11rem';\n row.appendChild(colSel);\n\n const opSel = document.createElement('snice-select') as any;\n opSel.size = 'small';\n opSel.maxHeight = '200px';\n opSel.style.width = '8rem';\n row.appendChild(opSel);\n\n const valWrap = document.createElement('span');\n valWrap.className = 'tt-filter-val-wrap';\n const valInp = document.createElement('snice-input') as any;\n valInp.size = 'small';\n valInp.placeholder = 'Value';\n valInp.style.width = '11rem';\n if (f.value != null) valInp.value = String(f.value);\n valWrap.appendChild(valInp);\n row.appendChild(valWrap);\n\n // Map column type → snice-input HTML5 type so number/date columns get\n // the right keyboard, validation and (for date) native picker.\n const inputTypeForColType = (t: string): string => {\n switch (t) {\n case 'number':\n case 'currency':\n case 'rating':\n case 'progress':\n case 'filesize':\n case 'duration':\n case 'percent':\n case 'percentage':\n return 'number';\n case 'date':\n return 'date';\n default:\n return 'text';\n }\n };\n\n const refreshOps = () => {\n const colDef = columns.find((c: any) => c.key === colSel.value);\n const colType = colDef?.type || 'text';\n const ops = engine.getOperatorsForType(colType);\n opSel.options = ops.map(o => ({ value: o.value, label: o.label }));\n // Preserve the user's chosen operator. If it isn't valid for the new\n // column type, leave the select unselected (placeholder); the user\n // picks a new op. Never rewrite f.operator behind their back.\n if (ops.some(o => o.value === f.operator)) {\n opSel.value = f.operator;\n } else {\n opSel.value = '';\n }\n valInp.type = inputTypeForColType(colType);\n updateValueVis();\n };\n const updateValueVis = () => {\n const colDef = columns.find((c: any) => c.key === colSel.value);\n const colType = colDef?.type || 'text';\n const opDef = engine.getOperatorsForType(colType).find(o => o.value === opSel.value);\n valWrap.style.display = opDef?.requiresValue === false ? 'none' : '';\n };\n\n colSel.addEventListener('change', () => {\n f.column = colSel.value;\n refreshOps();\n apply();\n });\n opSel.addEventListener('change', () => {\n f.operator = opSel.value;\n updateValueVis();\n apply();\n });\n let valDebounce: number;\n valInp.addEventListener('input', () => {\n clearTimeout(valDebounce);\n valDebounce = window.setTimeout(() => {\n this.pendingDebounces = this.pendingDebounces.filter(t => t !== valDebounce);\n f.value = valInp.value;\n apply();\n }, 250);\n this.pendingDebounces.push(valDebounce);\n });\n valInp.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.key === 'Enter') {\n f.value = valInp.value;\n apply();\n }\n });\n\n refreshOps();\n return row;\n };\n\n // Panel-level logic toggle (AND / OR) — appears when 2+ filters\n if (this.filters.length > 1) {\n const logicBar = document.createElement('div');\n logicBar.className = 'tt-filter-logicbar';\n const logicLabel = document.createElement('span');\n logicLabel.className = 'tt-filter-logicbar-label';\n logicLabel.textContent = 'Match';\n const logicSel = document.createElement('snice-select') as any;\n logicSel.size = 'small';\n logicSel.options = [\n { value: 'and', label: 'All filters (AND)' },\n { value: 'or', label: 'Any filter (OR)' },\n ];\n logicSel.value = this.logic;\n logicSel.style.width = '11rem';\n logicSel.addEventListener('change', () => {\n this.logic = logicSel.value;\n apply();\n });\n logicBar.appendChild(logicLabel);\n logicBar.appendChild(logicSel);\n inner.insertBefore(logicBar, rows);\n }\n\n if (this.filters.length === 0) {\n const empty = document.createElement('div');\n empty.className = 'tt-filter-empty';\n empty.textContent = 'No filters applied';\n rows.appendChild(empty);\n } else {\n this.filters.forEach((f, idx) => rows.appendChild(renderRow(f, idx)));\n }\n\n const footer = document.createElement('div');\n footer.className = 'tt-filter-footer';\n\n const addBtn = document.createElement('button');\n addBtn.type = 'button';\n addBtn.className = 'tt-filter-add';\n addBtn.innerHTML = `${PLUS}<span>Add filter</span>`;\n addBtn.addEventListener('click', () => {\n const next = columns[0];\n if (!next) return;\n const ops = engine.getOperatorsForType(next.type || 'text');\n if (!ops[0]) return;\n this.filters.push({ column: next.key, operator: ops[0].value as FilterOperator, value: '' });\n this.renderFilterPanel();\n });\n footer.appendChild(addBtn);\n\n if (this.filters.length > 0) {\n const clearBtn = document.createElement('button');\n clearBtn.type = 'button';\n clearBtn.className = 'tt-filter-clear';\n clearBtn.textContent = 'Clear all';\n clearBtn.addEventListener('click', () => {\n this.cancelPendingDebounces();\n this.filters = [];\n this.logic = 'and';\n this.onClearFilters?.();\n this.renderFilterPanel();\n });\n footer.appendChild(clearBtn);\n }\n\n inner.appendChild(footer);\n this.filterPanel.appendChild(inner);\n }\n\n private mkBtn(label: string, svg: string): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.className = 'toolbar-btn';\n btn.setAttribute('aria-label', label);\n btn.setAttribute('title', label);\n btn.innerHTML = svg;\n return btn;\n }\n\n private styleTag(): HTMLStyleElement {\n const style = document.createElement('style');\n style.textContent = TT_STYLES;\n return style;\n }\n\n setActiveFilterCount(_count: number) {}\n isAttached(): boolean { return this.container !== null; }\n}\n\nconst TT_STYLES = `\n .tt-wrap { display: flex; flex-direction: column; }\n\n .tt-filter-panel {\n border-bottom: 1px solid var(--snice-color-border, rgb(226 226 226));\n background: var(--snice-color-surface-container-low, rgb(250 250 250));\n }\n .tt-sort-panel {\n border-bottom: 1px solid var(--snice-color-border, rgb(226 226 226));\n background: var(--snice-color-surface-container-low, rgb(250 250 250));\n }\n .tt-filter-inner {\n padding: 0.75rem 0.875rem;\n padding-right: 2.5rem;\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n position: relative;\n }\n .tt-filter-corner-close {\n position: absolute;\n top: 0.5rem;\n right: 0.5rem;\n width: 1.75rem;\n height: 1.75rem;\n border: none;\n background: none;\n cursor: pointer;\n color: var(--snice-color-text-tertiary, rgb(115 115 115));\n border-radius: var(--snice-border-radius-md, 0.25rem);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n line-height: 0;\n z-index: 1;\n }\n .tt-filter-corner-close:hover {\n background: var(--snice-color-surface-hover, rgb(245 245 245));\n color: var(--snice-color-text, rgb(23 23 23));\n }\n .tt-filter-corner-close svg {\n width: 1rem;\n height: 1rem;\n }\n .tt-filter-logicbar {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n }\n .tt-filter-logicbar-label {\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--snice-color-text-secondary, rgb(82 82 82));\n flex: 0 0 auto;\n }\n .tt-filter-rows {\n display: flex;\n flex-direction: column;\n gap: 0.375rem;\n }\n .tt-filter-empty {\n padding: 0.625rem 0.5rem;\n font-size: 0.8125rem;\n color: var(--snice-color-text-tertiary, rgb(115 115 115));\n font-style: italic;\n }\n .tt-filter-row {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex-wrap: nowrap;\n }\n .tt-filter-x {\n border: none;\n background: none;\n color: var(--snice-color-text-tertiary, rgb(115 115 115));\n cursor: pointer;\n border-radius: var(--snice-border-radius-md, 0.25rem);\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n padding: 0;\n line-height: 0;\n }\n .tt-filter-x svg {\n width: 1rem;\n height: 1rem;\n }\n .tt-filter-x:hover {\n color: var(--snice-color-danger, rgb(220 38 38));\n background: var(--snice-color-surface-hover, rgb(245 245 245));\n }\n .tt-filter-val-wrap { display: inline-flex; flex: 1 1 auto; min-width: 0; }\n .tt-filter-val-wrap snice-input { width: 100%; }\n .tt-filter-footer {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n margin-top: 0.125rem;\n }\n .tt-filter-add,\n .tt-filter-clear {\n border: none;\n background: none;\n font-family: inherit;\n font-size: 0.8125rem;\n cursor: pointer;\n padding: 0.375rem 0.625rem;\n border-radius: var(--snice-border-radius-md, 0.25rem);\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n line-height: 1;\n }\n .tt-filter-add svg,\n .tt-filter-clear svg {\n width: 0.875rem;\n height: 0.875rem;\n }\n .tt-filter-add { color: var(--snice-color-primary, rgb(37 99 235)); font-weight: 500; }\n .tt-filter-add:hover { background: var(--snice-color-primary-subtle, rgb(219 234 254 / 0.4)); }\n .tt-filter-clear { color: var(--snice-color-text-tertiary, rgb(115 115 115)); margin-left: auto; }\n .tt-filter-clear:hover {\n color: var(--snice-color-danger, rgb(220 38 38));\n background: var(--snice-color-surface-hover, rgb(245 245 245));\n }\n`;\n"],"names":[],"mappings":"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"}
|
|
@@ -33,6 +33,8 @@ export declare class TableTreeData {
|
|
|
33
33
|
private enabled;
|
|
34
34
|
attach(options: TreeDataOptions): void;
|
|
35
35
|
private defaultDepth;
|
|
36
|
+
/** Whether the default expansion depth has been seeded (first data only). */
|
|
37
|
+
private defaultsApplied;
|
|
36
38
|
isEnabled(): boolean;
|
|
37
39
|
/**
|
|
38
40
|
* Process raw data into a flat tree structure.
|
|
@@ -9,10 +9,13 @@ class TableTreeData {
|
|
|
9
9
|
this.flatRows = [];
|
|
10
10
|
this.enabled = false;
|
|
11
11
|
this.defaultDepth = 0;
|
|
12
|
+
/** Whether the default expansion depth has been seeded (first data only). */
|
|
13
|
+
this.defaultsApplied = false;
|
|
12
14
|
}
|
|
13
15
|
attach(options) {
|
|
14
16
|
this.options = options;
|
|
15
17
|
this.enabled = true;
|
|
18
|
+
this.defaultsApplied = false;
|
|
16
19
|
// Pre-expand to default depth
|
|
17
20
|
if (options.defaultExpansionDepth !== undefined && options.defaultExpansionDepth >= 0) {
|
|
18
21
|
this.defaultDepth = options.defaultExpansionDepth;
|
|
@@ -33,13 +36,27 @@ class TableTreeData {
|
|
|
33
36
|
for (const row of data) {
|
|
34
37
|
const path = this.options.getPath(row);
|
|
35
38
|
const key = path.join('/');
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
// A real row may already exist as a gap node generated for a descendant
|
|
40
|
+
// delivered earlier; upgrade it in place so the children it collected
|
|
41
|
+
// survive.
|
|
42
|
+
const existing = nodeMap.get(key);
|
|
43
|
+
if (existing) {
|
|
44
|
+
existing.data = row;
|
|
45
|
+
existing.depth = path.length - 1;
|
|
46
|
+
existing.isGap = false;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
nodeMap.set(key, {
|
|
50
|
+
data: row,
|
|
51
|
+
children: new Set(),
|
|
52
|
+
depth: path.length - 1,
|
|
53
|
+
isGap: false,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
// Ensure all ancestors exist (gap nodes), and register each one as a
|
|
57
|
+
// child of its own parent: a generated node with no link upward leaves
|
|
58
|
+
// its parent reporting hasChildren === false, so flatten() never
|
|
59
|
+
// descends and the whole subtree — real rows included — disappears.
|
|
43
60
|
for (let i = 1; i < path.length; i++) {
|
|
44
61
|
const ancestorPath = path.slice(0, i);
|
|
45
62
|
const ancestorKey = ancestorPath.join('/');
|
|
@@ -51,6 +68,11 @@ class TableTreeData {
|
|
|
51
68
|
isGap: true,
|
|
52
69
|
});
|
|
53
70
|
}
|
|
71
|
+
if (i > 1) {
|
|
72
|
+
const ancestorParent = nodeMap.get(path.slice(0, i - 1).join('/'));
|
|
73
|
+
if (ancestorParent)
|
|
74
|
+
ancestorParent.children.add(ancestorKey);
|
|
75
|
+
}
|
|
54
76
|
}
|
|
55
77
|
// Register as child of parent
|
|
56
78
|
if (path.length > 1) {
|
|
@@ -67,13 +89,17 @@ class TableTreeData {
|
|
|
67
89
|
rootKeys.push(key);
|
|
68
90
|
}
|
|
69
91
|
rootKeys.sort();
|
|
70
|
-
// Auto-expand to default depth on first process
|
|
71
|
-
|
|
92
|
+
// Auto-expand to default depth on the first process that sees rows.
|
|
93
|
+
// `defaultExpansionDepth` describes the STARTING expansion only: keying
|
|
94
|
+
// this off an empty expansion set re-seeded it on every render, so
|
|
95
|
+
// collapsing the last expanded node (or collapseAll()) was silently undone.
|
|
96
|
+
if (!this.defaultsApplied && this.defaultDepth > 0 && nodeMap.size > 0) {
|
|
72
97
|
for (const [key, node] of nodeMap) {
|
|
73
98
|
if (node.depth < this.defaultDepth && node.children.size > 0) {
|
|
74
99
|
this.expandedKeys.add(key);
|
|
75
100
|
}
|
|
76
101
|
}
|
|
102
|
+
this.defaultsApplied = true;
|
|
77
103
|
}
|
|
78
104
|
// Flatten tree respecting expand/collapse
|
|
79
105
|
this.flatRows = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table-tree-data.js","sources":["../../../../components/table/table-tree-data.ts"],"sourcesContent":["/**\n * Tree data engine for snice-table.\n * Hierarchical rows with indent levels, expand/collapse nodes.\n */\n\nexport interface TreeRow {\n /** Path array defining hierarchy. e.g. ['US', 'CA', 'LA'] */\n path: string[];\n /** The original row data */\n data: any;\n /** Depth level (0-based) */\n depth: number;\n /** Whether this node has children */\n hasChildren: boolean;\n /** Whether this node is expanded */\n expanded: boolean;\n /** Unique key derived from path */\n key: string;\n /** Whether this is a gap node (auto-generated for missing parents) */\n isGap: boolean;\n}\n\nexport interface TreeDataOptions {\n /** Function to get the path array from a row */\n getPath: (row: any) => string[];\n /** Default expansion depth. -1 = all collapsed, Infinity = all expanded */\n defaultExpansionDepth?: number;\n /** Group column key (where expand/collapse controls appear) */\n groupColumn?: string;\n}\n\nexport class TableTreeData {\n private options: TreeDataOptions | null = null;\n private expandedKeys: Set<string> = new Set();\n private flatRows: TreeRow[] = [];\n private enabled = false;\n\n attach(options: TreeDataOptions) {\n this.options = options;\n this.enabled = true;\n\n // Pre-expand to default depth\n if (options.defaultExpansionDepth !== undefined && options.defaultExpansionDepth >= 0) {\n this.defaultDepth = options.defaultExpansionDepth;\n }\n }\n\n private defaultDepth = 0;\n\n isEnabled(): boolean {\n return this.enabled;\n }\n\n /**\n * Process raw data into a flat tree structure.\n * Returns only visible rows (respecting expand/collapse state).\n */\n processData(data: any[]): TreeRow[] {\n if (!this.options) return [];\n\n // Build tree from path arrays\n const nodeMap = new Map<string, { data: any; children: Set<string>; depth: number; isGap: boolean }>();\n\n for (const row of data) {\n const path = this.options.getPath(row);\n const key = path.join('/');\n\n nodeMap.set(key, {\n data: row,\n children: new Set(),\n depth: path.length - 1,\n isGap: false,\n });\n\n // Ensure all ancestors exist (gap nodes)\n for (let i = 1; i < path.length; i++) {\n const ancestorPath = path.slice(0, i);\n const ancestorKey = ancestorPath.join('/');\n if (!nodeMap.has(ancestorKey)) {\n nodeMap.set(ancestorKey, {\n data: { [this.options.groupColumn || 'name']: ancestorPath[ancestorPath.length - 1] },\n children: new Set(),\n depth: i - 1,\n isGap: true,\n });\n }\n }\n\n // Register as child of parent\n if (path.length > 1) {\n const parentKey = path.slice(0, -1).join('/');\n const parent = nodeMap.get(parentKey);\n if (parent) parent.children.add(key);\n }\n }\n\n // Find root nodes (depth 0)\n const rootKeys: string[] = [];\n for (const [key, node] of nodeMap) {\n if (node.depth === 0) rootKeys.push(key);\n }\n rootKeys.sort();\n\n // Auto-expand to default depth on first process\n if (this.expandedKeys.size === 0 && this.defaultDepth > 0) {\n for (const [key, node] of nodeMap) {\n if (node.depth < this.defaultDepth && node.children.size > 0) {\n this.expandedKeys.add(key);\n }\n }\n }\n\n // Flatten tree respecting expand/collapse\n this.flatRows = [];\n const flatten = (key: string) => {\n const node = nodeMap.get(key);\n if (!node) return;\n\n const hasChildren = node.children.size > 0;\n const expanded = this.expandedKeys.has(key);\n\n this.flatRows.push({\n path: key.split('/'),\n data: node.data,\n depth: node.depth,\n hasChildren,\n expanded,\n key,\n isGap: node.isGap,\n });\n\n if (expanded) {\n const childKeys = Array.from(node.children).sort();\n for (const childKey of childKeys) {\n flatten(childKey);\n }\n }\n };\n\n for (const rootKey of rootKeys) {\n flatten(rootKey);\n }\n\n return this.flatRows;\n }\n\n /** Get the current flat rows */\n getFlatRows(): TreeRow[] {\n return this.flatRows;\n }\n\n /** Toggle node expansion */\n toggle(key: string) {\n if (this.expandedKeys.has(key)) {\n this.expandedKeys.delete(key);\n } else {\n this.expandedKeys.add(key);\n }\n }\n\n /** Expand a node */\n expand(key: string) {\n this.expandedKeys.add(key);\n }\n\n /** Collapse a node */\n collapse(key: string) {\n this.expandedKeys.delete(key);\n }\n\n /** Expand all nodes */\n expandAll(data: any[]) {\n if (!this.options) return;\n for (const row of data) {\n const path = this.options.getPath(row);\n // Expand all ancestor paths\n for (let i = 1; i <= path.length; i++) {\n this.expandedKeys.add(path.slice(0, i).join('/'));\n }\n }\n }\n\n /** Collapse all nodes */\n collapseAll() {\n this.expandedKeys.clear();\n }\n\n /** Check if a node is expanded */\n isExpanded(key: string): boolean {\n return this.expandedKeys.has(key);\n }\n\n /** Create the expand/collapse toggle for a tree node */\n createToggle(treeRow: TreeRow): HTMLElement {\n const container = document.createElement('span');\n container.className = 'tree-indent';\n container.style.paddingLeft = `${treeRow.depth * 1.5}rem`;\n\n if (treeRow.hasChildren) {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = `tree-toggle${treeRow.expanded ? ' tree-toggle--expanded' : ''}`;\n btn.innerHTML = `<svg class=\"tree-toggle-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M6 9l6 6 6-6\"/></svg>`;\n btn.setAttribute('aria-expanded', String(treeRow.expanded));\n btn.setAttribute('aria-label', `${treeRow.expanded ? 'Collapse' : 'Expand'} row`);\n btn.addEventListener('click', (e) => {\n e.stopPropagation();\n this.toggle(treeRow.key);\n // Dispatch on the button — composed:true crosses shadow DOM boundary\n btn.dispatchEvent(new CustomEvent('tree-toggle', {\n detail: { key: treeRow.key, expanded: this.isExpanded(treeRow.key) },\n bubbles: true,\n composed: true,\n }));\n });\n container.appendChild(btn);\n } else {\n // Spacer for leaf nodes (align with siblings)\n const spacer = document.createElement('span');\n spacer.className = 'tree-spacer';\n container.appendChild(spacer);\n }\n\n return container;\n }\n\n getGroupColumn(): string {\n return this.options?.groupColumn || '';\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"table-tree-data.js","sources":["../../../../components/table/table-tree-data.ts"],"sourcesContent":["/**\n * Tree data engine for snice-table.\n * Hierarchical rows with indent levels, expand/collapse nodes.\n */\n\nexport interface TreeRow {\n /** Path array defining hierarchy. e.g. ['US', 'CA', 'LA'] */\n path: string[];\n /** The original row data */\n data: any;\n /** Depth level (0-based) */\n depth: number;\n /** Whether this node has children */\n hasChildren: boolean;\n /** Whether this node is expanded */\n expanded: boolean;\n /** Unique key derived from path */\n key: string;\n /** Whether this is a gap node (auto-generated for missing parents) */\n isGap: boolean;\n}\n\nexport interface TreeDataOptions {\n /** Function to get the path array from a row */\n getPath: (row: any) => string[];\n /** Default expansion depth. -1 = all collapsed, Infinity = all expanded */\n defaultExpansionDepth?: number;\n /** Group column key (where expand/collapse controls appear) */\n groupColumn?: string;\n}\n\nexport class TableTreeData {\n private options: TreeDataOptions | null = null;\n private expandedKeys: Set<string> = new Set();\n private flatRows: TreeRow[] = [];\n private enabled = false;\n\n attach(options: TreeDataOptions) {\n this.options = options;\n this.enabled = true;\n this.defaultsApplied = false;\n\n // Pre-expand to default depth\n if (options.defaultExpansionDepth !== undefined && options.defaultExpansionDepth >= 0) {\n this.defaultDepth = options.defaultExpansionDepth;\n }\n }\n\n private defaultDepth = 0;\n /** Whether the default expansion depth has been seeded (first data only). */\n private defaultsApplied = false;\n\n isEnabled(): boolean {\n return this.enabled;\n }\n\n /**\n * Process raw data into a flat tree structure.\n * Returns only visible rows (respecting expand/collapse state).\n */\n processData(data: any[]): TreeRow[] {\n if (!this.options) return [];\n\n // Build tree from path arrays\n const nodeMap = new Map<string, { data: any; children: Set<string>; depth: number; isGap: boolean }>();\n\n for (const row of data) {\n const path = this.options.getPath(row);\n const key = path.join('/');\n\n // A real row may already exist as a gap node generated for a descendant\n // delivered earlier; upgrade it in place so the children it collected\n // survive.\n const existing = nodeMap.get(key);\n if (existing) {\n existing.data = row;\n existing.depth = path.length - 1;\n existing.isGap = false;\n } else {\n nodeMap.set(key, {\n data: row,\n children: new Set(),\n depth: path.length - 1,\n isGap: false,\n });\n }\n\n // Ensure all ancestors exist (gap nodes), and register each one as a\n // child of its own parent: a generated node with no link upward leaves\n // its parent reporting hasChildren === false, so flatten() never\n // descends and the whole subtree — real rows included — disappears.\n for (let i = 1; i < path.length; i++) {\n const ancestorPath = path.slice(0, i);\n const ancestorKey = ancestorPath.join('/');\n if (!nodeMap.has(ancestorKey)) {\n nodeMap.set(ancestorKey, {\n data: { [this.options.groupColumn || 'name']: ancestorPath[ancestorPath.length - 1] },\n children: new Set(),\n depth: i - 1,\n isGap: true,\n });\n }\n if (i > 1) {\n const ancestorParent = nodeMap.get(path.slice(0, i - 1).join('/'));\n if (ancestorParent) ancestorParent.children.add(ancestorKey);\n }\n }\n\n // Register as child of parent\n if (path.length > 1) {\n const parentKey = path.slice(0, -1).join('/');\n const parent = nodeMap.get(parentKey);\n if (parent) parent.children.add(key);\n }\n }\n\n // Find root nodes (depth 0)\n const rootKeys: string[] = [];\n for (const [key, node] of nodeMap) {\n if (node.depth === 0) rootKeys.push(key);\n }\n rootKeys.sort();\n\n // Auto-expand to default depth on the first process that sees rows.\n // `defaultExpansionDepth` describes the STARTING expansion only: keying\n // this off an empty expansion set re-seeded it on every render, so\n // collapsing the last expanded node (or collapseAll()) was silently undone.\n if (!this.defaultsApplied && this.defaultDepth > 0 && nodeMap.size > 0) {\n for (const [key, node] of nodeMap) {\n if (node.depth < this.defaultDepth && node.children.size > 0) {\n this.expandedKeys.add(key);\n }\n }\n this.defaultsApplied = true;\n }\n\n // Flatten tree respecting expand/collapse\n this.flatRows = [];\n const flatten = (key: string) => {\n const node = nodeMap.get(key);\n if (!node) return;\n\n const hasChildren = node.children.size > 0;\n const expanded = this.expandedKeys.has(key);\n\n this.flatRows.push({\n path: key.split('/'),\n data: node.data,\n depth: node.depth,\n hasChildren,\n expanded,\n key,\n isGap: node.isGap,\n });\n\n if (expanded) {\n const childKeys = Array.from(node.children).sort();\n for (const childKey of childKeys) {\n flatten(childKey);\n }\n }\n };\n\n for (const rootKey of rootKeys) {\n flatten(rootKey);\n }\n\n return this.flatRows;\n }\n\n /** Get the current flat rows */\n getFlatRows(): TreeRow[] {\n return this.flatRows;\n }\n\n /** Toggle node expansion */\n toggle(key: string) {\n if (this.expandedKeys.has(key)) {\n this.expandedKeys.delete(key);\n } else {\n this.expandedKeys.add(key);\n }\n }\n\n /** Expand a node */\n expand(key: string) {\n this.expandedKeys.add(key);\n }\n\n /** Collapse a node */\n collapse(key: string) {\n this.expandedKeys.delete(key);\n }\n\n /** Expand all nodes */\n expandAll(data: any[]) {\n if (!this.options) return;\n for (const row of data) {\n const path = this.options.getPath(row);\n // Expand all ancestor paths\n for (let i = 1; i <= path.length; i++) {\n this.expandedKeys.add(path.slice(0, i).join('/'));\n }\n }\n }\n\n /** Collapse all nodes */\n collapseAll() {\n this.expandedKeys.clear();\n }\n\n /** Check if a node is expanded */\n isExpanded(key: string): boolean {\n return this.expandedKeys.has(key);\n }\n\n /** Create the expand/collapse toggle for a tree node */\n createToggle(treeRow: TreeRow): HTMLElement {\n const container = document.createElement('span');\n container.className = 'tree-indent';\n container.style.paddingLeft = `${treeRow.depth * 1.5}rem`;\n\n if (treeRow.hasChildren) {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = `tree-toggle${treeRow.expanded ? ' tree-toggle--expanded' : ''}`;\n btn.innerHTML = `<svg class=\"tree-toggle-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M6 9l6 6 6-6\"/></svg>`;\n btn.setAttribute('aria-expanded', String(treeRow.expanded));\n btn.setAttribute('aria-label', `${treeRow.expanded ? 'Collapse' : 'Expand'} row`);\n btn.addEventListener('click', (e) => {\n e.stopPropagation();\n this.toggle(treeRow.key);\n // Dispatch on the button — composed:true crosses shadow DOM boundary\n btn.dispatchEvent(new CustomEvent('tree-toggle', {\n detail: { key: treeRow.key, expanded: this.isExpanded(treeRow.key) },\n bubbles: true,\n composed: true,\n }));\n });\n container.appendChild(btn);\n } else {\n // Spacer for leaf nodes (align with siblings)\n const spacer = document.createElement('span');\n spacer.className = 'tree-spacer';\n container.appendChild(spacer);\n }\n\n return container;\n }\n\n getGroupColumn(): string {\n return this.options?.groupColumn || '';\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -12,8 +12,22 @@ export interface VirtualizerOptions {
|
|
|
12
12
|
totalRows: number;
|
|
13
13
|
/** Container element that scrolls */
|
|
14
14
|
scrollContainer: HTMLElement;
|
|
15
|
+
/**
|
|
16
|
+
* Optional: re-resolve the scrolling container on every update. A host whose
|
|
17
|
+
* template flips structural branches replaces the element captured at
|
|
18
|
+
* `attach()`; without this the virtualizer keeps painting into the DETACHED
|
|
19
|
+
* subtree's orphaned `<tbody>` while the live one stays empty.
|
|
20
|
+
*/
|
|
21
|
+
resolveScrollContainer?: () => HTMLElement | null;
|
|
15
22
|
/** Callback to render a range of rows */
|
|
16
23
|
renderRange: (startIndex: number, endIndex: number) => DocumentFragment;
|
|
24
|
+
/**
|
|
25
|
+
* How many columns a spacer row spans. Required in practice: a spacer that
|
|
26
|
+
* over-spans invents columns, and `table-layout: fixed` then hands the
|
|
27
|
+
* frame's spare width to the phantom ones — the real columns stop short of
|
|
28
|
+
* the right edge with a dead strip beside them.
|
|
29
|
+
*/
|
|
30
|
+
resolveColumnSpan?: () => number;
|
|
17
31
|
/**
|
|
18
32
|
* Optional: render pinned-top rows. These live OUTSIDE the windowed range
|
|
19
33
|
* (before the top spacer) so they are always present regardless of scroll
|
|
@@ -22,6 +36,13 @@ export interface VirtualizerOptions {
|
|
|
22
36
|
renderPinnedTop?: () => DocumentFragment;
|
|
23
37
|
/** Optional: render pinned-bottom rows (after the bottom spacer). */
|
|
24
38
|
renderPinnedBottom?: () => DocumentFragment;
|
|
39
|
+
/**
|
|
40
|
+
* Optional: the single message row a zero-row body shows (loading, error, or
|
|
41
|
+
* empty state). Called only when `totalRows` is 0, so the virtualized body
|
|
42
|
+
* carries the same states the ordinary render path does instead of being
|
|
43
|
+
* wiped to nothing.
|
|
44
|
+
*/
|
|
45
|
+
renderEmptyBody?: () => Node | null;
|
|
25
46
|
/** Called after the new window has been inserted into tbody. */
|
|
26
47
|
afterRender?: () => void;
|
|
27
48
|
}
|
|
@@ -40,11 +61,27 @@ export declare class TableVirtualizer {
|
|
|
40
61
|
constructor();
|
|
41
62
|
attach(options: VirtualizerOptions): void;
|
|
42
63
|
detach(): void;
|
|
43
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Publish a new row count. `repaint` false updates the model only — the
|
|
66
|
+
* pending re-render is still armed (lastStartIndex is reset), so the caller's
|
|
67
|
+
* own paint (scrollToIndex / refresh) performs it. Callers that resolve a
|
|
68
|
+
* display index and then scroll MUST use that form: painting here runs
|
|
69
|
+
* `afterRender`, and a host whose afterRender restores keyboard focus would
|
|
70
|
+
* re-enter this method from inside its own update.
|
|
71
|
+
*/
|
|
72
|
+
setTotalRows(total: number, repaint?: boolean): void;
|
|
73
|
+
/** Row count the virtualizer is currently windowing over. */
|
|
74
|
+
getTotalRows(): number;
|
|
44
75
|
/**
|
|
45
76
|
* Force a full re-render of the visible range.
|
|
46
77
|
*/
|
|
47
78
|
refresh(): void;
|
|
79
|
+
/**
|
|
80
|
+
* The element that scrolls RIGHT NOW. A structural re-render of the host
|
|
81
|
+
* swaps the node captured at `attach()`; keep the listener and every lookup
|
|
82
|
+
* (notably the `<tbody>` we paint into) on the live one.
|
|
83
|
+
*/
|
|
84
|
+
private resolveContainer;
|
|
48
85
|
/**
|
|
49
86
|
* Calculate visible range and render if changed.
|
|
50
87
|
*/
|
|
@@ -54,14 +91,14 @@ export declare class TableVirtualizer {
|
|
|
54
91
|
start: number;
|
|
55
92
|
end: number;
|
|
56
93
|
};
|
|
57
|
-
/** Scroll to bring a specific row into view */
|
|
58
|
-
scrollToRow(index: number): void;
|
|
59
94
|
/**
|
|
60
|
-
* Scroll a
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
95
|
+
* Scroll a row into view AND synchronously render the window around it.
|
|
96
|
+
* A programmatic `scrollTop` assignment fires no scroll event, so the window
|
|
97
|
+
* has to be recomputed here — otherwise the viewport lands on bare spacer and
|
|
98
|
+
* the requested row is never in the DOM.
|
|
64
99
|
*/
|
|
100
|
+
scrollToRow(index: number): void;
|
|
101
|
+
/** Scroll to a logical (flattened display) row index. */
|
|
65
102
|
scrollToIndex(index: number): void;
|
|
66
103
|
/** Get current scroll position */
|
|
67
104
|
getScrollPosition(): {
|