@toolbox-web/grid 0.2.5 → 0.2.7

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.
Files changed (71) hide show
  1. package/all.d.ts +486 -80
  2. package/all.js +1364 -1029
  3. package/all.js.map +1 -1
  4. package/index-DG2CZ_Zo.js +3229 -0
  5. package/index-DG2CZ_Zo.js.map +1 -0
  6. package/index.d.ts +222 -11
  7. package/index.js +25 -3143
  8. package/index.js.map +1 -1
  9. package/lib/plugins/clipboard/index.js +1 -1
  10. package/lib/plugins/clipboard/index.js.map +1 -1
  11. package/lib/plugins/column-virtualization/index.js +1 -1
  12. package/lib/plugins/column-virtualization/index.js.map +1 -1
  13. package/lib/plugins/context-menu/index.js +1 -1
  14. package/lib/plugins/context-menu/index.js.map +1 -1
  15. package/lib/plugins/export/index.js +1 -1
  16. package/lib/plugins/export/index.js.map +1 -1
  17. package/lib/plugins/filtering/index.js +184 -149
  18. package/lib/plugins/filtering/index.js.map +1 -1
  19. package/lib/plugins/grouping-columns/index.js +46 -45
  20. package/lib/plugins/grouping-columns/index.js.map +1 -1
  21. package/lib/plugins/grouping-rows/index.js +117 -83
  22. package/lib/plugins/grouping-rows/index.js.map +1 -1
  23. package/lib/plugins/master-detail/index.js +140 -82
  24. package/lib/plugins/master-detail/index.js.map +1 -1
  25. package/lib/plugins/multi-sort/index.js +18 -18
  26. package/lib/plugins/multi-sort/index.js.map +1 -1
  27. package/lib/plugins/pinned-columns/index.js +1 -1
  28. package/lib/plugins/pinned-columns/index.js.map +1 -1
  29. package/lib/plugins/pinned-rows/index.js +55 -47
  30. package/lib/plugins/pinned-rows/index.js.map +1 -1
  31. package/lib/plugins/pivot/index.js +385 -351
  32. package/lib/plugins/pivot/index.js.map +1 -1
  33. package/lib/plugins/reorder/index.js +278 -85
  34. package/lib/plugins/reorder/index.js.map +1 -1
  35. package/lib/plugins/selection/index.js +28 -27
  36. package/lib/plugins/selection/index.js.map +1 -1
  37. package/lib/plugins/server-side/index.js +2 -2
  38. package/lib/plugins/server-side/index.js.map +1 -1
  39. package/lib/plugins/tree/index.js +181 -170
  40. package/lib/plugins/tree/index.js.map +1 -1
  41. package/lib/plugins/undo-redo/index.js +1 -1
  42. package/lib/plugins/undo-redo/index.js.map +1 -1
  43. package/lib/plugins/visibility/index.js +1 -1
  44. package/lib/plugins/visibility/index.js.map +1 -1
  45. package/package.json +1 -1
  46. package/umd/grid.all.umd.js +22 -22
  47. package/umd/grid.all.umd.js.map +1 -1
  48. package/umd/grid.umd.js +12 -12
  49. package/umd/grid.umd.js.map +1 -1
  50. package/umd/plugins/filtering.umd.js +1 -1
  51. package/umd/plugins/filtering.umd.js.map +1 -1
  52. package/umd/plugins/grouping-columns.umd.js +1 -1
  53. package/umd/plugins/grouping-columns.umd.js.map +1 -1
  54. package/umd/plugins/grouping-rows.umd.js +1 -1
  55. package/umd/plugins/grouping-rows.umd.js.map +1 -1
  56. package/umd/plugins/master-detail.umd.js +1 -1
  57. package/umd/plugins/master-detail.umd.js.map +1 -1
  58. package/umd/plugins/multi-sort.umd.js +1 -1
  59. package/umd/plugins/multi-sort.umd.js.map +1 -1
  60. package/umd/plugins/pinned-rows.umd.js +1 -1
  61. package/umd/plugins/pinned-rows.umd.js.map +1 -1
  62. package/umd/plugins/pivot.umd.js +1 -1
  63. package/umd/plugins/pivot.umd.js.map +1 -1
  64. package/umd/plugins/reorder.umd.js +1 -1
  65. package/umd/plugins/reorder.umd.js.map +1 -1
  66. package/umd/plugins/selection.umd.js +1 -1
  67. package/umd/plugins/selection.umd.js.map +1 -1
  68. package/umd/plugins/server-side.umd.js +1 -1
  69. package/umd/plugins/server-side.umd.js.map +1 -1
  70. package/umd/plugins/tree.umd.js +1 -1
  71. package/umd/plugins/tree.umd.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"pinned-rows.umd.js","sources":["../../../../../libs/grid/src/lib/plugins/pinned-rows/pinned-rows.ts","../../../../../libs/grid/src/lib/plugins/pinned-rows/PinnedRowsPlugin.ts"],"sourcesContent":["/**\n * Status Bar Rendering Logic\n *\n * Pure functions for creating and updating the status bar UI.\n * Includes both info bar and aggregation row rendering.\n */\n\nimport { getAggregator } from '../../core/internal/aggregators';\nimport type { ColumnConfig } from '../../core/types';\nimport type { AggregationRowConfig, PinnedRowsConfig, PinnedRowsContext, PinnedRowsPanel } from './types';\n\n/**\n * Creates the info bar DOM element with all configured panels.\n *\n * @param config - The status bar configuration\n * @param context - The current grid context for rendering\n * @returns The complete info bar element\n */\nexport function createInfoBarElement(config: PinnedRowsConfig, context: PinnedRowsContext): HTMLElement {\n const pinnedRows = document.createElement('div');\n pinnedRows.className = 'tbw-pinned-rows';\n pinnedRows.setAttribute('role', 'presentation');\n pinnedRows.setAttribute('aria-live', 'polite');\n\n const left = document.createElement('div');\n left.className = 'tbw-pinned-rows-left';\n\n const center = document.createElement('div');\n center.className = 'tbw-pinned-rows-center';\n\n const right = document.createElement('div');\n right.className = 'tbw-pinned-rows-right';\n\n // Default panels - row count\n if (config.showRowCount !== false) {\n const rowCount = document.createElement('span');\n rowCount.className = 'tbw-status-panel tbw-status-panel-row-count';\n rowCount.textContent = `Total: ${context.totalRows} rows`;\n left.appendChild(rowCount);\n }\n\n // Filtered count panel (only shows when filter is active)\n if (config.showFilteredCount && context.filteredRows !== context.totalRows) {\n const filteredCount = document.createElement('span');\n filteredCount.className = 'tbw-status-panel tbw-status-panel-filtered-count';\n filteredCount.textContent = `Filtered: ${context.filteredRows}`;\n left.appendChild(filteredCount);\n }\n\n // Selected count panel (only shows when rows are selected)\n if (config.showSelectedCount && context.selectedRows > 0) {\n const selectedCount = document.createElement('span');\n selectedCount.className = 'tbw-status-panel tbw-status-panel-selected-count';\n selectedCount.textContent = `Selected: ${context.selectedRows}`;\n right.appendChild(selectedCount);\n }\n\n // Render custom panels\n if (config.customPanels) {\n for (const panel of config.customPanels) {\n const panelEl = renderCustomPanel(panel, context);\n switch (panel.position) {\n case 'left':\n left.appendChild(panelEl);\n break;\n case 'center':\n center.appendChild(panelEl);\n break;\n case 'right':\n right.appendChild(panelEl);\n break;\n }\n }\n }\n\n pinnedRows.appendChild(left);\n pinnedRows.appendChild(center);\n pinnedRows.appendChild(right);\n\n return pinnedRows;\n}\n\n/**\n * Creates a container for aggregation rows at top or bottom.\n *\n * @param position - 'top' or 'bottom'\n * @returns The container element\n */\nexport function createAggregationContainer(position: 'top' | 'bottom'): HTMLElement {\n const container = document.createElement('div');\n container.className = `tbw-aggregation-rows tbw-aggregation-rows-${position}`;\n // Use presentation role since aggregation rows are outside the role=\"grid\" element for layout reasons\n container.setAttribute('role', 'presentation');\n return container;\n}\n\n/**\n * Renders aggregation rows into a container.\n *\n * @param container - The container to render into\n * @param rows - Aggregation row configurations\n * @param columns - Current column configuration\n * @param dataRows - Current row data for aggregation calculations\n */\nexport function renderAggregationRows(\n container: HTMLElement,\n rows: AggregationRowConfig[],\n columns: ColumnConfig[],\n dataRows: unknown[],\n): void {\n container.innerHTML = '';\n\n for (const rowConfig of rows) {\n const rowEl = document.createElement('div');\n rowEl.className = 'tbw-aggregation-row';\n // Use presentation role since aggregation rows are outside the role=\"grid\" element\n rowEl.setAttribute('role', 'presentation');\n if (rowConfig.id) {\n rowEl.setAttribute('data-aggregation-id', rowConfig.id);\n }\n\n if (rowConfig.fullWidth) {\n // Full-width mode: single cell spanning all columns\n const cell = document.createElement('div');\n cell.className = 'tbw-aggregation-cell tbw-aggregation-cell-full';\n cell.style.gridColumn = '1 / -1';\n cell.textContent = rowConfig.label || '';\n rowEl.appendChild(cell);\n } else {\n // Per-column mode: one cell per column with aggregated/static values\n for (const col of columns) {\n const cell = document.createElement('div');\n cell.className = 'tbw-aggregation-cell';\n cell.setAttribute('data-field', col.field);\n\n let value: unknown;\n\n // Check for aggregator first\n const aggRef = rowConfig.aggregators?.[col.field];\n if (aggRef) {\n const aggFn = getAggregator(aggRef);\n if (aggFn) {\n value = aggFn(dataRows, col.field, col);\n }\n } else if (rowConfig.cells && Object.prototype.hasOwnProperty.call(rowConfig.cells, col.field)) {\n // Static or computed cell value\n const staticVal = rowConfig.cells[col.field];\n if (typeof staticVal === 'function') {\n value = staticVal(dataRows, col.field, col);\n } else {\n value = staticVal;\n }\n }\n\n cell.textContent = value != null ? String(value) : '';\n rowEl.appendChild(cell);\n }\n }\n\n container.appendChild(rowEl);\n }\n}\n\n/**\n * Renders a custom panel element.\n *\n * @param panel - The panel definition\n * @param context - The current grid context\n * @returns The panel DOM element\n */\nfunction renderCustomPanel(panel: PinnedRowsPanel, context: PinnedRowsContext): HTMLElement {\n const panelEl = document.createElement('div');\n panelEl.className = 'tbw-status-panel tbw-status-panel-custom';\n panelEl.id = `status-panel-${panel.id}`;\n\n const content = panel.render(context);\n\n if (typeof content === 'string') {\n panelEl.innerHTML = content;\n } else {\n panelEl.appendChild(content);\n }\n\n return panelEl;\n}\n\n/**\n * Builds the status bar context from grid state and plugin states.\n *\n * @param rows - Current row data\n * @param columns - Current column configuration\n * @param grid - Grid element reference\n * @param selectionState - Optional selection plugin state\n * @param filterState - Optional filtering plugin state\n * @returns The status bar context\n */\nexport function buildContext(\n rows: unknown[],\n columns: unknown[],\n grid: HTMLElement,\n selectionState?: { selected: Set<number> } | null,\n filterState?: { cachedResult: unknown[] | null } | null,\n): PinnedRowsContext {\n return {\n totalRows: rows.length,\n filteredRows: filterState?.cachedResult?.length ?? rows.length,\n selectedRows: selectionState?.selected?.size ?? 0,\n columns: columns as PinnedRowsContext['columns'],\n rows,\n grid,\n };\n}\n\n// Keep old name as alias for backwards compatibility\nexport const createPinnedRowsElement = createInfoBarElement;\n","/**\n * Pinned Rows Plugin (Class-based)\n *\n * Adds info bars and aggregation rows to the grid.\n * - Info bar: Shows row counts, selection info, and custom panels\n * - Aggregation rows: Footer/header rows with computed values (sum, avg, etc.)\n */\n\nimport { BaseGridPlugin } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig } from '../../core/types';\nimport { buildContext, createAggregationContainer, createInfoBarElement, renderAggregationRows } from './pinned-rows';\nimport styles from './pinned-rows.css?inline';\nimport type { AggregationRowConfig, PinnedRowsConfig, PinnedRowsContext, PinnedRowsPanel } from './types';\n\n/**\n * Pinned Rows Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new PinnedRowsPlugin({\n * enabled: true,\n * position: 'bottom',\n * showRowCount: true,\n * showSelectedCount: true,\n * aggregationRows: [\n * { id: 'totals', position: 'bottom', values: { amount: 'sum' } },\n * ],\n * })\n * ```\n */\nexport class PinnedRowsPlugin extends BaseGridPlugin<PinnedRowsConfig> {\n readonly name = 'pinnedRows';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<PinnedRowsConfig> {\n return {\n position: 'bottom',\n showRowCount: true,\n showSelectedCount: true,\n showFilteredCount: true,\n };\n }\n\n // #region Internal State\n private infoBarElement: HTMLElement | null = null;\n private topAggregationContainer: HTMLElement | null = null;\n private bottomAggregationContainer: HTMLElement | null = null;\n private footerWrapper: HTMLElement | null = null;\n // #endregion\n\n // #region Lifecycle\n override detach(): void {\n if (this.infoBarElement) {\n this.infoBarElement.remove();\n this.infoBarElement = null;\n }\n if (this.topAggregationContainer) {\n this.topAggregationContainer.remove();\n this.topAggregationContainer = null;\n }\n if (this.bottomAggregationContainer) {\n this.bottomAggregationContainer.remove();\n this.bottomAggregationContainer = null;\n }\n if (this.footerWrapper) {\n this.footerWrapper.remove();\n this.footerWrapper = null;\n }\n }\n // #endregion\n\n // #region Hooks\n override afterRender(): void {\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) return;\n\n // Use .tbw-scroll-area so footer is inside the horizontal scroll area,\n // otherwise fall back to .tbw-grid-content or root container\n const container =\n shadowRoot.querySelector('.tbw-scroll-area') ??\n shadowRoot.querySelector('.tbw-grid-content') ??\n shadowRoot.children[0];\n if (!container) return;\n\n // Build context with plugin states\n const selectionState = this.getSelectionState();\n const filterState = this.getFilterState();\n\n const context = buildContext(\n this.rows as unknown[],\n this.columns as unknown[],\n this.grid as unknown as HTMLElement,\n selectionState,\n filterState,\n );\n\n // #region Handle Aggregation Rows\n const aggregationRows = this.config.aggregationRows || [];\n const topRows = aggregationRows.filter((r) => r.position === 'top');\n const bottomRows = aggregationRows.filter((r) => r.position !== 'top');\n\n // Top aggregation rows\n if (topRows.length > 0) {\n if (!this.topAggregationContainer) {\n this.topAggregationContainer = createAggregationContainer('top');\n const header = shadowRoot.querySelector('.header');\n if (header && header.nextSibling) {\n container.insertBefore(this.topAggregationContainer, header.nextSibling);\n } else {\n container.appendChild(this.topAggregationContainer);\n }\n }\n renderAggregationRows(\n this.topAggregationContainer,\n topRows,\n this.visibleColumns as ColumnConfig[],\n this.rows as unknown[],\n );\n } else if (this.topAggregationContainer) {\n this.topAggregationContainer.remove();\n this.topAggregationContainer = null;\n }\n\n // Handle footer\n const hasInfoContent =\n this.config.showRowCount !== false ||\n (this.config.showSelectedCount && context.selectedRows > 0) ||\n (this.config.showFilteredCount && context.filteredRows !== context.totalRows) ||\n (this.config.customPanels && this.config.customPanels.length > 0);\n const hasBottomInfoBar = hasInfoContent && this.config.position !== 'top';\n const needsFooter = bottomRows.length > 0 || hasBottomInfoBar;\n\n // Handle top info bar\n if (hasInfoContent && this.config.position === 'top') {\n if (!this.infoBarElement) {\n this.infoBarElement = createInfoBarElement(this.config, context);\n container.insertBefore(this.infoBarElement, container.firstChild);\n } else {\n const newInfoBar = createInfoBarElement(this.config, context);\n this.infoBarElement.replaceWith(newInfoBar);\n this.infoBarElement = newInfoBar;\n }\n } else if (this.config.position === 'top' && this.infoBarElement) {\n this.infoBarElement.remove();\n this.infoBarElement = null;\n }\n\n // Create/manage footer wrapper\n if (needsFooter) {\n if (!this.footerWrapper) {\n this.footerWrapper = document.createElement('div');\n this.footerWrapper.className = 'tbw-footer';\n container.appendChild(this.footerWrapper);\n }\n\n this.footerWrapper.innerHTML = '';\n\n if (bottomRows.length > 0) {\n if (!this.bottomAggregationContainer) {\n this.bottomAggregationContainer = createAggregationContainer('bottom');\n }\n this.footerWrapper.appendChild(this.bottomAggregationContainer);\n renderAggregationRows(\n this.bottomAggregationContainer,\n bottomRows,\n this.visibleColumns as ColumnConfig[],\n this.rows as unknown[],\n );\n }\n\n if (hasBottomInfoBar) {\n this.infoBarElement = createInfoBarElement(this.config, context);\n this.footerWrapper.appendChild(this.infoBarElement);\n }\n } else {\n this.cleanupFooter();\n }\n // #endregion\n }\n // #endregion\n\n // #region Private Methods\n private cleanup(): void {\n if (this.infoBarElement) {\n this.infoBarElement.remove();\n this.infoBarElement = null;\n }\n if (this.topAggregationContainer) {\n this.topAggregationContainer.remove();\n this.topAggregationContainer = null;\n }\n if (this.bottomAggregationContainer) {\n this.bottomAggregationContainer.remove();\n this.bottomAggregationContainer = null;\n }\n if (this.footerWrapper) {\n this.footerWrapper.remove();\n this.footerWrapper = null;\n }\n }\n\n private cleanupFooter(): void {\n if (this.footerWrapper) {\n this.footerWrapper.remove();\n this.footerWrapper = null;\n }\n if (this.bottomAggregationContainer) {\n this.bottomAggregationContainer.remove();\n this.bottomAggregationContainer = null;\n }\n if (this.infoBarElement && this.config.position !== 'top') {\n this.infoBarElement.remove();\n this.infoBarElement = null;\n }\n }\n\n private getSelectionState(): { selected: Set<number> } | null {\n // Try to get selection plugin state\n try {\n const grid = this.grid as any;\n return grid?.getPluginState?.('selection') ?? null;\n } catch {\n return null;\n }\n }\n\n private getFilterState(): { cachedResult: unknown[] | null } | null {\n try {\n const grid = this.grid as any;\n return grid?.getPluginState?.('filtering') ?? null;\n } catch {\n return null;\n }\n }\n // #endregion\n\n // #region Public API\n /**\n * Refresh the status bar to reflect current grid state.\n */\n refresh(): void {\n this.requestRender();\n }\n\n /**\n * Get the current status bar context.\n * @returns The context with row counts and other info\n */\n getContext(): PinnedRowsContext {\n const selectionState = this.getSelectionState();\n const filterState = this.getFilterState();\n\n return buildContext(\n this.rows as unknown[],\n this.columns as unknown[],\n this.grid as unknown as HTMLElement,\n selectionState,\n filterState,\n );\n }\n\n /**\n * Add a custom panel to the info bar.\n * @param panel - The panel configuration to add\n */\n addPanel(panel: PinnedRowsPanel): void {\n if (!this.config.customPanels) {\n this.config.customPanels = [];\n }\n this.config.customPanels.push(panel);\n this.requestRender();\n }\n\n /**\n * Remove a custom panel by ID.\n * @param id - The panel ID to remove\n */\n removePanel(id: string): void {\n if (this.config.customPanels) {\n this.config.customPanels = this.config.customPanels.filter((p) => p.id !== id);\n this.requestRender();\n }\n }\n\n /**\n * Add an aggregation row.\n * @param row - The aggregation row configuration\n */\n addAggregationRow(row: AggregationRowConfig): void {\n if (!this.config.aggregationRows) {\n this.config.aggregationRows = [];\n }\n this.config.aggregationRows.push(row);\n this.requestRender();\n }\n\n /**\n * Remove an aggregation row by ID.\n * @param id - The aggregation row ID to remove\n */\n removeAggregationRow(id: string): void {\n if (this.config.aggregationRows) {\n this.config.aggregationRows = this.config.aggregationRows.filter((r) => r.id !== id);\n this.requestRender();\n }\n }\n // #endregion\n\n // #region Styles\n override readonly styles = styles;\n // #endregion\n}\n"],"names":["createInfoBarElement","config","context","pinnedRows","left","center","right","rowCount","filteredCount","selectedCount","panel","panelEl","renderCustomPanel","createAggregationContainer","position","container","renderAggregationRows","rows","columns","dataRows","rowConfig","rowEl","cell","col","value","aggRef","aggFn","getAggregator","staticVal","content","buildContext","grid","selectionState","filterState","PinnedRowsPlugin","BaseGridPlugin","shadowRoot","aggregationRows","topRows","r","bottomRows","header","hasInfoContent","hasBottomInfoBar","needsFooter","newInfoBar","id","p","row","styles"],"mappings":"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"}
1
+ {"version":3,"file":"pinned-rows.umd.js","sources":["../../../../../libs/grid/src/lib/plugins/pinned-rows/pinned-rows.ts","../../../../../libs/grid/src/lib/plugins/pinned-rows/PinnedRowsPlugin.ts"],"sourcesContent":["/**\n * Status Bar Rendering Logic\n *\n * Pure functions for creating and updating the status bar UI.\n * Includes both info bar and aggregation row rendering.\n */\n\nimport { getAggregator } from '../../core/internal/aggregators';\nimport type { ColumnConfig } from '../../core/types';\nimport type {\n AggregationRowConfig,\n AggregatorConfig,\n AggregatorDefinition,\n PinnedRowsConfig,\n PinnedRowsContext,\n PinnedRowsPanel,\n} from './types';\n\n/**\n * Check if an aggregator definition is a full config object (with aggFunc and optional formatter).\n */\nfunction isAggregatorConfig(def: AggregatorDefinition): def is AggregatorConfig {\n return typeof def === 'object' && def !== null && 'aggFunc' in def;\n}\n\n/**\n * Creates the info bar DOM element with all configured panels.\n *\n * @param config - The status bar configuration\n * @param context - The current grid context for rendering\n * @returns The complete info bar element\n */\nexport function createInfoBarElement(config: PinnedRowsConfig, context: PinnedRowsContext): HTMLElement {\n const pinnedRows = document.createElement('div');\n pinnedRows.className = 'tbw-pinned-rows';\n pinnedRows.setAttribute('role', 'presentation');\n pinnedRows.setAttribute('aria-live', 'polite');\n\n const left = document.createElement('div');\n left.className = 'tbw-pinned-rows-left';\n\n const center = document.createElement('div');\n center.className = 'tbw-pinned-rows-center';\n\n const right = document.createElement('div');\n right.className = 'tbw-pinned-rows-right';\n\n // Default panels - row count\n if (config.showRowCount !== false) {\n const rowCount = document.createElement('span');\n rowCount.className = 'tbw-status-panel tbw-status-panel-row-count';\n rowCount.textContent = `Total: ${context.totalRows} rows`;\n left.appendChild(rowCount);\n }\n\n // Filtered count panel (only shows when filter is active)\n if (config.showFilteredCount && context.filteredRows !== context.totalRows) {\n const filteredCount = document.createElement('span');\n filteredCount.className = 'tbw-status-panel tbw-status-panel-filtered-count';\n filteredCount.textContent = `Filtered: ${context.filteredRows}`;\n left.appendChild(filteredCount);\n }\n\n // Selected count panel (only shows when rows are selected)\n if (config.showSelectedCount && context.selectedRows > 0) {\n const selectedCount = document.createElement('span');\n selectedCount.className = 'tbw-status-panel tbw-status-panel-selected-count';\n selectedCount.textContent = `Selected: ${context.selectedRows}`;\n right.appendChild(selectedCount);\n }\n\n // Render custom panels\n if (config.customPanels) {\n for (const panel of config.customPanels) {\n const panelEl = renderCustomPanel(panel, context);\n switch (panel.position) {\n case 'left':\n left.appendChild(panelEl);\n break;\n case 'center':\n center.appendChild(panelEl);\n break;\n case 'right':\n right.appendChild(panelEl);\n break;\n }\n }\n }\n\n pinnedRows.appendChild(left);\n pinnedRows.appendChild(center);\n pinnedRows.appendChild(right);\n\n return pinnedRows;\n}\n\n/**\n * Creates a container for aggregation rows at top or bottom.\n *\n * @param position - 'top' or 'bottom'\n * @returns The container element\n */\nexport function createAggregationContainer(position: 'top' | 'bottom'): HTMLElement {\n const container = document.createElement('div');\n container.className = `tbw-aggregation-rows tbw-aggregation-rows-${position}`;\n // Use presentation role since aggregation rows are outside the role=\"grid\" element for layout reasons\n container.setAttribute('role', 'presentation');\n return container;\n}\n\n/**\n * Renders aggregation rows into a container.\n *\n * @param container - The container to render into\n * @param rows - Aggregation row configurations\n * @param columns - Current column configuration\n * @param dataRows - Current row data for aggregation calculations\n */\nexport function renderAggregationRows(\n container: HTMLElement,\n rows: AggregationRowConfig[],\n columns: ColumnConfig[],\n dataRows: unknown[],\n): void {\n container.innerHTML = '';\n\n for (const rowConfig of rows) {\n const rowEl = document.createElement('div');\n rowEl.className = 'tbw-aggregation-row';\n // Use presentation role since aggregation rows are outside the role=\"grid\" element\n rowEl.setAttribute('role', 'presentation');\n if (rowConfig.id) {\n rowEl.setAttribute('data-aggregation-id', rowConfig.id);\n }\n\n if (rowConfig.fullWidth) {\n // Full-width mode: single cell spanning all columns\n const cell = document.createElement('div');\n cell.className = 'tbw-aggregation-cell tbw-aggregation-cell-full';\n cell.style.gridColumn = '1 / -1';\n cell.textContent = rowConfig.label || '';\n rowEl.appendChild(cell);\n } else {\n // Per-column mode: one cell per column with aggregated/static values\n for (const col of columns) {\n const cell = document.createElement('div');\n cell.className = 'tbw-aggregation-cell';\n cell.setAttribute('data-field', col.field);\n\n let value: unknown;\n let formatter: ((value: unknown, field: string, column?: ColumnConfig) => string) | undefined;\n\n // Check for aggregator first\n const aggDef = rowConfig.aggregators?.[col.field];\n if (aggDef) {\n // Handle both simple ref and full config object\n if (isAggregatorConfig(aggDef)) {\n const aggFn = getAggregator(aggDef.aggFunc);\n if (aggFn) {\n value = aggFn(dataRows, col.field, col);\n }\n formatter = aggDef.formatter;\n } else {\n const aggFn = getAggregator(aggDef);\n if (aggFn) {\n value = aggFn(dataRows, col.field, col);\n }\n }\n } else if (rowConfig.cells && Object.prototype.hasOwnProperty.call(rowConfig.cells, col.field)) {\n // Static or computed cell value\n const staticVal = rowConfig.cells[col.field];\n if (typeof staticVal === 'function') {\n value = staticVal(dataRows, col.field, col);\n } else {\n value = staticVal;\n }\n }\n\n // Apply formatter if provided, otherwise convert to string\n if (value != null) {\n cell.textContent = formatter ? formatter(value, col.field, col) : String(value);\n } else {\n cell.textContent = '';\n }\n rowEl.appendChild(cell);\n }\n }\n\n container.appendChild(rowEl);\n }\n}\n\n/**\n * Renders a custom panel element.\n *\n * @param panel - The panel definition\n * @param context - The current grid context\n * @returns The panel DOM element\n */\nfunction renderCustomPanel(panel: PinnedRowsPanel, context: PinnedRowsContext): HTMLElement {\n const panelEl = document.createElement('div');\n panelEl.className = 'tbw-status-panel tbw-status-panel-custom';\n panelEl.id = `status-panel-${panel.id}`;\n\n const content = panel.render(context);\n\n if (typeof content === 'string') {\n panelEl.innerHTML = content;\n } else {\n panelEl.appendChild(content);\n }\n\n return panelEl;\n}\n\n/**\n * Builds the status bar context from grid state and plugin states.\n *\n * @param rows - Current row data\n * @param columns - Current column configuration\n * @param grid - Grid element reference\n * @param selectionState - Optional selection plugin state\n * @param filterState - Optional filtering plugin state\n * @returns The status bar context\n */\nexport function buildContext(\n rows: unknown[],\n columns: unknown[],\n grid: HTMLElement,\n selectionState?: { selected: Set<number> } | null,\n filterState?: { cachedResult: unknown[] | null } | null,\n): PinnedRowsContext {\n return {\n totalRows: rows.length,\n filteredRows: filterState?.cachedResult?.length ?? rows.length,\n selectedRows: selectionState?.selected?.size ?? 0,\n columns: columns as PinnedRowsContext['columns'],\n rows,\n grid,\n };\n}\n\n// Keep old name as alias for backwards compatibility\nexport const createPinnedRowsElement = createInfoBarElement;\n","/**\n * Pinned Rows Plugin (Class-based)\n *\n * Adds info bars and aggregation rows to the grid.\n * - Info bar: Shows row counts, selection info, and custom panels\n * - Aggregation rows: Footer/header rows with computed values (sum, avg, etc.)\n */\n\nimport { BaseGridPlugin } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig } from '../../core/types';\nimport { buildContext, createAggregationContainer, createInfoBarElement, renderAggregationRows } from './pinned-rows';\nimport styles from './pinned-rows.css?inline';\nimport type { AggregationRowConfig, PinnedRowsConfig, PinnedRowsContext, PinnedRowsPanel } from './types';\n\n/**\n * Pinned Rows Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new PinnedRowsPlugin({\n * enabled: true,\n * position: 'bottom',\n * showRowCount: true,\n * showSelectedCount: true,\n * aggregationRows: [\n * { id: 'totals', position: 'bottom', values: { amount: 'sum' } },\n * ],\n * })\n * ```\n */\nexport class PinnedRowsPlugin extends BaseGridPlugin<PinnedRowsConfig> {\n readonly name = 'pinnedRows';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<PinnedRowsConfig> {\n return {\n position: 'bottom',\n showRowCount: true,\n showSelectedCount: true,\n showFilteredCount: true,\n };\n }\n\n // #region Internal State\n private infoBarElement: HTMLElement | null = null;\n private topAggregationContainer: HTMLElement | null = null;\n private bottomAggregationContainer: HTMLElement | null = null;\n private footerWrapper: HTMLElement | null = null;\n // #endregion\n\n // #region Lifecycle\n override detach(): void {\n if (this.infoBarElement) {\n this.infoBarElement.remove();\n this.infoBarElement = null;\n }\n if (this.topAggregationContainer) {\n this.topAggregationContainer.remove();\n this.topAggregationContainer = null;\n }\n if (this.bottomAggregationContainer) {\n this.bottomAggregationContainer.remove();\n this.bottomAggregationContainer = null;\n }\n if (this.footerWrapper) {\n this.footerWrapper.remove();\n this.footerWrapper = null;\n }\n }\n // #endregion\n\n // #region Hooks\n override afterRender(): void {\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) return;\n\n // Use .tbw-scroll-area so footer is inside the horizontal scroll area,\n // otherwise fall back to .tbw-grid-content or root container\n const container =\n shadowRoot.querySelector('.tbw-scroll-area') ??\n shadowRoot.querySelector('.tbw-grid-content') ??\n shadowRoot.children[0];\n if (!container) return;\n\n // Build context with plugin states\n const selectionState = this.getSelectionState();\n const filterState = this.getFilterState();\n\n const context = buildContext(\n this.rows as unknown[],\n this.columns as unknown[],\n this.grid as unknown as HTMLElement,\n selectionState,\n filterState,\n );\n\n // #region Handle Aggregation Rows\n const aggregationRows = this.config.aggregationRows || [];\n const topRows = aggregationRows.filter((r) => r.position === 'top');\n const bottomRows = aggregationRows.filter((r) => r.position !== 'top');\n\n // Top aggregation rows\n if (topRows.length > 0) {\n if (!this.topAggregationContainer) {\n this.topAggregationContainer = createAggregationContainer('top');\n const header = shadowRoot.querySelector('.header');\n if (header && header.nextSibling) {\n container.insertBefore(this.topAggregationContainer, header.nextSibling);\n } else {\n container.appendChild(this.topAggregationContainer);\n }\n }\n renderAggregationRows(\n this.topAggregationContainer,\n topRows,\n this.visibleColumns as ColumnConfig[],\n this.rows as unknown[],\n );\n } else if (this.topAggregationContainer) {\n this.topAggregationContainer.remove();\n this.topAggregationContainer = null;\n }\n\n // Handle footer\n const hasInfoContent =\n this.config.showRowCount !== false ||\n (this.config.showSelectedCount && context.selectedRows > 0) ||\n (this.config.showFilteredCount && context.filteredRows !== context.totalRows) ||\n (this.config.customPanels && this.config.customPanels.length > 0);\n const hasBottomInfoBar = hasInfoContent && this.config.position !== 'top';\n const needsFooter = bottomRows.length > 0 || hasBottomInfoBar;\n\n // Handle top info bar\n if (hasInfoContent && this.config.position === 'top') {\n if (!this.infoBarElement) {\n this.infoBarElement = createInfoBarElement(this.config, context);\n container.insertBefore(this.infoBarElement, container.firstChild);\n } else {\n const newInfoBar = createInfoBarElement(this.config, context);\n this.infoBarElement.replaceWith(newInfoBar);\n this.infoBarElement = newInfoBar;\n }\n } else if (this.config.position === 'top' && this.infoBarElement) {\n this.infoBarElement.remove();\n this.infoBarElement = null;\n }\n\n // Create/manage footer wrapper\n if (needsFooter) {\n if (!this.footerWrapper) {\n this.footerWrapper = document.createElement('div');\n this.footerWrapper.className = 'tbw-footer';\n container.appendChild(this.footerWrapper);\n }\n\n this.footerWrapper.innerHTML = '';\n\n if (bottomRows.length > 0) {\n if (!this.bottomAggregationContainer) {\n this.bottomAggregationContainer = createAggregationContainer('bottom');\n }\n this.footerWrapper.appendChild(this.bottomAggregationContainer);\n renderAggregationRows(\n this.bottomAggregationContainer,\n bottomRows,\n this.visibleColumns as ColumnConfig[],\n this.rows as unknown[],\n );\n }\n\n if (hasBottomInfoBar) {\n this.infoBarElement = createInfoBarElement(this.config, context);\n this.footerWrapper.appendChild(this.infoBarElement);\n }\n } else {\n this.cleanupFooter();\n }\n // #endregion\n }\n // #endregion\n\n // #region Private Methods\n private cleanup(): void {\n if (this.infoBarElement) {\n this.infoBarElement.remove();\n this.infoBarElement = null;\n }\n if (this.topAggregationContainer) {\n this.topAggregationContainer.remove();\n this.topAggregationContainer = null;\n }\n if (this.bottomAggregationContainer) {\n this.bottomAggregationContainer.remove();\n this.bottomAggregationContainer = null;\n }\n if (this.footerWrapper) {\n this.footerWrapper.remove();\n this.footerWrapper = null;\n }\n }\n\n private cleanupFooter(): void {\n if (this.footerWrapper) {\n this.footerWrapper.remove();\n this.footerWrapper = null;\n }\n if (this.bottomAggregationContainer) {\n this.bottomAggregationContainer.remove();\n this.bottomAggregationContainer = null;\n }\n if (this.infoBarElement && this.config.position !== 'top') {\n this.infoBarElement.remove();\n this.infoBarElement = null;\n }\n }\n\n private getSelectionState(): { selected: Set<number> } | null {\n // Try to get selection plugin state\n try {\n const grid = this.grid as any;\n return grid?.getPluginState?.('selection') ?? null;\n } catch {\n return null;\n }\n }\n\n private getFilterState(): { cachedResult: unknown[] | null } | null {\n try {\n const grid = this.grid as any;\n return grid?.getPluginState?.('filtering') ?? null;\n } catch {\n return null;\n }\n }\n // #endregion\n\n // #region Public API\n /**\n * Refresh the status bar to reflect current grid state.\n */\n refresh(): void {\n this.requestRender();\n }\n\n /**\n * Get the current status bar context.\n * @returns The context with row counts and other info\n */\n getContext(): PinnedRowsContext {\n const selectionState = this.getSelectionState();\n const filterState = this.getFilterState();\n\n return buildContext(\n this.rows as unknown[],\n this.columns as unknown[],\n this.grid as unknown as HTMLElement,\n selectionState,\n filterState,\n );\n }\n\n /**\n * Add a custom panel to the info bar.\n * @param panel - The panel configuration to add\n */\n addPanel(panel: PinnedRowsPanel): void {\n if (!this.config.customPanels) {\n this.config.customPanels = [];\n }\n this.config.customPanels.push(panel);\n this.requestRender();\n }\n\n /**\n * Remove a custom panel by ID.\n * @param id - The panel ID to remove\n */\n removePanel(id: string): void {\n if (this.config.customPanels) {\n this.config.customPanels = this.config.customPanels.filter((p) => p.id !== id);\n this.requestRender();\n }\n }\n\n /**\n * Add an aggregation row.\n * @param row - The aggregation row configuration\n */\n addAggregationRow(row: AggregationRowConfig): void {\n if (!this.config.aggregationRows) {\n this.config.aggregationRows = [];\n }\n this.config.aggregationRows.push(row);\n this.requestRender();\n }\n\n /**\n * Remove an aggregation row by ID.\n * @param id - The aggregation row ID to remove\n */\n removeAggregationRow(id: string): void {\n if (this.config.aggregationRows) {\n this.config.aggregationRows = this.config.aggregationRows.filter((r) => r.id !== id);\n this.requestRender();\n }\n }\n // #endregion\n\n // #region Styles\n override readonly styles = styles;\n // #endregion\n}\n"],"names":["isAggregatorConfig","def","createInfoBarElement","config","context","pinnedRows","left","center","right","rowCount","filteredCount","selectedCount","panel","panelEl","renderCustomPanel","createAggregationContainer","position","container","renderAggregationRows","rows","columns","dataRows","rowConfig","rowEl","cell","col","value","formatter","aggDef","aggFn","getAggregator","staticVal","content","buildContext","grid","selectionState","filterState","PinnedRowsPlugin","BaseGridPlugin","shadowRoot","aggregationRows","topRows","r","bottomRows","header","hasInfoContent","hasBottomInfoBar","needsFooter","newInfoBar","id","p","row","styles"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- (function(h,f){typeof exports=="object"&&typeof module<"u"?f(exports,require("../../core/plugin/base-plugin"),require("../../core/internal/aggregators")):typeof define=="function"&&define.amd?define(["exports","../../core/plugin/base-plugin","../../core/internal/aggregators"],f):(h=typeof globalThis<"u"?globalThis:h||self,f(h.TbwGridPlugin_pivot={},h.TbwGrid,h.TbwGrid))})(this,(function(h,f,_){"use strict";const L=_.getValueAggregator;function P(a){const e=[];return!a.rowGroupFields?.length&&!a.columnGroupFields?.length&&e.push("At least one row or column group field is required"),a.valueFields?.length||e.push("At least one value field is required"),e}function w(a,e){return[...a,e].join("|")}function E(a,e){const n=e.rowGroupFields??[],o=e.columnGroupFields??[],i=e.valueFields??[],t=k(a,o),r=C(a,n,o,t,i,0,""),l=K(r,t,i),s=Object.values(l).reduce((d,c)=>d+c,0);return{rows:r,columnKeys:t,totals:l,grandTotal:s}}function k(a,e){if(e.length===0)return["value"];const n=new Set;for(const o of a){const i=e.map(t=>String(o[t]??"")).join("|");n.add(i)}return[...n].sort()}function N(a,e){const n=new Map;for(const o of a){const i=String(o[e]??""),t=n.get(i);t?t.push(o):n.set(i,[o])}return n}function C(a,e,n,o,i,t,r){const l=[];if(e.length===0){const u=F(a,n,o,i),v=y(u);return l.push({rowKey:r||"all",rowLabel:r||"All",depth:t,values:u,total:v,isGroup:!1,rowCount:a.length}),l}const s=e[0],d=e.slice(1),c=d.length>0,p=N(a,s);for(const[u,v]of p){const A=r?`${r}|${u}`:u,G=F(v,n,o,i),B=y(G);let T;c&&(T=C(v,d,n,o,i,t+1,A)),l.push({rowKey:A,rowLabel:u||"(blank)",depth:t,values:G,total:B,isGroup:c,children:T,rowCount:v.length})}return l}function F(a,e,n,o){const i={};for(const t of n)for(const r of o){const s=(e.length>0?a.filter(u=>e.map(v=>String(u[v]??"")).join("|")===t):a).map(u=>Number(u[r.field])||0),d=L(r.aggFunc),c=s.length>0?d(s):null,p=w([t],r.field);i[p]=c}return i}function y(a){let e=0;for(const n of Object.values(a))e+=n??0;return e}function K(a,e,n){const o={};function i(t){for(const r of t)if(!r.isGroup||!r.children?.length)for(const l of e)for(const s of n){const d=w([l],s.field);o[d]=(o[d]??0)+(r.values[d]??0)}else r.children&&i(r.children)}return i(a),o}function S(a,e,n=!0){const o=[];function i(t){o.push(t);const r=e?e.has(t.rowKey):n;if(t.children&&r)for(const l of t.children)i(l)}for(const t of a)i(t);return o}function m(a){const e=[];function n(o){if(o.isGroup&&e.push(o.rowKey),o.children)for(const i of o.children)n(i)}for(const o of a)n(o);return e}const V=["sum","avg","count","min","max","first","last"];function z(a,e,n,o){const i=new AbortController,t={config:e,callbacks:o,signal:i.signal},r=document.createElement("div");return r.className="tbw-pivot-panel",r.appendChild(b("Options",()=>M(n,t))),r.appendChild(b("Row Groups",()=>R("rowGroups",t))),r.appendChild(b("Column Groups",()=>R("columnGroups",t))),r.appendChild(b("Values",()=>D(t))),r.appendChild(b("Available Fields",()=>q(t))),a.appendChild(r),()=>{i.abort(),r.remove()}}function b(a,e){const n=document.createElement("div");n.className="tbw-pivot-section";const o=document.createElement("div");o.className="tbw-pivot-section-header",o.textContent=a;const i=document.createElement("div");return i.className="tbw-pivot-section-content",i.appendChild(e()),n.appendChild(o),n.appendChild(i),n}function R(a,e){const{config:n,callbacks:o,signal:i}=e,t=document.createElement("div");t.className="tbw-pivot-drop-zone",t.setAttribute("data-zone",a);const r=a==="rowGroups"?n.rowGroupFields??[]:n.columnGroupFields??[];if(r.length===0){const l=document.createElement("div");l.className="tbw-pivot-placeholder",l.textContent="Drag fields here or click to add",t.appendChild(l)}else for(const l of r)t.appendChild(I(l,a,e));return t.addEventListener("dragover",l=>{l.preventDefault(),t.classList.add("drag-over")},{signal:i}),t.addEventListener("dragleave",()=>{t.classList.remove("drag-over")},{signal:i}),t.addEventListener("drop",l=>{l.preventDefault(),t.classList.remove("drag-over");const s=l.dataTransfer?.getData("text/plain");s&&o.onAddFieldToZone(s,a)},{signal:i}),t}function I(a,e,n){const{callbacks:o,signal:i}=n,t=document.createElement("div");t.className="tbw-pivot-field-chip",t.draggable=!0;const r=o.getAvailableFields().find(d=>d.field===a),l=document.createElement("span");l.className="tbw-pivot-chip-label",l.textContent=r?.header??a;const s=document.createElement("button");return s.className="tbw-pivot-chip-remove",s.innerHTML="×",s.title="Remove field",s.addEventListener("click",d=>{d.stopPropagation(),o.onRemoveFieldFromZone(a,e)},{signal:i}),t.appendChild(l),t.appendChild(s),t.addEventListener("dragstart",d=>{d.dataTransfer?.setData("text/plain",a),d.dataTransfer?.setData("source-zone",e),t.classList.add("dragging")},{signal:i}),t.addEventListener("dragend",()=>{t.classList.remove("dragging")},{signal:i}),t}function D(a){const{config:e,callbacks:n,signal:o}=a,i=document.createElement("div");i.className="tbw-pivot-drop-zone tbw-pivot-values-zone",i.setAttribute("data-zone","values");const t=e.valueFields??[];if(t.length===0){const r=document.createElement("div");r.className="tbw-pivot-placeholder",r.textContent="Drag numeric fields here for aggregation",i.appendChild(r)}else for(const r of t)i.appendChild(H(r,a));return i.addEventListener("dragover",r=>{r.preventDefault(),i.classList.add("drag-over")},{signal:o}),i.addEventListener("dragleave",()=>{i.classList.remove("drag-over")},{signal:o}),i.addEventListener("drop",r=>{r.preventDefault(),i.classList.remove("drag-over");const l=r.dataTransfer?.getData("text/plain");l&&n.onAddValueField(l,"sum")},{signal:o}),i}function H(a,e){const{callbacks:n,signal:o}=e,i=document.createElement("div");i.className="tbw-pivot-field-chip tbw-pivot-value-chip";const t=n.getAvailableFields().find(c=>c.field===a.field),r=document.createElement("div");r.className="tbw-pivot-value-label-wrapper";const l=document.createElement("span");l.className="tbw-pivot-chip-label",l.textContent=t?.header??a.field;const s=document.createElement("select");s.className="tbw-pivot-agg-select",s.title="Aggregation function";for(const c of V){const p=document.createElement("option");p.value=c,p.textContent=c.toUpperCase(),p.selected=c===a.aggFunc,s.appendChild(p)}s.addEventListener("change",()=>{n.onUpdateValueAggFunc(a.field,s.value)},{signal:o});const d=document.createElement("button");return d.className="tbw-pivot-chip-remove",d.innerHTML="×",d.title="Remove value field",d.addEventListener("click",c=>{c.stopPropagation(),n.onRemoveValueField(a.field)},{signal:o}),r.appendChild(l),r.appendChild(s),i.appendChild(r),i.appendChild(d),i}function q(a){const{config:e,callbacks:n,signal:o}=a,i=document.createElement("div");i.className="tbw-pivot-available-fields";const t=n.getAvailableFields(),r=new Set([...e.rowGroupFields??[],...e.columnGroupFields??[],...e.valueFields?.map(s=>s.field)??[]]),l=t.filter(s=>!r.has(s.field));if(l.length===0){const s=document.createElement("div");s.className="tbw-pivot-placeholder",s.textContent="All fields are in use",i.appendChild(s)}else for(const s of l){const d=document.createElement("div");d.className="tbw-pivot-field-chip available",d.textContent=s.header,d.draggable=!0,d.title=`Drag to add "${s.field}" to a zone`,d.addEventListener("dragstart",c=>{c.dataTransfer?.setData("text/plain",s.field),d.classList.add("dragging")},{signal:o}),d.addEventListener("dragend",()=>{d.classList.remove("dragging")},{signal:o}),i.appendChild(d)}return i}function M(a,e){const{config:n,callbacks:o,signal:i}=e,t=document.createElement("div");return t.className="tbw-pivot-options",t.appendChild(x("Enable Pivot View",a,r=>{o.onTogglePivot(r)},i)),t.appendChild(x("Show Row Totals",n.showTotals??!0,r=>{o.onOptionChange("showTotals",r)},i)),t.appendChild(x("Show Grand Total",n.showGrandTotal??!0,r=>{o.onOptionChange("showGrandTotal",r)},i)),t}function x(a,e,n,o){const i=document.createElement("label");i.className="tbw-pivot-checkbox";const t=document.createElement("input");t.type="checkbox",t.checked=e,t.addEventListener("change",()=>n(t.checked),{signal:o});const r=document.createElement("span");return r.textContent=a,i.appendChild(t),i.appendChild(r),i}function O(a,e,n){return e.className="pivot-group-row",e.setAttribute("data-pivot-depth",String(a.__pivotDepth??0)),e.setAttribute("role","row"),e.innerHTML="",n.columns.forEach((o,i)=>{const t=document.createElement("div");if(t.className="cell",t.setAttribute("data-col",String(i)),t.setAttribute("role","gridcell"),i===0){const r=Number(a.__pivotIndent)||0;t.style.paddingLeft=`${r}px`;const l=String(a.__pivotRowKey),s=document.createElement("button");s.type="button",s.className="pivot-toggle",s.setAttribute("aria-label",a.__pivotExpanded?"Collapse group":"Expand group"),n.setIcon(s,n.resolveIcon(a.__pivotExpanded?"collapse":"expand")),s.addEventListener("click",p=>{p.stopPropagation(),n.onToggle(l)}),t.appendChild(s);const d=document.createElement("span");d.className="pivot-label",d.textContent=String(a.__pivotLabel??""),t.appendChild(d);const c=document.createElement("span");c.className="pivot-count",c.textContent=` (${Number(a.__pivotRowCount)||0})`,t.appendChild(c)}else{const r=a[o.field];t.textContent=r!=null?String(r):""}e.appendChild(t)}),!0}function Z(a,e,n){return e.className="pivot-leaf-row",e.setAttribute("data-pivot-depth",String(a.__pivotDepth??0)),e.innerHTML="",n.forEach((o,i)=>{const t=document.createElement("div");if(t.className="cell",t.setAttribute("data-col",String(i)),t.setAttribute("role","gridcell"),i===0){const r=Number(a.__pivotIndent)||0;t.style.paddingLeft=`${r+20}px`;const l=document.createElement("span");l.className="pivot-label",l.textContent=String(a.__pivotLabel??""),t.appendChild(l)}else{const r=a[o.field];t.textContent=r!=null?String(r):""}e.appendChild(t)}),!0}function j(a,e,n){return e.className="pivot-grand-total-row",e.setAttribute("role","presentation"),e.innerHTML="",n.forEach((o,i)=>{const t=document.createElement("div");if(t.className="cell",t.setAttribute("data-col",String(i)),i===0){const r=document.createElement("span");r.className="pivot-label",r.textContent="Grand Total",t.appendChild(r)}else{const r=a[o.field];t.textContent=r!=null?String(r):""}e.appendChild(t)}),!0}const $='.pivot-group-row{display:grid;grid-template-columns:var(--tbw-column-template);font-weight:600;background:var(--tbw-pivot-group-bg, var(--tbw-color-row-alt));min-height:var(--tbw-row-height);border-bottom:var(--tbw-row-divider)}.pivot-group-row:hover{background:var(--tbw-pivot-group-hover, var(--tbw-color-row-hover))}.pivot-leaf-row{display:grid;grid-template-columns:var(--tbw-column-template);background:var(--tbw-pivot-leaf-bg, var(--tbw-color-bg));min-height:var(--tbw-row-height);border-bottom:var(--tbw-row-divider)}.pivot-grand-total-row{display:grid;grid-template-columns:var(--tbw-column-template);font-weight:700;background:var(--tbw-pivot-grand-total-bg, var(--tbw-color-header-bg));min-height:var(--tbw-row-height);border-top:2px solid var(--tbw-color-border-strong)}.pivot-grand-total-row>.cell{display:flex;align-items:center;padding:var(--tbw-cell-padding);border-right:1px solid var(--tbw-color-border-cell);overflow:hidden;min-width:0}.pivot-grand-total-row>.cell:last-child{border-right:0}.pivot-grand-total-footer{position:sticky;bottom:0;z-index:var(--tbw-z-layer-pinned-rows, 20);background:var(--tbw-pivot-grand-total-bg, var(--tbw-color-header-bg));min-width:fit-content}.pivot-group-row>.cell,.pivot-leaf-row>.cell{display:flex;align-items:center;padding:var(--tbw-cell-padding);border-right:1px solid var(--tbw-color-border-cell);overflow:hidden;min-width:0}.pivot-group-row>.cell:last-child,.pivot-leaf-row>.cell:last-child{border-right:0}.pivot-toggle{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;margin-right:6px;border:none;background:transparent;cursor:pointer;font-size:10px;color:var(--tbw-pivot-toggle-color, var(--tbw-color-fg-muted));border-radius:var(--tbw-border-radius);transition:background .15s,color .15s}.pivot-toggle:hover{background:var(--tbw-pivot-toggle-hover-bg, var(--tbw-color-row-hover));color:var(--tbw-pivot-toggle-hover-color, var(--tbw-color-fg))}.pivot-toggle:focus{outline:var(--tbw-focus-outline);outline-offset:var(--tbw-focus-outline-offset)}.pivot-label{font-weight:inherit}.pivot-count{color:var(--tbw-pivot-count-color, var(--tbw-color-fg-muted));font-size:.9em;font-weight:400}.pivot-total-row{font-weight:700;border-top:2px solid var(--tbw-pivot-border, var(--tbw-color-border-strong))}[data-pivot-depth="1"]{--tbw-pivot-depth: 1}[data-pivot-depth="2"]{--tbw-pivot-depth: 2}[data-pivot-depth="3"]{--tbw-pivot-depth: 3}[data-pivot-depth="4"]{--tbw-pivot-depth: 4}.tbw-pivot-panel{display:flex;flex-direction:column;gap:12px;padding:12px;height:100%;overflow-y:auto;font-size:13px}.tbw-pivot-section{border:1px solid var(--tbw-pivot-border, var(--tbw-color-border));border-radius:var(--tbw-border-radius);background:var(--tbw-pivot-section-bg, var(--tbw-color-bg))}.tbw-pivot-section-header{padding:8px 12px;font-weight:600;background:var(--tbw-pivot-header-bg, var(--tbw-color-header-bg));border-bottom:1px solid var(--tbw-pivot-border, var(--tbw-color-border));border-radius:var(--tbw-border-radius) var(--tbw-border-radius) 0 0}.tbw-pivot-section-content{padding:8px}.tbw-pivot-toggle-wrapper{display:flex;align-items:center}.tbw-pivot-toggle-label{display:flex;align-items:center;gap:8px;cursor:pointer}.tbw-pivot-toggle-label input{width:16px;height:16px;cursor:pointer}.tbw-pivot-drop-zone{min-height:60px;padding:8px;border:2px dashed var(--tbw-pivot-drop-border, var(--tbw-color-border));border-radius:var(--tbw-border-radius);background:var(--tbw-pivot-drop-bg, var(--tbw-color-row-alt));display:flex;flex-wrap:wrap;gap:6px;align-content:flex-start;transition:all .15s ease}.tbw-pivot-drop-zone.drag-over{border-color:var(--tbw-color-accent);background:var(--tbw-pivot-drop-active, var(--tbw-focus-background))}.tbw-pivot-placeholder{color:var(--tbw-color-fg-muted);font-style:italic;padding:8px;text-align:center;width:100%}.tbw-pivot-field-chip{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;background:var(--tbw-pivot-chip-bg, var(--tbw-color-header-bg));border:1px solid var(--tbw-pivot-chip-border, var(--tbw-color-border));border-radius:var(--tbw-border-radius);cursor:grab;font-size:12px;transition:all .15s ease}.tbw-pivot-field-chip:hover{background:var(--tbw-pivot-chip-hover, var(--tbw-color-row-hover));border-color:var(--tbw-color-accent)}.tbw-pivot-field-chip.available{background:var(--tbw-color-bg)}.tbw-pivot-field-chip.dragging{opacity:.5;cursor:grabbing}.tbw-pivot-chip-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:120px}.tbw-pivot-chip-remove{display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;background:transparent;color:var(--tbw-color-fg-muted);font-size:14px;font-weight:700;cursor:pointer;border-radius:50%;transition:all .15s ease}.tbw-pivot-chip-remove:hover{background:var(--tbw-pivot-chip-remove-hover-bg, var(--tbw-color-accent));color:var(--tbw-pivot-chip-remove-hover-fg, var(--tbw-color-accent-fg))}.tbw-pivot-value-chip{padding:4px 8px}.tbw-pivot-value-label-wrapper{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.tbw-pivot-agg-select{padding:2px 4px;font-size:11px;border:1px solid var(--tbw-color-border);border-radius:var(--tbw-border-radius);background:var(--tbw-color-bg);cursor:pointer}.tbw-pivot-available-fields{display:flex;flex-wrap:wrap;gap:6px;min-height:40px}.tbw-pivot-options{display:flex;flex-direction:column;gap:8px}.tbw-pivot-checkbox{display:flex;align-items:center;gap:8px;cursor:pointer}.tbw-pivot-checkbox input{width:14px;height:14px;cursor:pointer}';class g extends f.BaseGridPlugin{name="pivot";version="1.0.0";static PANEL_ID="pivot";get defaultConfig(){return{active:!0,showTotals:!0,showGrandTotal:!0}}isActive=!1;hasInitialized=!1;pivotResult=null;fieldHeaderMap=new Map;expandedKeys=new Set;defaultExpanded=!0;originalColumns=[];panelContainer=null;grandTotalFooter=null;hasValidPivotConfig(){return(this.config.valueFields?.length??0)>0}detach(){this.isActive=!1,this.hasInitialized=!1,this.pivotResult=null,this.fieldHeaderMap.clear(),this.originalColumns=[],this.panelContainer=null,this.cleanupGrandTotalFooter()}getToolPanel(){return{id:g.PANEL_ID,title:"Pivot",icon:"⊞",tooltip:"Configure pivot table",order:90,render:e=>this.renderPanel(e)}}processRows(e){if(!this.hasInitialized&&this.config.active!==!1&&this.hasValidPivotConfig()&&(this.hasInitialized=!0,this.isActive=!0),!this.isActive)return[...e];const n=P(this.config);if(n.length>0)return this.warn(`Config errors: ${n.join(", ")}`),[...e];if(this.buildFieldHeaderMap(),this.defaultExpanded=this.config.defaultExpanded??!0,this.expandedKeys.size===0&&this.defaultExpanded&&this.pivotResult){const t=m(this.pivotResult.rows);for(const r of t)this.expandedKeys.add(r)}if(this.pivotResult=E(e,this.config),this.expandedKeys.size===0&&this.defaultExpanded){const t=m(this.pivotResult.rows);for(const r of t)this.expandedKeys.add(r)}const o=this.config.indentWidth??20;return S(this.pivotResult.rows,this.expandedKeys,this.defaultExpanded).map(t=>({__pivotRowKey:t.rowKey,__pivotLabel:t.rowLabel,__pivotDepth:t.depth,__pivotIsGroup:t.isGroup,__pivotHasChildren:!!t.children?.length,__pivotExpanded:this.expandedKeys.has(t.rowKey),__pivotRowCount:t.rowCount??0,__pivotIndent:t.depth*o,__pivotTotal:t.total,...t.values}))}processColumns(e){if(!this.isActive||!this.pivotResult)return[...e];const n=[],o=(this.config.rowGroupFields??[]).map(i=>this.fieldHeaderMap.get(i)??i).join(" / ");n.push({field:"__pivotLabel",header:o||"Group",width:200});for(const i of this.pivotResult.columnKeys)for(const t of this.config.valueFields??[]){const r=w([i],t.field),l=t.header||this.fieldHeaderMap.get(t.field)||t.field;n.push({field:r,header:`${i} - ${l} (${t.aggFunc})`,width:120,type:"number"})}return this.config.showTotals&&n.push({field:"__pivotTotal",header:"Total",width:100,type:"number"}),n}renderRow(e,n){const o=e;return o.__pivotRowKey&&o.__pivotHasChildren?O(o,n,{columns:this.gridColumns,onToggle:i=>this.toggle(i),resolveIcon:i=>this.resolveIcon(i),setIcon:(i,t)=>this.setIcon(i,t)}):o.__pivotRowKey!==void 0&&this.isActive?Z(o,n,this.gridColumns):(this.cleanupPivotStyling(n),!1)}cleanupPivotStyling(e){(e.classList.contains("pivot-group-row")||e.classList.contains("pivot-leaf-row")||e.classList.contains("pivot-grand-total-row"))&&(e.classList.remove("pivot-group-row","pivot-leaf-row","pivot-grand-total-row"),e.classList.add("data-grid-row"),e.removeAttribute("data-pivot-depth"),e.innerHTML="")}afterRender(){this.isActive&&this.config.showGrandTotal&&this.pivotResult?this.renderGrandTotalFooter():this.cleanupGrandTotalFooter()}renderGrandTotalFooter(){if(!this.pivotResult)return;const e=this.shadowRoot;if(!e)return;const n=e.querySelector(".tbw-scroll-area")??e.querySelector(".tbw-grid-content")??e.children[0];if(!n)return;this.grandTotalFooter||(this.grandTotalFooter=document.createElement("div"),this.grandTotalFooter.className="pivot-grand-total-footer",n.appendChild(this.grandTotalFooter));const o={__pivotRowKey:"__grandTotal",__pivotLabel:"Grand Total",__pivotIsGrandTotal:!0,__pivotTotal:this.pivotResult.grandTotal,...this.pivotResult.totals};j(o,this.grandTotalFooter,this.gridColumns)}cleanupGrandTotalFooter(){this.grandTotalFooter&&(this.grandTotalFooter.remove(),this.grandTotalFooter=null)}toggle(e){this.expandedKeys.has(e)?this.expandedKeys.delete(e):this.expandedKeys.add(e),this.requestRender()}expand(e){this.expandedKeys.add(e),this.requestRender()}collapse(e){this.expandedKeys.delete(e),this.requestRender()}expandAll(){if(this.pivotResult){const e=m(this.pivotResult.rows);for(const n of e)this.expandedKeys.add(n);this.requestRender()}}collapseAll(){this.expandedKeys.clear(),this.requestRender()}isExpanded(e){return this.expandedKeys.has(e)}enablePivot(){this.originalColumns.length===0&&this.captureOriginalColumns(),this.isActive=!0,this.requestRender()}disablePivot(){this.isActive=!1,this.pivotResult=null,this.requestRender()}isPivotActive(){return this.isActive}getPivotResult(){return this.pivotResult}setRowGroupFields(e){this.config.rowGroupFields=e,this.requestRender()}setColumnGroupFields(e){this.config.columnGroupFields=e,this.requestRender()}setValueFields(e){this.config.valueFields=e,this.requestRender()}refresh(){this.pivotResult=null,this.requestRender()}showPanel(){this.grid.openToolPanel(g.PANEL_ID)}hidePanel(){this.grid.closeToolPanel()}togglePanel(){this.grid.toggleToolPanel(g.PANEL_ID)}isPanelVisible(){return this.grid.activeToolPanel===g.PANEL_ID}get gridColumns(){return this.grid.columns??[]}buildFieldHeaderMap(){const e=this.getAvailableFields();this.fieldHeaderMap.clear();for(const n of e)this.fieldHeaderMap.set(n.field,n.header)}getAvailableFields(){return this.originalColumns.length>0?this.originalColumns:this.captureOriginalColumns()}captureOriginalColumns(){const e=this.grid;try{const n=e.getAllColumns?.()??e.columns??[];return this.originalColumns=n.filter(o=>!o.field.startsWith("__pivot")).map(o=>({field:o.field,header:o.header??o.field})),this.originalColumns}catch{return[]}}renderPanel(e){this.panelContainer=e,this.originalColumns.length===0&&this.captureOriginalColumns();const n={onTogglePivot:o=>{o?this.enablePivot():this.disablePivot(),this.refreshPanel()},onAddFieldToZone:(o,i)=>this.addFieldToZone(o,i),onRemoveFieldFromZone:(o,i)=>this.removeFieldFromZone(o,i),onAddValueField:(o,i)=>this.addValueField(o,i),onRemoveValueField:o=>this.removeValueField(o),onUpdateValueAggFunc:(o,i)=>this.updateValueAggFunc(o,i),onOptionChange:(o,i)=>{this.config[o]=i,this.isActive&&this.refresh()},getAvailableFields:()=>this.getAvailableFields()};return z(e,this.config,this.isActive,n)}refreshPanel(){this.panelContainer&&(this.panelContainer.innerHTML="",this.renderPanel(this.panelContainer))}addFieldToZone(e,n){if(n==="rowGroups"){const o=this.config.rowGroupFields??[];o.includes(e)||(this.config.rowGroupFields=[...o,e])}else{const o=this.config.columnGroupFields??[];o.includes(e)||(this.config.columnGroupFields=[...o,e])}this.removeFromOtherZones(e,n),this.isActive&&this.refresh(),this.refreshPanel()}removeFieldFromZone(e,n){n==="rowGroups"?this.config.rowGroupFields=(this.config.rowGroupFields??[]).filter(o=>o!==e):this.config.columnGroupFields=(this.config.columnGroupFields??[]).filter(o=>o!==e),this.isActive&&this.refresh(),this.refreshPanel()}removeFromOtherZones(e,n){n!=="rowGroups"&&(this.config.rowGroupFields=(this.config.rowGroupFields??[]).filter(o=>o!==e)),n!=="columnGroups"&&(this.config.columnGroupFields=(this.config.columnGroupFields??[]).filter(o=>o!==e)),n!=="values"&&(this.config.valueFields=(this.config.valueFields??[]).filter(o=>o.field!==e))}addValueField(e,n){const o=this.config.valueFields??[];o.some(i=>i.field===e)||(this.config.valueFields=[...o,{field:e,aggFunc:n}]),this.removeFromOtherZones(e,"values"),this.isActive&&this.refresh(),this.refreshPanel()}removeValueField(e){this.config.valueFields=(this.config.valueFields??[]).filter(n=>n.field!==e),this.isActive&&this.refresh(),this.refreshPanel()}updateValueAggFunc(e,n){const o=this.config.valueFields??[],i=o.findIndex(t=>t.field===e);i>=0&&(o[i]={...o[i],aggFunc:n},this.config.valueFields=[...o]),this.isActive&&this.refresh()}styles=$}h.PivotPlugin=g,Object.defineProperty(h,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(h,f){typeof exports=="object"&&typeof module<"u"?f(exports,require("../../core/plugin/base-plugin"),require("../../core/internal/aggregators")):typeof define=="function"&&define.amd?define(["exports","../../core/plugin/base-plugin","../../core/internal/aggregators"],f):(h=typeof globalThis<"u"?globalThis:h||self,f(h.TbwGridPlugin_pivot={},h.TbwGrid,h.TbwGrid))})(this,(function(h,f,G){"use strict";const P=G.getValueAggregator;function k(a){const e=[];return!a.rowGroupFields?.length&&!a.columnGroupFields?.length&&e.push("At least one row or column group field is required"),a.valueFields?.length||e.push("At least one value field is required"),e}function w(a,e){return[...a,e].join("|")}function L(a,e){const n=e.rowGroupFields??[],t=e.columnGroupFields??[],o=e.valueFields??[],i=E(a,t),r=y(a,n,t,i,o,0,""),s=N(r,i,o),l=Object.values(s).reduce((d,c)=>d+c,0);return{rows:r,columnKeys:i,totals:s,grandTotal:l}}function E(a,e){if(e.length===0)return["value"];const n=new Set;for(const t of a){const o=e.map(i=>String(t[i]??"")).join("|");n.add(o)}return[...n].sort()}function K(a,e){const n=new Map;for(const t of a){const o=String(t[e]??""),i=n.get(o);i?i.push(t):n.set(o,[t])}return n}function y(a,e,n,t,o,i,r){const s=[];if(e.length===0){const u=C(a,n,t,o),v=F(u);return s.push({rowKey:r||"all",rowLabel:r||"All",depth:i,values:u,total:v,isGroup:!1,rowCount:a.length}),s}const l=e[0],d=e.slice(1),c=d.length>0,p=K(a,l);for(const[u,v]of p){const T=r?`${r}|${u}`:u,R=C(v,n,t,o),B=F(R);let _;c&&(_=y(v,d,n,t,o,i+1,T)),s.push({rowKey:T,rowLabel:u||"(blank)",depth:i,values:R,total:B,isGroup:c,children:_,rowCount:v.length})}return s}function C(a,e,n,t){const o={};for(const i of n)for(const r of t){const l=(e.length>0?a.filter(u=>e.map(v=>String(u[v]??"")).join("|")===i):a).map(u=>Number(u[r.field])||0),d=P(r.aggFunc),c=l.length>0?d(l):null,p=w([i],r.field);o[p]=c}return o}function F(a){let e=0;for(const n of Object.values(a))e+=n??0;return e}function N(a,e,n){const t={};function o(i){for(const r of i)if(!r.isGroup||!r.children?.length)for(const s of e)for(const l of n){const d=w([s],l.field);t[d]=(t[d]??0)+(r.values[d]??0)}else r.children&&o(r.children)}return o(a),t}function S(a,e,n=!0){const t=[];function o(i){t.push(i);const r=e?e.has(i.rowKey):n;if(i.children&&r)for(const s of i.children)o(s)}for(const i of a)o(i);return t}function m(a){const e=[];function n(t){if(t.isGroup&&e.push(t.rowKey),t.children)for(const o of t.children)n(o)}for(const t of a)n(t);return e}const V=["sum","avg","count","min","max","first","last"];function z(a,e,n,t){const o=new AbortController,i={config:e,callbacks:t,signal:o.signal},r=document.createElement("div");return r.className="tbw-pivot-panel",r.appendChild(b("Options",()=>M(n,i))),r.appendChild(b("Row Groups",()=>A("rowGroups",i))),r.appendChild(b("Column Groups",()=>A("columnGroups",i))),r.appendChild(b("Values",()=>I(i))),r.appendChild(b("Available Fields",()=>H(i))),a.appendChild(r),()=>{o.abort(),r.remove()}}function b(a,e){const n=document.createElement("div");n.className="tbw-pivot-section";const t=document.createElement("div");t.className="tbw-pivot-section-header",t.textContent=a;const o=document.createElement("div");return o.className="tbw-pivot-section-content",o.appendChild(e()),n.appendChild(t),n.appendChild(o),n}function A(a,e){const{config:n,callbacks:t,signal:o}=e,i=document.createElement("div");i.className="tbw-pivot-drop-zone",i.setAttribute("data-zone",a);const r=a==="rowGroups"?n.rowGroupFields??[]:n.columnGroupFields??[];if(r.length===0){const s=document.createElement("div");s.className="tbw-pivot-placeholder",s.textContent="Drag fields here or click to add",i.appendChild(s)}else for(const s of r)i.appendChild(D(s,a,e));return i.addEventListener("dragover",s=>{s.preventDefault(),i.classList.add("drag-over")},{signal:o}),i.addEventListener("dragleave",()=>{i.classList.remove("drag-over")},{signal:o}),i.addEventListener("drop",s=>{s.preventDefault(),i.classList.remove("drag-over");const l=s.dataTransfer?.getData("text/plain");l&&t.onAddFieldToZone(l,a)},{signal:o}),i}function D(a,e,n){const{callbacks:t,signal:o}=n,i=document.createElement("div");i.className="tbw-pivot-field-chip",i.draggable=!0;const r=t.getAvailableFields().find(d=>d.field===a),s=document.createElement("span");s.className="tbw-pivot-chip-label",s.textContent=r?.header??a;const l=document.createElement("button");return l.className="tbw-pivot-chip-remove",l.innerHTML="×",l.title="Remove field",l.addEventListener("click",d=>{d.stopPropagation(),t.onRemoveFieldFromZone(a,e)},{signal:o}),i.appendChild(s),i.appendChild(l),i.addEventListener("dragstart",d=>{d.dataTransfer?.setData("text/plain",a),d.dataTransfer?.setData("source-zone",e),i.classList.add("dragging")},{signal:o}),i.addEventListener("dragend",()=>{i.classList.remove("dragging")},{signal:o}),i}function I(a){const{config:e,callbacks:n,signal:t}=a,o=document.createElement("div");o.className="tbw-pivot-drop-zone tbw-pivot-values-zone",o.setAttribute("data-zone","values");const i=e.valueFields??[];if(i.length===0){const r=document.createElement("div");r.className="tbw-pivot-placeholder",r.textContent="Drag numeric fields here for aggregation",o.appendChild(r)}else for(const r of i)o.appendChild(q(r,a));return o.addEventListener("dragover",r=>{r.preventDefault(),o.classList.add("drag-over")},{signal:t}),o.addEventListener("dragleave",()=>{o.classList.remove("drag-over")},{signal:t}),o.addEventListener("drop",r=>{r.preventDefault(),o.classList.remove("drag-over");const s=r.dataTransfer?.getData("text/plain");s&&n.onAddValueField(s,"sum")},{signal:t}),o}function q(a,e){const{callbacks:n,signal:t}=e,o=document.createElement("div");o.className="tbw-pivot-field-chip tbw-pivot-value-chip";const i=n.getAvailableFields().find(c=>c.field===a.field),r=document.createElement("div");r.className="tbw-pivot-value-label-wrapper";const s=document.createElement("span");s.className="tbw-pivot-chip-label",s.textContent=i?.header??a.field;const l=document.createElement("select");l.className="tbw-pivot-agg-select",l.title="Aggregation function";for(const c of V){const p=document.createElement("option");p.value=c,p.textContent=c.toUpperCase(),p.selected=c===a.aggFunc,l.appendChild(p)}l.addEventListener("change",()=>{n.onUpdateValueAggFunc(a.field,l.value)},{signal:t});const d=document.createElement("button");return d.className="tbw-pivot-chip-remove",d.innerHTML="×",d.title="Remove value field",d.addEventListener("click",c=>{c.stopPropagation(),n.onRemoveValueField(a.field)},{signal:t}),r.appendChild(s),r.appendChild(l),o.appendChild(r),o.appendChild(d),o}function H(a){const{config:e,callbacks:n,signal:t}=a,o=document.createElement("div");o.className="tbw-pivot-available-fields";const i=n.getAvailableFields(),r=new Set([...e.rowGroupFields??[],...e.columnGroupFields??[],...e.valueFields?.map(l=>l.field)??[]]),s=i.filter(l=>!r.has(l.field));if(s.length===0){const l=document.createElement("div");l.className="tbw-pivot-placeholder",l.textContent="All fields are in use",o.appendChild(l)}else for(const l of s){const d=document.createElement("div");d.className="tbw-pivot-field-chip available",d.textContent=l.header,d.draggable=!0,d.title=`Drag to add "${l.field}" to a zone`,d.addEventListener("dragstart",c=>{c.dataTransfer?.setData("text/plain",l.field),d.classList.add("dragging")},{signal:t}),d.addEventListener("dragend",()=>{d.classList.remove("dragging")},{signal:t}),o.appendChild(d)}return o}function M(a,e){const{config:n,callbacks:t,signal:o}=e,i=document.createElement("div");return i.className="tbw-pivot-options",i.appendChild(x("Enable Pivot View",a,r=>{t.onTogglePivot(r)},o)),i.appendChild(x("Show Row Totals",n.showTotals??!0,r=>{t.onOptionChange("showTotals",r)},o)),i.appendChild(x("Show Grand Total",n.showGrandTotal??!0,r=>{t.onOptionChange("showGrandTotal",r)},o)),i}function x(a,e,n,t){const o=document.createElement("label");o.className="tbw-pivot-checkbox";const i=document.createElement("input");i.type="checkbox",i.checked=e,i.addEventListener("change",()=>n(i.checked),{signal:t});const r=document.createElement("span");return r.textContent=a,o.appendChild(i),o.appendChild(r),o}function O(a,e,n){return e.className="pivot-group-row",e.setAttribute("data-pivot-depth",String(a.__pivotDepth??0)),e.setAttribute("data-pivot-key",String(a.__pivotRowKey??"")),e.setAttribute("role","row"),e.innerHTML="",n.columns.forEach((t,o)=>{const i=document.createElement("div");if(i.className="cell",i.setAttribute("data-col",String(o)),i.setAttribute("role","gridcell"),o===0){const r=Number(a.__pivotIndent)||0;i.style.paddingLeft=`${r}px`;const s=String(a.__pivotRowKey),l=document.createElement("button");l.type="button",l.className="pivot-toggle",l.setAttribute("aria-label",a.__pivotExpanded?"Collapse group":"Expand group"),n.setIcon(l,n.resolveIcon(a.__pivotExpanded?"collapse":"expand")),l.addEventListener("click",p=>{p.stopPropagation(),n.onToggle(s)}),i.appendChild(l);const d=document.createElement("span");d.className="pivot-label",d.textContent=String(a.__pivotLabel??""),i.appendChild(d);const c=document.createElement("span");c.className="pivot-count",c.textContent=` (${Number(a.__pivotRowCount)||0})`,i.appendChild(c)}else{const r=a[t.field];i.textContent=r!=null?String(r):""}e.appendChild(i)}),!0}function Z(a,e,n){return e.className="pivot-leaf-row",e.setAttribute("data-pivot-depth",String(a.__pivotDepth??0)),e.setAttribute("data-pivot-key",String(a.__pivotRowKey??"")),e.innerHTML="",n.forEach((t,o)=>{const i=document.createElement("div");if(i.className="cell",i.setAttribute("data-col",String(o)),i.setAttribute("role","gridcell"),o===0){const r=Number(a.__pivotIndent)||0;i.style.paddingLeft=`${r+20}px`;const s=document.createElement("span");s.className="pivot-label",s.textContent=String(a.__pivotLabel??""),i.appendChild(s)}else{const r=a[t.field];i.textContent=r!=null?String(r):""}e.appendChild(i)}),!0}function j(a,e,n){return e.className="pivot-grand-total-row",e.setAttribute("role","presentation"),e.innerHTML="",n.forEach((t,o)=>{const i=document.createElement("div");if(i.className="cell",i.setAttribute("data-col",String(o)),o===0){const r=document.createElement("span");r.className="pivot-label",r.textContent="Grand Total",i.appendChild(r)}else{const r=a[t.field];i.textContent=r!=null?String(r):""}e.appendChild(i)}),!0}const $='.pivot-group-row{display:grid;grid-template-columns:var(--tbw-column-template);font-weight:600;background:var(--tbw-pivot-group-bg, var(--tbw-color-row-alt));min-height:var(--tbw-row-height);border-bottom:var(--tbw-row-divider)}.pivot-group-row:hover{background:var(--tbw-pivot-group-hover, var(--tbw-color-row-hover))}.pivot-leaf-row{display:grid;grid-template-columns:var(--tbw-column-template);background:var(--tbw-pivot-leaf-bg, var(--tbw-color-bg));min-height:var(--tbw-row-height);border-bottom:var(--tbw-row-divider)}.pivot-grand-total-row{display:grid;grid-template-columns:var(--tbw-column-template);font-weight:700;background:var(--tbw-pivot-grand-total-bg, var(--tbw-color-header-bg));min-height:var(--tbw-row-height);border-top:2px solid var(--tbw-color-border-strong)}.pivot-grand-total-row>.cell{display:flex;align-items:center;padding:var(--tbw-cell-padding);border-right:1px solid var(--tbw-color-border-cell);overflow:hidden;min-width:0}.pivot-grand-total-row>.cell:last-child{border-right:0}.pivot-grand-total-footer{position:sticky;bottom:0;z-index:var(--tbw-z-layer-pinned-rows, 20);background:var(--tbw-pivot-grand-total-bg, var(--tbw-color-header-bg));min-width:fit-content}.pivot-group-row>.cell,.pivot-leaf-row>.cell{display:flex;align-items:center;padding:var(--tbw-cell-padding);border-right:1px solid var(--tbw-color-border-cell);overflow:hidden;min-width:0}.pivot-group-row>.cell:last-child,.pivot-leaf-row>.cell:last-child{border-right:0}.pivot-toggle{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;margin-right:6px;border:none;background:transparent;cursor:pointer;color:var(--tbw-pivot-toggle-color, var(--tbw-color-fg-muted));border-radius:var(--tbw-border-radius);transition:background .15s,color .15s}.pivot-toggle:hover{background:var(--tbw-pivot-toggle-hover-bg, var(--tbw-color-row-hover));color:var(--tbw-pivot-toggle-hover-color, var(--tbw-color-fg))}.pivot-toggle:focus{outline:var(--tbw-focus-outline);outline-offset:var(--tbw-focus-outline-offset)}.pivot-label{font-weight:inherit}.pivot-count{color:var(--tbw-pivot-count-color, var(--tbw-color-fg-muted));font-size:.9em;font-weight:400}.pivot-total-row{font-weight:700;border-top:2px solid var(--tbw-pivot-border, var(--tbw-color-border-strong))}[data-pivot-depth="1"]{--tbw-pivot-depth: 1}[data-pivot-depth="2"]{--tbw-pivot-depth: 2}[data-pivot-depth="3"]{--tbw-pivot-depth: 3}[data-pivot-depth="4"]{--tbw-pivot-depth: 4}.tbw-pivot-panel{display:flex;flex-direction:column;gap:12px;padding:12px;height:100%;overflow-y:auto;font-size:13px}.tbw-pivot-section{border:1px solid var(--tbw-pivot-border, var(--tbw-color-border));border-radius:var(--tbw-border-radius);background:var(--tbw-pivot-section-bg, var(--tbw-color-bg))}.tbw-pivot-section-header{padding:8px 12px;font-weight:600;background:var(--tbw-pivot-header-bg, var(--tbw-color-header-bg));border-bottom:1px solid var(--tbw-pivot-border, var(--tbw-color-border));border-radius:var(--tbw-border-radius) var(--tbw-border-radius) 0 0}.tbw-pivot-section-content{padding:8px}.tbw-pivot-toggle-wrapper{display:flex;align-items:center}.tbw-pivot-toggle-label{display:flex;align-items:center;gap:8px;cursor:pointer}.tbw-pivot-toggle-label input{width:16px;height:16px;cursor:pointer}.tbw-pivot-drop-zone{min-height:60px;padding:8px;border:2px dashed var(--tbw-pivot-drop-border, var(--tbw-color-border));border-radius:var(--tbw-border-radius);background:var(--tbw-pivot-drop-bg, var(--tbw-color-row-alt));display:flex;flex-wrap:wrap;gap:6px;align-content:flex-start;transition:all .15s ease}.tbw-pivot-drop-zone.drag-over{border-color:var(--tbw-color-accent);background:var(--tbw-pivot-drop-active, var(--tbw-focus-background))}.tbw-pivot-placeholder{color:var(--tbw-color-fg-muted);font-style:italic;padding:8px;text-align:center;width:100%}.tbw-pivot-field-chip{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;background:var(--tbw-pivot-chip-bg, var(--tbw-color-header-bg));border:1px solid var(--tbw-pivot-chip-border, var(--tbw-color-border));border-radius:var(--tbw-border-radius);cursor:grab;font-size:12px;transition:all .15s ease}.tbw-pivot-field-chip:hover{background:var(--tbw-pivot-chip-hover, var(--tbw-color-row-hover));border-color:var(--tbw-color-accent)}.tbw-pivot-field-chip.available{background:var(--tbw-color-bg)}.tbw-pivot-field-chip.dragging{opacity:.5;cursor:grabbing}.tbw-pivot-chip-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:120px}.tbw-pivot-chip-remove{display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;background:transparent;color:var(--tbw-color-fg-muted);font-size:14px;font-weight:700;cursor:pointer;border-radius:50%;transition:all .15s ease}.tbw-pivot-chip-remove:hover{background:var(--tbw-pivot-chip-remove-hover-bg, var(--tbw-color-accent));color:var(--tbw-pivot-chip-remove-hover-fg, var(--tbw-color-accent-fg))}.tbw-pivot-value-chip{padding:4px 8px}.tbw-pivot-value-label-wrapper{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.tbw-pivot-agg-select{padding:2px 4px;font-size:11px;border:1px solid var(--tbw-color-border);border-radius:var(--tbw-border-radius);background:var(--tbw-color-bg);cursor:pointer}.tbw-pivot-available-fields{display:flex;flex-wrap:wrap;gap:6px;min-height:40px}.tbw-pivot-options{display:flex;flex-direction:column;gap:8px}.tbw-pivot-checkbox{display:flex;align-items:center;gap:8px;cursor:pointer}.tbw-pivot-checkbox input{width:14px;height:14px;cursor:pointer}.pivot-group-row.tbw-pivot-slide-in,.pivot-leaf-row.tbw-pivot-slide-in{animation:tbw-pivot-slide-in var(--tbw-animation-duration, .2s) var(--tbw-animation-easing, ease-out) forwards}@keyframes tbw-pivot-slide-in{0%{opacity:0;transform:translate(-8px)}to{opacity:1;transform:translate(0)}}.pivot-group-row.tbw-pivot-fade-in,.pivot-leaf-row.tbw-pivot-fade-in{animation:tbw-pivot-fade-in var(--tbw-animation-duration, .2s) var(--tbw-animation-easing, ease-out) forwards}@keyframes tbw-pivot-fade-in{0%{opacity:0}to{opacity:1}}';class g extends f.BaseGridPlugin{name="pivot";version="1.0.0";static PANEL_ID="pivot";get defaultConfig(){return{active:!0,showTotals:!0,showGrandTotal:!0,showToolPanel:!0,animation:"slide"}}isActive=!1;hasInitialized=!1;pivotResult=null;fieldHeaderMap=new Map;expandedKeys=new Set;defaultExpanded=!0;originalColumns=[];panelContainer=null;grandTotalFooter=null;previousVisibleKeys=new Set;keysToAnimate=new Set;hasValidPivotConfig(){return(this.config.valueFields?.length??0)>0}get animationStyle(){const n=this.grid.effectiveConfig?.animation?.mode??"reduced-motion";if(n===!1||n==="off")return!1;if(n!==!0&&n!=="on"){const t=this.shadowRoot?.host;if(t&&getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim()==="0")return!1}return this.config.animation??"slide"}detach(){this.isActive=!1,this.hasInitialized=!1,this.pivotResult=null,this.fieldHeaderMap.clear(),this.originalColumns=[],this.panelContainer=null,this.cleanupGrandTotalFooter(),this.previousVisibleKeys.clear(),this.keysToAnimate.clear()}getToolPanel(){if((this.config?.showToolPanel??this.userConfig?.showToolPanel??!0)!==!1)return{id:g.PANEL_ID,title:"Pivot",icon:"⊞",tooltip:"Configure pivot table",order:90,render:n=>this.renderPanel(n)}}processRows(e){if(!this.hasInitialized&&this.config.active!==!1&&this.hasValidPivotConfig()&&(this.hasInitialized=!0,this.isActive=!0),!this.isActive)return[...e];const n=k(this.config);if(n.length>0)return this.warn(`Config errors: ${n.join(", ")}`),[...e];if(this.buildFieldHeaderMap(),this.defaultExpanded=this.config.defaultExpanded??!0,this.expandedKeys.size===0&&this.defaultExpanded&&this.pivotResult){const r=m(this.pivotResult.rows);for(const s of r)this.expandedKeys.add(s)}if(this.pivotResult=L(e,this.config),this.expandedKeys.size===0&&this.defaultExpanded){const r=m(this.pivotResult.rows);for(const s of r)this.expandedKeys.add(s)}const t=this.config.indentWidth??20,o=S(this.pivotResult.rows,this.expandedKeys,this.defaultExpanded).map(r=>({__pivotRowKey:r.rowKey,__pivotLabel:r.rowLabel,__pivotDepth:r.depth,__pivotIsGroup:r.isGroup,__pivotHasChildren:!!r.children?.length,__pivotExpanded:this.expandedKeys.has(r.rowKey),__pivotRowCount:r.rowCount??0,__pivotIndent:r.depth*t,__pivotTotal:r.total,...r.values}));this.keysToAnimate.clear();const i=new Set;for(const r of o){const s=r.__pivotRowKey;i.add(s),!this.previousVisibleKeys.has(s)&&r.__pivotDepth>0&&this.keysToAnimate.add(s)}return this.previousVisibleKeys=i,o}processColumns(e){if(!this.isActive||!this.pivotResult)return[...e];const n=[],t=(this.config.rowGroupFields??[]).map(o=>this.fieldHeaderMap.get(o)??o).join(" / ");n.push({field:"__pivotLabel",header:t||"Group",width:200});for(const o of this.pivotResult.columnKeys)for(const i of this.config.valueFields??[]){const r=w([o],i.field),s=i.header||this.fieldHeaderMap.get(i.field)||i.field;n.push({field:r,header:`${o} - ${s} (${i.aggFunc})`,width:120,type:"number"})}return this.config.showTotals&&n.push({field:"__pivotTotal",header:"Total",width:100,type:"number"}),n}renderRow(e,n){const t=e;return t.__pivotRowKey&&t.__pivotHasChildren?O(t,n,{columns:this.gridColumns,onToggle:o=>this.toggle(o),resolveIcon:o=>this.resolveIcon(o),setIcon:(o,i)=>this.setIcon(o,i)}):t.__pivotRowKey!==void 0&&this.isActive?Z(t,n,this.gridColumns):(this.cleanupPivotStyling(n),!1)}cleanupPivotStyling(e){(e.classList.contains("pivot-group-row")||e.classList.contains("pivot-leaf-row")||e.classList.contains("pivot-grand-total-row"))&&(e.classList.remove("pivot-group-row","pivot-leaf-row","pivot-grand-total-row"),e.classList.add("data-grid-row"),e.removeAttribute("data-pivot-depth"),e.innerHTML="")}afterRender(){this.isActive&&this.config.showGrandTotal&&this.pivotResult?this.renderGrandTotalFooter():this.cleanupGrandTotalFooter();const e=this.animationStyle;if(e===!1||this.keysToAnimate.size===0)return;const n=this.shadowRoot?.querySelector(".rows");if(!n)return;const t=e==="fade"?"tbw-pivot-fade-in":"tbw-pivot-slide-in";for(const o of n.querySelectorAll(".pivot-group-row, .pivot-leaf-row")){const i=o.dataset.pivotKey;i&&this.keysToAnimate.has(i)&&(o.classList.add(t),o.addEventListener("animationend",()=>o.classList.remove(t),{once:!0}))}this.keysToAnimate.clear()}renderGrandTotalFooter(){if(!this.pivotResult)return;const e=this.shadowRoot;if(!e)return;const n=e.querySelector(".tbw-scroll-area")??e.querySelector(".tbw-grid-content")??e.children[0];if(!n)return;this.grandTotalFooter||(this.grandTotalFooter=document.createElement("div"),this.grandTotalFooter.className="pivot-grand-total-footer",n.appendChild(this.grandTotalFooter));const t={__pivotRowKey:"__grandTotal",__pivotLabel:"Grand Total",__pivotIsGrandTotal:!0,__pivotTotal:this.pivotResult.grandTotal,...this.pivotResult.totals};j(t,this.grandTotalFooter,this.gridColumns)}cleanupGrandTotalFooter(){this.grandTotalFooter&&(this.grandTotalFooter.remove(),this.grandTotalFooter=null)}toggle(e){this.expandedKeys.has(e)?this.expandedKeys.delete(e):this.expandedKeys.add(e),this.requestRender()}expand(e){this.expandedKeys.add(e),this.requestRender()}collapse(e){this.expandedKeys.delete(e),this.requestRender()}expandAll(){if(this.pivotResult){const e=m(this.pivotResult.rows);for(const n of e)this.expandedKeys.add(n);this.requestRender()}}collapseAll(){this.expandedKeys.clear(),this.requestRender()}isExpanded(e){return this.expandedKeys.has(e)}enablePivot(){this.originalColumns.length===0&&this.captureOriginalColumns(),this.isActive=!0,this.requestRender()}disablePivot(){this.isActive=!1,this.pivotResult=null,this.requestRender()}isPivotActive(){return this.isActive}getPivotResult(){return this.pivotResult}setRowGroupFields(e){this.config.rowGroupFields=e,this.requestRender()}setColumnGroupFields(e){this.config.columnGroupFields=e,this.requestRender()}setValueFields(e){this.config.valueFields=e,this.requestRender()}refresh(){this.pivotResult=null,this.requestRender()}showPanel(){this.grid.openToolPanel(g.PANEL_ID)}hidePanel(){this.grid.closeToolPanel()}togglePanel(){this.grid.toggleToolPanel(g.PANEL_ID)}isPanelVisible(){return this.grid.activeToolPanel===g.PANEL_ID}get gridColumns(){return this.grid.columns??[]}buildFieldHeaderMap(){const e=this.getAvailableFields();this.fieldHeaderMap.clear();for(const n of e)this.fieldHeaderMap.set(n.field,n.header)}getAvailableFields(){return this.originalColumns.length>0?this.originalColumns:this.captureOriginalColumns()}captureOriginalColumns(){const e=this.grid;try{const n=e.getAllColumns?.()??e.columns??[];return this.originalColumns=n.filter(t=>!t.field.startsWith("__pivot")).map(t=>({field:t.field,header:t.header??t.field})),this.originalColumns}catch{return[]}}renderPanel(e){this.panelContainer=e,this.originalColumns.length===0&&this.captureOriginalColumns();const n={onTogglePivot:t=>{t?this.enablePivot():this.disablePivot(),this.refreshPanel()},onAddFieldToZone:(t,o)=>this.addFieldToZone(t,o),onRemoveFieldFromZone:(t,o)=>this.removeFieldFromZone(t,o),onAddValueField:(t,o)=>this.addValueField(t,o),onRemoveValueField:t=>this.removeValueField(t),onUpdateValueAggFunc:(t,o)=>this.updateValueAggFunc(t,o),onOptionChange:(t,o)=>{this.config[t]=o,this.isActive&&this.refresh()},getAvailableFields:()=>this.getAvailableFields()};return z(e,this.config,this.isActive,n)}refreshPanel(){this.panelContainer&&(this.panelContainer.innerHTML="",this.renderPanel(this.panelContainer))}addFieldToZone(e,n){if(n==="rowGroups"){const t=this.config.rowGroupFields??[];t.includes(e)||(this.config.rowGroupFields=[...t,e])}else{const t=this.config.columnGroupFields??[];t.includes(e)||(this.config.columnGroupFields=[...t,e])}this.removeFromOtherZones(e,n),this.isActive&&this.refresh(),this.refreshPanel()}removeFieldFromZone(e,n){n==="rowGroups"?this.config.rowGroupFields=(this.config.rowGroupFields??[]).filter(t=>t!==e):this.config.columnGroupFields=(this.config.columnGroupFields??[]).filter(t=>t!==e),this.isActive&&this.refresh(),this.refreshPanel()}removeFromOtherZones(e,n){n!=="rowGroups"&&(this.config.rowGroupFields=(this.config.rowGroupFields??[]).filter(t=>t!==e)),n!=="columnGroups"&&(this.config.columnGroupFields=(this.config.columnGroupFields??[]).filter(t=>t!==e)),n!=="values"&&(this.config.valueFields=(this.config.valueFields??[]).filter(t=>t.field!==e))}addValueField(e,n){const t=this.config.valueFields??[];t.some(o=>o.field===e)||(this.config.valueFields=[...t,{field:e,aggFunc:n}]),this.removeFromOtherZones(e,"values"),this.isActive&&this.refresh(),this.refreshPanel()}removeValueField(e){this.config.valueFields=(this.config.valueFields??[]).filter(n=>n.field!==e),this.isActive&&this.refresh(),this.refreshPanel()}updateValueAggFunc(e,n){const t=this.config.valueFields??[],o=t.findIndex(i=>i.field===e);o>=0&&(t[o]={...t[o],aggFunc:n},this.config.valueFields=[...t]),this.isActive&&this.refresh()}styles=$}h.PivotPlugin=g,Object.defineProperty(h,Symbol.toStringTag,{value:"Module"})}));
2
2
  //# sourceMappingURL=pivot.umd.js.map