photon-grid-core 0.0.1
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/LICENSE +1 -0
- package/README.md +0 -0
- package/cell-selection/active-grid-registry.d.ts +37 -0
- package/cell-selection/active-grid-registry.d.ts.map +1 -0
- package/cell-selection/active-grid-registry.js +25 -0
- package/cell-selection/active-grid-registry.js.map +1 -0
- package/cell-selection/cell-selection-engine.d.ts +336 -0
- package/cell-selection/cell-selection-engine.d.ts.map +1 -0
- package/cell-selection/cell-selection-engine.js +1534 -0
- package/cell-selection/cell-selection-engine.js.map +1 -0
- package/cell-selection/selection-range.d.ts +16 -0
- package/cell-selection/selection-range.d.ts.map +1 -0
- package/cell-selection/selection-range.js +48 -0
- package/cell-selection/selection-range.js.map +1 -0
- package/cell-selection/selection-renderer.d.ts +24 -0
- package/cell-selection/selection-renderer.d.ts.map +1 -0
- package/cell-selection/selection-renderer.js +107 -0
- package/cell-selection/selection-renderer.js.map +1 -0
- package/chart/chart-analyzer/aggregation-analyzer.d.ts +18 -0
- package/chart/chart-analyzer/aggregation-analyzer.d.ts.map +1 -0
- package/chart/chart-analyzer/aggregation-analyzer.js +63 -0
- package/chart/chart-analyzer/aggregation-analyzer.js.map +1 -0
- package/chart/chart-analyzer/bar-analyzer.d.ts +19 -0
- package/chart/chart-analyzer/bar-analyzer.d.ts.map +1 -0
- package/chart/chart-analyzer/bar-analyzer.js +56 -0
- package/chart/chart-analyzer/bar-analyzer.js.map +1 -0
- package/chart/chart-analyzer/bubble-analyzer.d.ts +16 -0
- package/chart/chart-analyzer/bubble-analyzer.d.ts.map +1 -0
- package/chart/chart-analyzer/bubble-analyzer.js +61 -0
- package/chart/chart-analyzer/bubble-analyzer.js.map +1 -0
- package/chart/chart-analyzer/cardinality-analyzer.d.ts +13 -0
- package/chart/chart-analyzer/cardinality-analyzer.d.ts.map +1 -0
- package/chart/chart-analyzer/cardinality-analyzer.js +28 -0
- package/chart/chart-analyzer/cardinality-analyzer.js.map +1 -0
- package/chart/chart-analyzer/dimension-analyzer.d.ts +12 -0
- package/chart/chart-analyzer/dimension-analyzer.d.ts.map +1 -0
- package/chart/chart-analyzer/dimension-analyzer.js +33 -0
- package/chart/chart-analyzer/dimension-analyzer.js.map +1 -0
- package/chart/chart-analyzer/histogram-analyzer.d.ts +11 -0
- package/chart/chart-analyzer/histogram-analyzer.d.ts.map +1 -0
- package/chart/chart-analyzer/histogram-analyzer.js +43 -0
- package/chart/chart-analyzer/histogram-analyzer.js.map +1 -0
- package/chart/chart-analyzer/index.d.ts +58 -0
- package/chart/chart-analyzer/index.d.ts.map +1 -0
- package/chart/chart-analyzer/index.js +130 -0
- package/chart/chart-analyzer/index.js.map +1 -0
- package/chart/chart-analyzer/line-analyzer.d.ts +23 -0
- package/chart/chart-analyzer/line-analyzer.d.ts.map +1 -0
- package/chart/chart-analyzer/line-analyzer.js +61 -0
- package/chart/chart-analyzer/line-analyzer.js.map +1 -0
- package/chart/chart-analyzer/measure-analyzer.d.ts +11 -0
- package/chart/chart-analyzer/measure-analyzer.d.ts.map +1 -0
- package/chart/chart-analyzer/measure-analyzer.js +44 -0
- package/chart/chart-analyzer/measure-analyzer.js.map +1 -0
- package/chart/chart-analyzer/pie-analyzer.d.ts +19 -0
- package/chart/chart-analyzer/pie-analyzer.d.ts.map +1 -0
- package/chart/chart-analyzer/pie-analyzer.js +64 -0
- package/chart/chart-analyzer/pie-analyzer.js.map +1 -0
- package/chart/chart-analyzer/recommendation-engine.d.ts +18 -0
- package/chart/chart-analyzer/recommendation-engine.d.ts.map +1 -0
- package/chart/chart-analyzer/recommendation-engine.js +82 -0
- package/chart/chart-analyzer/recommendation-engine.js.map +1 -0
- package/chart/chart-analyzer/scatter-analyzer.d.ts +16 -0
- package/chart/chart-analyzer/scatter-analyzer.d.ts.map +1 -0
- package/chart/chart-analyzer/scatter-analyzer.js +70 -0
- package/chart/chart-analyzer/scatter-analyzer.js.map +1 -0
- package/chart/chart-analyzer/types.d.ts +52 -0
- package/chart/chart-analyzer/types.d.ts.map +1 -0
- package/chart/chart-analyzer/types.js +10 -0
- package/chart/chart-analyzer/types.js.map +1 -0
- package/chart/chart-analyzer.d.ts +12 -0
- package/chart/chart-analyzer.d.ts.map +1 -0
- package/chart/chart-analyzer.js +77 -0
- package/chart/chart-analyzer.js.map +1 -0
- package/chart/chart-data-transformer.d.ts +26 -0
- package/chart/chart-data-transformer.d.ts.map +1 -0
- package/chart/chart-data-transformer.js +93 -0
- package/chart/chart-data-transformer.js.map +1 -0
- package/chart/chart-engine.d.ts +38 -0
- package/chart/chart-engine.d.ts.map +1 -0
- package/chart/chart-engine.js +96 -0
- package/chart/chart-engine.js.map +1 -0
- package/chart/chart-panel.d.ts +54 -0
- package/chart/chart-panel.d.ts.map +1 -0
- package/chart/chart-panel.js +350 -0
- package/chart/chart-panel.js.map +1 -0
- package/chart/chart-renderer.d.ts +93 -0
- package/chart/chart-renderer.d.ts.map +1 -0
- package/chart/chart-renderer.js +1330 -0
- package/chart/chart-renderer.js.map +1 -0
- package/chart/sparkline/sparkline-renderer.d.ts +269 -0
- package/chart/sparkline/sparkline-renderer.d.ts.map +1 -0
- package/chart/sparkline/sparkline-renderer.js +875 -0
- package/chart/sparkline/sparkline-renderer.js.map +1 -0
- package/chart/sparkline/sparkline.types.d.ts +214 -0
- package/chart/sparkline/sparkline.types.d.ts.map +1 -0
- package/chart/sparkline/sparkline.types.js +8 -0
- package/chart/sparkline/sparkline.types.js.map +1 -0
- package/column-groups/column-group-drag-handler.d.ts +169 -0
- package/column-groups/column-group-drag-handler.d.ts.map +1 -0
- package/column-groups/column-group-drag-handler.js +517 -0
- package/column-groups/column-group-drag-handler.js.map +1 -0
- package/column-groups/column-group-header-builder.d.ts +106 -0
- package/column-groups/column-group-header-builder.d.ts.map +1 -0
- package/column-groups/column-group-header-builder.js +311 -0
- package/column-groups/column-group-header-builder.js.map +1 -0
- package/column-groups/column-group-model.d.ts +248 -0
- package/column-groups/column-group-model.d.ts.map +1 -0
- package/column-groups/column-group-model.js +668 -0
- package/column-groups/column-group-model.js.map +1 -0
- package/column-groups/column-group-state-manager.d.ts +110 -0
- package/column-groups/column-group-state-manager.d.ts.map +1 -0
- package/column-groups/column-group-state-manager.js +153 -0
- package/column-groups/column-group-state-manager.js.map +1 -0
- package/column-groups/column-group.types.d.ts +250 -0
- package/column-groups/column-group.types.d.ts.map +1 -0
- package/column-groups/column-group.types.js +20 -0
- package/column-groups/column-group.types.js.map +1 -0
- package/column-groups/display-group-builder.d.ts +91 -0
- package/column-groups/display-group-builder.d.ts.map +1 -0
- package/column-groups/display-group-builder.js +225 -0
- package/column-groups/display-group-builder.js.map +1 -0
- package/column-groups/display-group-drag-handler.d.ts +205 -0
- package/column-groups/display-group-drag-handler.d.ts.map +1 -0
- package/column-groups/display-group-drag-handler.js +536 -0
- package/column-groups/display-group-drag-handler.js.map +1 -0
- package/column-groups/display-group-engine.d.ts +310 -0
- package/column-groups/display-group-engine.d.ts.map +1 -0
- package/column-groups/display-group-engine.js +549 -0
- package/column-groups/display-group-engine.js.map +1 -0
- package/column-groups/display-group-header-builder.d.ts +94 -0
- package/column-groups/display-group-header-builder.d.ts.map +1 -0
- package/column-groups/display-group-header-builder.js +224 -0
- package/column-groups/display-group-header-builder.js.map +1 -0
- package/column-groups/display-group.types.d.ts +140 -0
- package/column-groups/display-group.types.d.ts.map +1 -0
- package/column-groups/display-group.types.js +2 -0
- package/column-groups/display-group.types.js.map +1 -0
- package/column-groups/index.d.ts +25 -0
- package/column-groups/index.d.ts.map +1 -0
- package/column-groups/index.js +26 -0
- package/column-groups/index.js.map +1 -0
- package/column-groups/logical-group-registry.d.ts +77 -0
- package/column-groups/logical-group-registry.d.ts.map +1 -0
- package/column-groups/logical-group-registry.js +118 -0
- package/column-groups/logical-group-registry.js.map +1 -0
- package/core/column-model.d.ts +30 -0
- package/core/column-model.d.ts.map +1 -0
- package/core/column-model.js +203 -0
- package/core/column-model.js.map +1 -0
- package/core/grid-api.d.ts +187 -0
- package/core/grid-api.d.ts.map +1 -0
- package/core/grid-api.js +569 -0
- package/core/grid-api.js.map +1 -0
- package/core/grid-context.d.ts +61 -0
- package/core/grid-context.d.ts.map +1 -0
- package/core/grid-context.js +2 -0
- package/core/grid-context.js.map +1 -0
- package/core/grid-core.d.ts +49 -0
- package/core/grid-core.d.ts.map +1 -0
- package/core/grid-core.js +675 -0
- package/core/grid-core.js.map +1 -0
- package/core/grid-store.d.ts +62 -0
- package/core/grid-store.d.ts.map +1 -0
- package/core/grid-store.js +104 -0
- package/core/grid-store.js.map +1 -0
- package/core/row-model.d.ts +32 -0
- package/core/row-model.d.ts.map +1 -0
- package/core/row-model.js +150 -0
- package/core/row-model.js.map +1 -0
- package/drag-drop/drag-autoscroll.d.ts +14 -0
- package/drag-drop/drag-autoscroll.d.ts.map +1 -0
- package/drag-drop/drag-autoscroll.js +66 -0
- package/drag-drop/drag-autoscroll.js.map +1 -0
- package/drag-drop/drag-drop-engine.d.ts +55 -0
- package/drag-drop/drag-drop-engine.d.ts.map +1 -0
- package/drag-drop/drag-drop-engine.js +179 -0
- package/drag-drop/drag-drop-engine.js.map +1 -0
- package/drag-drop/drag-preview.d.ts +32 -0
- package/drag-drop/drag-preview.d.ts.map +1 -0
- package/drag-drop/drag-preview.js +74 -0
- package/drag-drop/drag-preview.js.map +1 -0
- package/engines/aggregation/aggregation-engine.d.ts +66 -0
- package/engines/aggregation/aggregation-engine.d.ts.map +1 -0
- package/engines/aggregation/aggregation-engine.js +149 -0
- package/engines/aggregation/aggregation-engine.js.map +1 -0
- package/engines/clipboard/clipboard-engine.d.ts +89 -0
- package/engines/clipboard/clipboard-engine.d.ts.map +1 -0
- package/engines/clipboard/clipboard-engine.js +323 -0
- package/engines/clipboard/clipboard-engine.js.map +1 -0
- package/engines/editing/cell-editor-engine.d.ts +62 -0
- package/engines/editing/cell-editor-engine.d.ts.map +1 -0
- package/engines/editing/cell-editor-engine.js +359 -0
- package/engines/editing/cell-editor-engine.js.map +1 -0
- package/engines/editing/custom-dropdown-editor.d.ts +99 -0
- package/engines/editing/custom-dropdown-editor.d.ts.map +1 -0
- package/engines/editing/custom-dropdown-editor.js +355 -0
- package/engines/editing/custom-dropdown-editor.js.map +1 -0
- package/engines/editing/value-parser.d.ts +12 -0
- package/engines/editing/value-parser.d.ts.map +1 -0
- package/engines/editing/value-parser.js +125 -0
- package/engines/editing/value-parser.js.map +1 -0
- package/engines/export/export-engine.d.ts +16 -0
- package/engines/export/export-engine.d.ts.map +1 -0
- package/engines/export/export-engine.js +99 -0
- package/engines/export/export-engine.js.map +1 -0
- package/engines/filter/filter-condition.d.ts +7 -0
- package/engines/filter/filter-condition.d.ts.map +1 -0
- package/engines/filter/filter-condition.js +126 -0
- package/engines/filter/filter-condition.js.map +1 -0
- package/engines/filter/filter-engine.d.ts +35 -0
- package/engines/filter/filter-engine.d.ts.map +1 -0
- package/engines/filter/filter-engine.js +150 -0
- package/engines/filter/filter-engine.js.map +1 -0
- package/engines/filter/filter-panel.d.ts +103 -0
- package/engines/filter/filter-panel.d.ts.map +1 -0
- package/engines/filter/filter-panel.js +645 -0
- package/engines/filter/filter-panel.js.map +1 -0
- package/engines/grouping/group-node.d.ts +21 -0
- package/engines/grouping/group-node.d.ts.map +1 -0
- package/engines/grouping/group-node.js +96 -0
- package/engines/grouping/group-node.js.map +1 -0
- package/engines/grouping/grouping-engine.d.ts +33 -0
- package/engines/grouping/grouping-engine.d.ts.map +1 -0
- package/engines/grouping/grouping-engine.js +118 -0
- package/engines/grouping/grouping-engine.js.map +1 -0
- package/engines/master-detail/master-detail-engine.d.ts +77 -0
- package/engines/master-detail/master-detail-engine.d.ts.map +1 -0
- package/engines/master-detail/master-detail-engine.js +199 -0
- package/engines/master-detail/master-detail-engine.js.map +1 -0
- package/engines/pagination/pagination-engine.d.ts +33 -0
- package/engines/pagination/pagination-engine.d.ts.map +1 -0
- package/engines/pagination/pagination-engine.js +110 -0
- package/engines/pagination/pagination-engine.js.map +1 -0
- package/engines/selection/row-selection-engine.d.ts +26 -0
- package/engines/selection/row-selection-engine.d.ts.map +1 -0
- package/engines/selection/row-selection-engine.js +145 -0
- package/engines/selection/row-selection-engine.js.map +1 -0
- package/engines/sort/sort-comparator.d.ts +43 -0
- package/engines/sort/sort-comparator.d.ts.map +1 -0
- package/engines/sort/sort-comparator.js +113 -0
- package/engines/sort/sort-comparator.js.map +1 -0
- package/engines/sort/sort-engine.d.ts +67 -0
- package/engines/sort/sort-engine.d.ts.map +1 -0
- package/engines/sort/sort-engine.js +178 -0
- package/engines/sort/sort-engine.js.map +1 -0
- package/engines/summary/summary-engine.d.ts +17 -0
- package/engines/summary/summary-engine.d.ts.map +1 -0
- package/engines/summary/summary-engine.js +72 -0
- package/engines/summary/summary-engine.js.map +1 -0
- package/engines/tree/tree-data-service.d.ts +117 -0
- package/engines/tree/tree-data-service.d.ts.map +1 -0
- package/engines/tree/tree-data-service.js +296 -0
- package/engines/tree/tree-data-service.js.map +1 -0
- package/engines/tree/tree-expansion-service.d.ts +35 -0
- package/engines/tree/tree-expansion-service.d.ts.map +1 -0
- package/engines/tree/tree-expansion-service.js +84 -0
- package/engines/tree/tree-expansion-service.js.map +1 -0
- package/engines/tree/tree-node.d.ts +40 -0
- package/engines/tree/tree-node.d.ts.map +1 -0
- package/engines/tree/tree-node.js +199 -0
- package/engines/tree/tree-node.js.map +1 -0
- package/engines/tree/tree-selection-service.d.ts +35 -0
- package/engines/tree/tree-selection-service.d.ts.map +1 -0
- package/engines/tree/tree-selection-service.js +72 -0
- package/engines/tree/tree-selection-service.js.map +1 -0
- package/engines/undo-redo/undo-redo-engine.d.ts +114 -0
- package/engines/undo-redo/undo-redo-engine.d.ts.map +1 -0
- package/engines/undo-redo/undo-redo-engine.js +165 -0
- package/engines/undo-redo/undo-redo-engine.js.map +1 -0
- package/event-bus/event-bus.d.ts +21 -0
- package/event-bus/event-bus.d.ts.map +1 -0
- package/event-bus/event-bus.js +106 -0
- package/event-bus/event-bus.js.map +1 -0
- package/icons/icon-registry.d.ts +19 -0
- package/icons/icon-registry.d.ts.map +1 -0
- package/icons/icon-registry.js +37 -0
- package/icons/icon-registry.js.map +1 -0
- package/icons/icon-renderer.d.ts +18 -0
- package/icons/icon-renderer.d.ts.map +1 -0
- package/icons/icon-renderer.js +75 -0
- package/icons/icon-renderer.js.map +1 -0
- package/icons/icon-sets/core-icons.d.ts +2 -0
- package/icons/icon-sets/core-icons.d.ts.map +1 -0
- package/icons/icon-sets/core-icons.js +48 -0
- package/icons/icon-sets/core-icons.js.map +1 -0
- package/index.d.ts +72 -0
- package/index.d.ts.map +1 -0
- package/index.js +54 -0
- package/index.js.map +1 -0
- package/package.json +64 -0
- package/photon-ai/builtins/filter.commands.d.ts +4 -0
- package/photon-ai/builtins/filter.commands.d.ts.map +1 -0
- package/photon-ai/builtins/filter.commands.js +189 -0
- package/photon-ai/builtins/filter.commands.js.map +1 -0
- package/photon-ai/builtins/grouping.commands.d.ts +4 -0
- package/photon-ai/builtins/grouping.commands.d.ts.map +1 -0
- package/photon-ai/builtins/grouping.commands.js +115 -0
- package/photon-ai/builtins/grouping.commands.js.map +1 -0
- package/photon-ai/builtins/index.d.ts +10 -0
- package/photon-ai/builtins/index.d.ts.map +1 -0
- package/photon-ai/builtins/index.js +26 -0
- package/photon-ai/builtins/index.js.map +1 -0
- package/photon-ai/builtins/info.commands.d.ts +4 -0
- package/photon-ai/builtins/info.commands.d.ts.map +1 -0
- package/photon-ai/builtins/info.commands.js +201 -0
- package/photon-ai/builtins/info.commands.js.map +1 -0
- package/photon-ai/builtins/move.commands.d.ts +4 -0
- package/photon-ai/builtins/move.commands.d.ts.map +1 -0
- package/photon-ai/builtins/move.commands.js +53 -0
- package/photon-ai/builtins/move.commands.js.map +1 -0
- package/photon-ai/builtins/pin.commands.d.ts +4 -0
- package/photon-ai/builtins/pin.commands.d.ts.map +1 -0
- package/photon-ai/builtins/pin.commands.js +106 -0
- package/photon-ai/builtins/pin.commands.js.map +1 -0
- package/photon-ai/builtins/selection.commands.d.ts +4 -0
- package/photon-ai/builtins/selection.commands.d.ts.map +1 -0
- package/photon-ai/builtins/selection.commands.js +102 -0
- package/photon-ai/builtins/selection.commands.js.map +1 -0
- package/photon-ai/builtins/sort.commands.d.ts +4 -0
- package/photon-ai/builtins/sort.commands.d.ts.map +1 -0
- package/photon-ai/builtins/sort.commands.js +67 -0
- package/photon-ai/builtins/sort.commands.js.map +1 -0
- package/photon-ai/builtins/visibility.commands.d.ts +4 -0
- package/photon-ai/builtins/visibility.commands.d.ts.map +1 -0
- package/photon-ai/builtins/visibility.commands.js +75 -0
- package/photon-ai/builtins/visibility.commands.js.map +1 -0
- package/photon-ai/command-builder.d.ts +21 -0
- package/photon-ai/command-builder.d.ts.map +1 -0
- package/photon-ai/command-builder.js +18 -0
- package/photon-ai/command-builder.js.map +1 -0
- package/photon-ai/command-executor.d.ts +15 -0
- package/photon-ai/command-executor.d.ts.map +1 -0
- package/photon-ai/command-executor.js +26 -0
- package/photon-ai/command-executor.js.map +1 -0
- package/photon-ai/entity-resolver.d.ts +121 -0
- package/photon-ai/entity-resolver.d.ts.map +1 -0
- package/photon-ai/entity-resolver.js +393 -0
- package/photon-ai/entity-resolver.js.map +1 -0
- package/photon-ai/fuzzy-match.d.ts +12 -0
- package/photon-ai/fuzzy-match.d.ts.map +1 -0
- package/photon-ai/fuzzy-match.js +37 -0
- package/photon-ai/fuzzy-match.js.map +1 -0
- package/photon-ai/index.d.ts +15 -0
- package/photon-ai/index.d.ts.map +1 -0
- package/photon-ai/index.js +13 -0
- package/photon-ai/index.js.map +1 -0
- package/photon-ai/intent-parser.d.ts +20 -0
- package/photon-ai/intent-parser.d.ts.map +1 -0
- package/photon-ai/intent-parser.js +52 -0
- package/photon-ai/intent-parser.js.map +1 -0
- package/photon-ai/photon-ai-memory.d.ts +42 -0
- package/photon-ai/photon-ai-memory.d.ts.map +1 -0
- package/photon-ai/photon-ai-memory.js +86 -0
- package/photon-ai/photon-ai-memory.js.map +1 -0
- package/photon-ai/photon-ai-panel.d.ts +54 -0
- package/photon-ai/photon-ai-panel.d.ts.map +1 -0
- package/photon-ai/photon-ai-panel.js +191 -0
- package/photon-ai/photon-ai-panel.js.map +1 -0
- package/photon-ai/photon-ai-registry.d.ts +25 -0
- package/photon-ai/photon-ai-registry.d.ts.map +1 -0
- package/photon-ai/photon-ai-registry.js +41 -0
- package/photon-ai/photon-ai-registry.js.map +1 -0
- package/photon-ai/photon-ai-service.d.ts +71 -0
- package/photon-ai/photon-ai-service.d.ts.map +1 -0
- package/photon-ai/photon-ai-service.js +165 -0
- package/photon-ai/photon-ai-service.js.map +1 -0
- package/photon-ai/photon-ai.types.d.ts +100 -0
- package/photon-ai/photon-ai.types.d.ts.map +1 -0
- package/photon-ai/photon-ai.types.js +2 -0
- package/photon-ai/photon-ai.types.js.map +1 -0
- package/photon-ai/query-splitter.d.ts +22 -0
- package/photon-ai/query-splitter.d.ts.map +1 -0
- package/photon-ai/query-splitter.js +81 -0
- package/photon-ai/query-splitter.js.map +1 -0
- package/photon-ai/text-normalizer.d.ts +33 -0
- package/photon-ai/text-normalizer.d.ts.map +1 -0
- package/photon-ai/text-normalizer.js +132 -0
- package/photon-ai/text-normalizer.js.map +1 -0
- package/renderer/auto-scroller.d.ts +78 -0
- package/renderer/auto-scroller.d.ts.map +1 -0
- package/renderer/auto-scroller.js +141 -0
- package/renderer/auto-scroller.js.map +1 -0
- package/renderer/body-renderer.d.ts +191 -0
- package/renderer/body-renderer.d.ts.map +1 -0
- package/renderer/body-renderer.js +806 -0
- package/renderer/body-renderer.js.map +1 -0
- package/renderer/cell-renderer.d.ts +26 -0
- package/renderer/cell-renderer.d.ts.map +1 -0
- package/renderer/cell-renderer.js +201 -0
- package/renderer/cell-renderer.js.map +1 -0
- package/renderer/column-menu.d.ts +285 -0
- package/renderer/column-menu.d.ts.map +1 -0
- package/renderer/column-menu.js +873 -0
- package/renderer/column-menu.js.map +1 -0
- package/renderer/column-style-manager.d.ts +38 -0
- package/renderer/column-style-manager.d.ts.map +1 -0
- package/renderer/column-style-manager.js +110 -0
- package/renderer/column-style-manager.js.map +1 -0
- package/renderer/detail-row-renderer.d.ts +153 -0
- package/renderer/detail-row-renderer.d.ts.map +1 -0
- package/renderer/detail-row-renderer.js +388 -0
- package/renderer/detail-row-renderer.js.map +1 -0
- package/renderer/dom-utils.d.ts +22 -0
- package/renderer/dom-utils.d.ts.map +1 -0
- package/renderer/dom-utils.js +132 -0
- package/renderer/dom-utils.js.map +1 -0
- package/renderer/footer-renderer.d.ts +25 -0
- package/renderer/footer-renderer.d.ts.map +1 -0
- package/renderer/footer-renderer.js +168 -0
- package/renderer/footer-renderer.js.map +1 -0
- package/renderer/grid-renderer.d.ts +295 -0
- package/renderer/grid-renderer.d.ts.map +1 -0
- package/renderer/grid-renderer.js +1456 -0
- package/renderer/grid-renderer.js.map +1 -0
- package/renderer/group-context-menu.d.ts +79 -0
- package/renderer/group-context-menu.d.ts.map +1 -0
- package/renderer/group-context-menu.js +238 -0
- package/renderer/group-context-menu.js.map +1 -0
- package/renderer/group-drop-zone.d.ts +56 -0
- package/renderer/group-drop-zone.d.ts.map +1 -0
- package/renderer/group-drop-zone.js +376 -0
- package/renderer/group-drop-zone.js.map +1 -0
- package/renderer/header-renderer.d.ts +264 -0
- package/renderer/header-renderer.d.ts.map +1 -0
- package/renderer/header-renderer.js +1321 -0
- package/renderer/header-renderer.js.map +1 -0
- package/renderer/overlay-renderer.d.ts +16 -0
- package/renderer/overlay-renderer.d.ts.map +1 -0
- package/renderer/overlay-renderer.js +64 -0
- package/renderer/overlay-renderer.js.map +1 -0
- package/renderer/renderer-resolver.d.ts +18 -0
- package/renderer/renderer-resolver.d.ts.map +1 -0
- package/renderer/renderer-resolver.js +18 -0
- package/renderer/renderer-resolver.js.map +1 -0
- package/renderer/row-animator.d.ts +72 -0
- package/renderer/row-animator.d.ts.map +1 -0
- package/renderer/row-animator.js +175 -0
- package/renderer/row-animator.js.map +1 -0
- package/renderer/row-drag-renderer.d.ts +58 -0
- package/renderer/row-drag-renderer.d.ts.map +1 -0
- package/renderer/row-drag-renderer.js +395 -0
- package/renderer/row-drag-renderer.js.map +1 -0
- package/renderer/row-offset-search.d.ts +17 -0
- package/renderer/row-offset-search.d.ts.map +1 -0
- package/renderer/row-offset-search.js +31 -0
- package/renderer/row-offset-search.js.map +1 -0
- package/renderer/row-position-sheet.d.ts +11 -0
- package/renderer/row-position-sheet.d.ts.map +1 -0
- package/renderer/row-position-sheet.js +29 -0
- package/renderer/row-position-sheet.js.map +1 -0
- package/renderer/scroll-controller.d.ts +58 -0
- package/renderer/scroll-controller.d.ts.map +1 -0
- package/renderer/scroll-controller.js +200 -0
- package/renderer/scroll-controller.js.map +1 -0
- package/renderer/sticky-row-tracker.d.ts +40 -0
- package/renderer/sticky-row-tracker.d.ts.map +1 -0
- package/renderer/sticky-row-tracker.js +63 -0
- package/renderer/sticky-row-tracker.js.map +1 -0
- package/renderer/tooltip-renderer.d.ts +36 -0
- package/renderer/tooltip-renderer.d.ts.map +1 -0
- package/renderer/tooltip-renderer.js +133 -0
- package/renderer/tooltip-renderer.js.map +1 -0
- package/renderer/tree-cell-renderer.d.ts +37 -0
- package/renderer/tree-cell-renderer.d.ts.map +1 -0
- package/renderer/tree-cell-renderer.js +75 -0
- package/renderer/tree-cell-renderer.js.map +1 -0
- package/renderer/tree-sticky-row-tracker.d.ts +62 -0
- package/renderer/tree-sticky-row-tracker.d.ts.map +1 -0
- package/renderer/tree-sticky-row-tracker.js +120 -0
- package/renderer/tree-sticky-row-tracker.js.map +1 -0
- package/renderer/virtual-scroll-renderer.d.ts +37 -0
- package/renderer/virtual-scroll-renderer.d.ts.map +1 -0
- package/renderer/virtual-scroll-renderer.js +133 -0
- package/renderer/virtual-scroll-renderer.js.map +1 -0
- package/styles/base-styles.d.ts +3 -0
- package/styles/base-styles.d.ts.map +1 -0
- package/styles/base-styles.js +3045 -0
- package/styles/base-styles.js.map +1 -0
- package/styles/themes/theme-alpine.d.ts +2 -0
- package/styles/themes/theme-alpine.d.ts.map +1 -0
- package/styles/themes/theme-alpine.js +120 -0
- package/styles/themes/theme-alpine.js.map +1 -0
- package/styles/themes/theme-balham.d.ts +2 -0
- package/styles/themes/theme-balham.d.ts.map +1 -0
- package/styles/themes/theme-balham.js +120 -0
- package/styles/themes/theme-balham.js.map +1 -0
- package/styles/themes/theme-dark.d.ts +2 -0
- package/styles/themes/theme-dark.d.ts.map +1 -0
- package/styles/themes/theme-dark.js +216 -0
- package/styles/themes/theme-dark.js.map +1 -0
- package/styles/themes/theme-material.d.ts +2 -0
- package/styles/themes/theme-material.d.ts.map +1 -0
- package/styles/themes/theme-material.js +134 -0
- package/styles/themes/theme-material.js.map +1 -0
- package/styles/themes/theme-quartz.d.ts +2 -0
- package/styles/themes/theme-quartz.d.ts.map +1 -0
- package/styles/themes/theme-quartz.js +120 -0
- package/styles/themes/theme-quartz.js.map +1 -0
- package/theme/css-var-injector.d.ts +10 -0
- package/theme/css-var-injector.d.ts.map +1 -0
- package/theme/css-var-injector.js +63 -0
- package/theme/css-var-injector.js.map +1 -0
- package/theme/theme-manager.d.ts +20 -0
- package/theme/theme-manager.d.ts.map +1 -0
- package/theme/theme-manager.js +79 -0
- package/theme/theme-manager.js.map +1 -0
- package/theme/themes/dark-theme.d.ts +3 -0
- package/theme/themes/dark-theme.d.ts.map +1 -0
- package/theme/themes/dark-theme.js +149 -0
- package/theme/themes/dark-theme.js.map +1 -0
- package/theme/themes/light-theme.d.ts +3 -0
- package/theme/themes/light-theme.d.ts.map +1 -0
- package/theme/themes/light-theme.js +149 -0
- package/theme/themes/light-theme.js.map +1 -0
- package/types/column.types.d.ts +195 -0
- package/types/column.types.d.ts.map +1 -0
- package/types/column.types.js +2 -0
- package/types/column.types.js.map +1 -0
- package/types/event.types.d.ts +213 -0
- package/types/event.types.d.ts.map +1 -0
- package/types/event.types.js +67 -0
- package/types/event.types.js.map +1 -0
- package/types/filter.types.d.ts +42 -0
- package/types/filter.types.d.ts.map +1 -0
- package/types/filter.types.js +2 -0
- package/types/filter.types.js.map +1 -0
- package/types/grid.types.d.ts +214 -0
- package/types/grid.types.d.ts.map +1 -0
- package/types/grid.types.js +2 -0
- package/types/grid.types.js.map +1 -0
- package/types/master-detail.types.d.ts +112 -0
- package/types/master-detail.types.d.ts.map +1 -0
- package/types/master-detail.types.js +2 -0
- package/types/master-detail.types.js.map +1 -0
- package/types/photon-ai.types.d.ts +19 -0
- package/types/photon-ai.types.d.ts.map +1 -0
- package/types/photon-ai.types.js +2 -0
- package/types/photon-ai.types.js.map +1 -0
- package/types/renderer.types.d.ts +156 -0
- package/types/renderer.types.d.ts.map +1 -0
- package/types/renderer.types.js +19 -0
- package/types/renderer.types.js.map +1 -0
- package/types/row.types.d.ts +127 -0
- package/types/row.types.d.ts.map +1 -0
- package/types/row.types.js +9 -0
- package/types/row.types.js.map +1 -0
- package/types/theme.types.d.ts +159 -0
- package/types/theme.types.d.ts.map +1 -0
- package/types/theme.types.js +2 -0
- package/types/theme.types.js.map +1 -0
- package/types/tree-data.types.d.ts +94 -0
- package/types/tree-data.types.d.ts.map +1 -0
- package/types/tree-data.types.js +2 -0
- package/types/tree-data.types.js.map +1 -0
|
@@ -0,0 +1,1321 @@
|
|
|
1
|
+
import { GridEventType } from '../types/event.types';
|
|
2
|
+
import { ColumnMenu } from './column-menu';
|
|
3
|
+
import { GroupContextMenu } from './group-context-menu';
|
|
4
|
+
import { createDiv, toggleClass } from './dom-utils';
|
|
5
|
+
import { resolveColumnRenderer } from './renderer-resolver';
|
|
6
|
+
export class HeaderRenderer {
|
|
7
|
+
/** Read by grid-renderer's columns-store watcher to skip header destroy during drag */
|
|
8
|
+
get isDraggingCol() { return this.isDragging; }
|
|
9
|
+
/**
|
|
10
|
+
* `true` between the resize-handle `mousedown` and the corresponding `mouseup`.
|
|
11
|
+
* Grid-renderer uses this to suppress body `renderRows` during resize — column
|
|
12
|
+
* widths are driven by CSS rules from `ColumnStyleManager`, so the body DOM
|
|
13
|
+
* never needs to be rebuilt while the user is dragging a resize handle.
|
|
14
|
+
*/
|
|
15
|
+
get isResizingColumn() { return this._isResizingColumn; }
|
|
16
|
+
constructor(store, eventBus, iconRenderer, columnModel, sortEngine, colStyles) {
|
|
17
|
+
this.store = store;
|
|
18
|
+
this.eventBus = eventBus;
|
|
19
|
+
this.iconRenderer = iconRenderer;
|
|
20
|
+
this.columnModel = columnModel;
|
|
21
|
+
this.sortEngine = sortEngine;
|
|
22
|
+
this.colStyles = colStyles;
|
|
23
|
+
this.leftHeaderRowEl = null;
|
|
24
|
+
this.centerHeaderRowEl = null;
|
|
25
|
+
this.rightHeaderRowEl = null;
|
|
26
|
+
this.centerFilterRowEl = null;
|
|
27
|
+
this.headerCheckbox = null;
|
|
28
|
+
this.groupContextMenu = null;
|
|
29
|
+
this.groupDropZone = null;
|
|
30
|
+
// ── Column-group header support ───────────────────────────────────────────
|
|
31
|
+
/** Tree model for the column group hierarchy. `null` until wired via `setColumnGroupModel`. */
|
|
32
|
+
this.groupModel = null;
|
|
33
|
+
/** DOM builder for multi-row grouped header rows. `null` until wired. */
|
|
34
|
+
this.groupHeaderBuilder = null;
|
|
35
|
+
/** Group header row elements per panel — indexed 0..maxDepth-1. */
|
|
36
|
+
this.leftGroupRowEls = [];
|
|
37
|
+
this.centerGroupRowEls = [];
|
|
38
|
+
this.rightGroupRowEls = [];
|
|
39
|
+
/**
|
|
40
|
+
* Callback invoked when the user clicks a group collapse/expand toggle.
|
|
41
|
+
* Provided by `GridRenderer` so it can coordinate header + body rebuild.
|
|
42
|
+
*/
|
|
43
|
+
this.onGroupToggleFn = null;
|
|
44
|
+
/**
|
|
45
|
+
* Callback invoked when the user finishes dragging a group resize handle.
|
|
46
|
+
* `GridRenderer` wires this to distribute the delta and trigger reflow.
|
|
47
|
+
*/
|
|
48
|
+
this.onGroupResizeFn = null;
|
|
49
|
+
/**
|
|
50
|
+
* Wired by `GridRenderer` after group model setup — used in `onGlobalMouseUp`
|
|
51
|
+
* to create a clone group when a leaf is dropped onto a different group header.
|
|
52
|
+
*/
|
|
53
|
+
this.groupDragHandler = null;
|
|
54
|
+
/**
|
|
55
|
+
* Display Group Engine — the new architecture that replaces ColumnGroupModel.
|
|
56
|
+
* When set, `renderInPanels` uses this engine instead of the legacy model.
|
|
57
|
+
*/
|
|
58
|
+
this.displayGroupEngine = null;
|
|
59
|
+
/**
|
|
60
|
+
* Cached header row height from the last `renderInPanels` / `updateCenterVisibleCols`
|
|
61
|
+
* call. Used by `rebuildGroupRowsForPanel` which is called during drag when
|
|
62
|
+
* `HeaderRendererOptions` is not available on the call stack.
|
|
63
|
+
*/
|
|
64
|
+
this.lastGroupRowHeight = 44;
|
|
65
|
+
// Drag state
|
|
66
|
+
this.draggingColId = null;
|
|
67
|
+
this.isDragging = false;
|
|
68
|
+
this.draggingPanelRowEl = null;
|
|
69
|
+
this.draggingIsGroupable = false;
|
|
70
|
+
this.isOverGroupZone = false;
|
|
71
|
+
this.ghostEl = null;
|
|
72
|
+
this.dragStyleEl = null;
|
|
73
|
+
this.draggingGridEl = null;
|
|
74
|
+
this.draggedColWidth = 0;
|
|
75
|
+
this.dragStartScrollX = 0;
|
|
76
|
+
this.dragIsHideMode = false;
|
|
77
|
+
this.dragSourcePanel = 'center';
|
|
78
|
+
this.dragTargetPanel = 'center';
|
|
79
|
+
this.dragTargetLocalIdx = -1;
|
|
80
|
+
this.panelDragData = [];
|
|
81
|
+
// Live cross-panel move state
|
|
82
|
+
this.livePanelMoveInProgress = false;
|
|
83
|
+
// Auto-scroll state
|
|
84
|
+
this.scrollByX = null;
|
|
85
|
+
this.canScrollX = null;
|
|
86
|
+
this.onResizeCb = null;
|
|
87
|
+
this.autoScrollRAF = 0;
|
|
88
|
+
this.autoScrollSpeed = 0;
|
|
89
|
+
this.centerPanelRect = null;
|
|
90
|
+
/** Last known cursor X during column drag — used to replay `onDragMove` after auto-scroll ticks. */
|
|
91
|
+
this.lastDragClientX = 0;
|
|
92
|
+
/** Callback wired by GridRenderer to open a filter panel for a column. */
|
|
93
|
+
this.openFilterPanelFn = null;
|
|
94
|
+
/** True while the user holds the resize handle and is actively moving the mouse. */
|
|
95
|
+
this._isResizingColumn = false;
|
|
96
|
+
// ─── Auto-scroll ──────────────────────────────────────────────────────────
|
|
97
|
+
this.tickAutoScroll = () => {
|
|
98
|
+
if (!this.isDragging || this.autoScrollSpeed === 0)
|
|
99
|
+
return;
|
|
100
|
+
if (this.autoScrollSpeed < 0 && !(this.canScrollX?.(-1) ?? true)) {
|
|
101
|
+
this.stopAutoScroll();
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (this.autoScrollSpeed > 0 && !(this.canScrollX?.(1) ?? true)) {
|
|
105
|
+
this.stopAutoScroll();
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
this.scrollByX?.(this.autoScrollSpeed);
|
|
109
|
+
// Immediately re-evaluate drag position using the updated --pg-scroll-x so
|
|
110
|
+
// header and body cell transforms stay in sync with the scroll on this frame.
|
|
111
|
+
// scrollDelta inside onDragMove reads the CSS var synchronously.
|
|
112
|
+
this.onDragMove(this.lastDragClientX);
|
|
113
|
+
this.autoScrollRAF = requestAnimationFrame(this.tickAutoScroll);
|
|
114
|
+
};
|
|
115
|
+
this.columnMenu = new ColumnMenu(columnModel, sortEngine, eventBus, iconRenderer, (action, colId) => this.onAction(action, colId));
|
|
116
|
+
this.columnMenu.setMenuCallbacks({
|
|
117
|
+
onAutoSize: (colId) => this.onAction('autosize', colId),
|
|
118
|
+
onAutoSizeAll: () => this.onAction('autosize-all', ''),
|
|
119
|
+
onFitToGrid: () => this.onAction('fit-to-grid', ''),
|
|
120
|
+
onResetWidth: (colId) => this.onAction('reset-width', colId),
|
|
121
|
+
onOpenColumnChooser: () => this.onAction('column-chooser', ''),
|
|
122
|
+
onOpenAdvancedFilter: (colDef, anchorEl) => {
|
|
123
|
+
this.openFilterPanelFn?.(colDef, anchorEl);
|
|
124
|
+
this.onAction('advanced-filter', colDef.colId);
|
|
125
|
+
},
|
|
126
|
+
onQuickFilter: (colId) => this.onAction('quick-filter', colId),
|
|
127
|
+
onCopyHeader: (colDef) => {
|
|
128
|
+
navigator.clipboard?.writeText(colDef.header).catch(() => { });
|
|
129
|
+
this.onAction('copy-header', colDef.colId);
|
|
130
|
+
},
|
|
131
|
+
onCopyColumn: (colDef) => this.onAction('copy-column', colDef.colId),
|
|
132
|
+
onCopyValues: (colDef) => this.onAction('copy-values', colDef.colId),
|
|
133
|
+
onRename: (colDef) => this.onAction('rename', colDef.colId),
|
|
134
|
+
onDuplicate: (colDef) => this.onAction('duplicate', colDef.colId),
|
|
135
|
+
onFreezePosition: (colDef) => this.onAction('freeze', colDef.colId),
|
|
136
|
+
onLockColumn: (colDef) => this.onAction('lock', colDef.colId),
|
|
137
|
+
onResetColumn: (colDef) => this.onAction('reset-column', colDef.colId),
|
|
138
|
+
onAggregate: (colDef, func) => this.onAction(`aggregate-${func}`, colDef.colId),
|
|
139
|
+
onMoveLeft: (colId) => {
|
|
140
|
+
const cols = columnModel.getVisibleColumns();
|
|
141
|
+
const idx = cols.findIndex((c) => c.colId === colId);
|
|
142
|
+
if (idx > 0) {
|
|
143
|
+
columnModel.moveColumn(idx, idx - 1);
|
|
144
|
+
this.onAction('move', colId);
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
onMoveRight: (colId) => {
|
|
148
|
+
const cols = columnModel.getVisibleColumns();
|
|
149
|
+
const idx = cols.findIndex((c) => c.colId === colId);
|
|
150
|
+
if (idx < cols.length - 1) {
|
|
151
|
+
columnModel.moveColumn(idx, idx + 1);
|
|
152
|
+
this.onAction('move', colId);
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
onMoveStart: (colId) => {
|
|
156
|
+
const cols = columnModel.getVisibleColumns();
|
|
157
|
+
const idx = cols.findIndex((c) => c.colId === colId);
|
|
158
|
+
if (idx > 0) {
|
|
159
|
+
columnModel.moveColumn(idx, 0);
|
|
160
|
+
this.onAction('move', colId);
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
onMoveEnd: (colId) => {
|
|
164
|
+
const cols = columnModel.getVisibleColumns();
|
|
165
|
+
const idx = cols.findIndex((c) => c.colId === colId);
|
|
166
|
+
if (idx < cols.length - 1) {
|
|
167
|
+
columnModel.moveColumn(idx, cols.length - 1);
|
|
168
|
+
this.onAction('move', colId);
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
this.boundMouseMove = this.onGlobalMouseMove.bind(this);
|
|
173
|
+
this.boundMouseUp = this.onGlobalMouseUp.bind(this);
|
|
174
|
+
}
|
|
175
|
+
setScrollCallback(fn, canScrollX) {
|
|
176
|
+
this.scrollByX = fn;
|
|
177
|
+
this.canScrollX = canScrollX ?? null;
|
|
178
|
+
}
|
|
179
|
+
setResizeCallback(cb) {
|
|
180
|
+
this.onResizeCb = cb;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Register the callback invoked when the user clicks the filter icon on a
|
|
184
|
+
* filterable column header. Wired by `GridRenderer.buildLayout()`.
|
|
185
|
+
*
|
|
186
|
+
* @param fn - Opens/positions a `FilterPanel` for the given column.
|
|
187
|
+
*/
|
|
188
|
+
setOpenFilterPanelCallback(fn) {
|
|
189
|
+
this.openFilterPanelFn = fn;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Wire the column-group model and DOM builder into the header renderer.
|
|
193
|
+
*
|
|
194
|
+
* Call this before the first `renderInPanels` when the grid's column
|
|
195
|
+
* definitions contain groups (i.e. `ColumnDef.children` is present on any
|
|
196
|
+
* top-level column). Once wired, `renderInPanels` and `updateCenterVisibleCols`
|
|
197
|
+
* automatically insert and update the multi-row grouped header rows.
|
|
198
|
+
*
|
|
199
|
+
* @param model - The live {@link ColumnGroupModel} for the grid.
|
|
200
|
+
* @param builder - The {@link ColumnGroupHeaderBuilder} instance.
|
|
201
|
+
*/
|
|
202
|
+
setColumnGroupModel(model, builder) {
|
|
203
|
+
this.groupModel = model;
|
|
204
|
+
this.groupHeaderBuilder = builder;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Wire the new Display Group Engine into the header renderer.
|
|
208
|
+
* When set, `renderInPanels` uses the engine's builder instead of the legacy
|
|
209
|
+
* `ColumnGroupModel` + `ColumnGroupHeaderBuilder`.
|
|
210
|
+
*
|
|
211
|
+
* @param engine - The fully-initialised `DisplayGroupEngine` instance.
|
|
212
|
+
*/
|
|
213
|
+
setDisplayGroupEngine(engine) {
|
|
214
|
+
this.displayGroupEngine = engine;
|
|
215
|
+
this.groupContextMenu = new GroupContextMenu(engine, this.iconRenderer);
|
|
216
|
+
this.groupContextMenu.setCallbacks({
|
|
217
|
+
onOpenColumnChooser: () => this.onAction('column-chooser', ''),
|
|
218
|
+
onAction: (action, groupId) => this.onAction(action, groupId),
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Register the callback fired when a user toggles a group's collapse state.
|
|
223
|
+
*
|
|
224
|
+
* `GridRenderer` wires this to coordinate header rebuild + leaf-column
|
|
225
|
+
* visibility update in `ColumnModel`.
|
|
226
|
+
*
|
|
227
|
+
* @param fn - Receives the `groupId` of the toggled group.
|
|
228
|
+
*/
|
|
229
|
+
setGroupToggleCallback(fn) {
|
|
230
|
+
this.onGroupToggleFn = fn;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Register the callback fired when a user finishes dragging a group resize handle.
|
|
234
|
+
*
|
|
235
|
+
* `GridRenderer` wires this to call {@link ColumnGroupModel.distributeResizeDelta}
|
|
236
|
+
* and flush the updated widths to `ColumnStyleManager`.
|
|
237
|
+
*
|
|
238
|
+
* @param fn - Receives `groupId` and the new desired total group width.
|
|
239
|
+
*/
|
|
240
|
+
setGroupResizeCallback(fn) {
|
|
241
|
+
this.onGroupResizeFn = fn;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Wire the group drag handler so that leaf drops on foreign group header cells
|
|
245
|
+
* create solo clone groups instead of doing a plain column reorder.
|
|
246
|
+
*
|
|
247
|
+
* @param handler - The active `ColumnGroupDragHandler` instance.
|
|
248
|
+
*/
|
|
249
|
+
setGroupDragHandler(handler) {
|
|
250
|
+
this.groupDragHandler = handler;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Rebuild only the group-header rows for all panels without touching the leaf
|
|
254
|
+
* row or filter row. Call this after a group collapse/expand event has already
|
|
255
|
+
* been processed by the model (i.e. `group.collapsed` flag is up to date).
|
|
256
|
+
*
|
|
257
|
+
* @param options - Header renderer options (passed from last `renderInPanels` call).
|
|
258
|
+
*/
|
|
259
|
+
rebuildGroupRows(options) {
|
|
260
|
+
if (!this.groupModel || !this.groupHeaderBuilder)
|
|
261
|
+
return;
|
|
262
|
+
if (!this.groupModel.hasGroups())
|
|
263
|
+
return;
|
|
264
|
+
const maxDepth = this.groupModel.getMaxDepth();
|
|
265
|
+
const rowHeight = options.headerRowHeight ?? 44;
|
|
266
|
+
const cellOpts = this.buildGroupCellOptions(rowHeight);
|
|
267
|
+
const rebuildPanel = (rowEls, panel) => {
|
|
268
|
+
const nodes = this.groupModel.getRootNodes(panel);
|
|
269
|
+
this.groupHeaderBuilder.updateGroupRows(rowEls, nodes, this.colStyles, maxDepth, cellOpts);
|
|
270
|
+
};
|
|
271
|
+
rebuildPanel(this.leftGroupRowEls, 'left');
|
|
272
|
+
rebuildPanel(this.centerGroupRowEls, 'center');
|
|
273
|
+
rebuildPanel(this.rightGroupRowEls, 'right');
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Updates the filter-active indicator (`pg-th--filter-active` class and icon
|
|
277
|
+
* swap) on every rendered header cell based on the current `FilterModel`.
|
|
278
|
+
* Called from the renderer's `filterModel` store watcher.
|
|
279
|
+
*
|
|
280
|
+
* @param activeColIds - Set of `colId` strings that currently have an active filter.
|
|
281
|
+
*/
|
|
282
|
+
updateFilterIndicators(activeColIds) {
|
|
283
|
+
const rows = [
|
|
284
|
+
this.leftHeaderRowEl,
|
|
285
|
+
this.centerHeaderRowEl,
|
|
286
|
+
this.rightHeaderRowEl,
|
|
287
|
+
].filter((r) => r !== null);
|
|
288
|
+
for (const row of rows) {
|
|
289
|
+
for (const cell of Array.from(row.querySelectorAll('.pg-th[data-col-id]'))) {
|
|
290
|
+
const colId = cell.getAttribute('data-col-id') ?? '';
|
|
291
|
+
const active = activeColIds.has(colId);
|
|
292
|
+
cell.classList.toggle('pg-th--filter-active', active);
|
|
293
|
+
const btn = cell.querySelector('.pg-th__filter-btn');
|
|
294
|
+
if (btn) {
|
|
295
|
+
btn.classList.toggle('pg-th__filter-btn--active', active);
|
|
296
|
+
const iconName = active ? 'filterActive' : 'filter';
|
|
297
|
+
const iconEl = btn.querySelector('.pg-icon');
|
|
298
|
+
if (iconEl)
|
|
299
|
+
this.iconRenderer.updateIcon(iconEl, iconName);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
// ── Private: group-cell option builder ───────────────────────────────────
|
|
305
|
+
/**
|
|
306
|
+
* Build the {@link GroupCellBuildOptions} object forwarded to the DOM builder.
|
|
307
|
+
* Wires the toggle and resize callbacks registered by `GridRenderer`.
|
|
308
|
+
*/
|
|
309
|
+
buildGroupCellOptions(rowHeight) {
|
|
310
|
+
return {
|
|
311
|
+
rowHeight,
|
|
312
|
+
onCollapseToggle: (groupId) => {
|
|
313
|
+
this.onGroupToggleFn?.(groupId);
|
|
314
|
+
},
|
|
315
|
+
onGroupResize: (groupId, newWidth) => {
|
|
316
|
+
this.onGroupResizeFn?.(groupId, newWidth);
|
|
317
|
+
},
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
renderInPanels(leftContainer, centerInnerEl, rightContainer, allColumns, options = {}) {
|
|
321
|
+
const leftCols = allColumns.filter((c) => c.pinned === 'left');
|
|
322
|
+
const centerCols = allColumns.filter((c) => c.pinned !== 'left' && c.pinned !== 'right');
|
|
323
|
+
const rightCols = allColumns.filter((c) => c.pinned === 'right');
|
|
324
|
+
this.lastGroupRowHeight = options.headerRowHeight ?? this.lastGroupRowHeight;
|
|
325
|
+
// ── Group header rows (must be inserted BEFORE leaf row) ──────────────
|
|
326
|
+
this.leftGroupRowEls = [];
|
|
327
|
+
this.centerGroupRowEls = [];
|
|
328
|
+
this.rightGroupRowEls = [];
|
|
329
|
+
if (this.displayGroupEngine?.hasGroups) {
|
|
330
|
+
// ── New Display Group Engine path ─────────────────────────────────────
|
|
331
|
+
const engine = this.displayGroupEngine;
|
|
332
|
+
const rowHeight = options.headerRowHeight ?? 44;
|
|
333
|
+
const dragHandler = engine.getDragHandler();
|
|
334
|
+
const cellOpts = {
|
|
335
|
+
rowHeight,
|
|
336
|
+
onCollapseToggle: (id) => this.onGroupToggleFn?.(id),
|
|
337
|
+
onGroupResize: (id, w) => this.onGroupResizeFn?.(id, w),
|
|
338
|
+
onGroupHeaderMouseDown: dragHandler
|
|
339
|
+
? (e, node, el) => dragHandler.onHeaderMouseDown(e, node, el)
|
|
340
|
+
: undefined,
|
|
341
|
+
didJustDragFn: dragHandler ? () => dragHandler.didJustDrag : undefined,
|
|
342
|
+
onGroupContextMenu: (e, node, el) => this.groupContextMenu?.show(node, el, e.clientX, e.clientY),
|
|
343
|
+
};
|
|
344
|
+
this.leftGroupRowEls = engine.headerBuilder.buildGroupRows(engine.buildTree(leftCols), cellOpts);
|
|
345
|
+
this.centerGroupRowEls = engine.headerBuilder.buildGroupRows(engine.buildTree(centerCols), cellOpts);
|
|
346
|
+
this.rightGroupRowEls = engine.headerBuilder.buildGroupRows(engine.buildTree(rightCols), cellOpts);
|
|
347
|
+
for (const el of this.leftGroupRowEls)
|
|
348
|
+
leftContainer.appendChild(el);
|
|
349
|
+
for (const el of this.centerGroupRowEls)
|
|
350
|
+
centerInnerEl.appendChild(el);
|
|
351
|
+
for (const el of this.rightGroupRowEls)
|
|
352
|
+
rightContainer.appendChild(el);
|
|
353
|
+
// Flat column cells use this to compute their full-height transform.
|
|
354
|
+
leftContainer.style.setProperty('--pg-group-rows-count', String(this.leftGroupRowEls.length));
|
|
355
|
+
centerInnerEl.style.setProperty('--pg-group-rows-count', String(this.centerGroupRowEls.length));
|
|
356
|
+
rightContainer.style.setProperty('--pg-group-rows-count', String(this.rightGroupRowEls.length));
|
|
357
|
+
}
|
|
358
|
+
else if (this.groupModel?.hasGroups() && this.groupHeaderBuilder) {
|
|
359
|
+
// ── Legacy ColumnGroupModel path (kept for compatibility) ─────────────
|
|
360
|
+
const maxDepth = this.groupModel.getMaxDepth();
|
|
361
|
+
const rowHeight = options.headerRowHeight ?? 44;
|
|
362
|
+
const cellOpts = this.buildGroupCellOptions(rowHeight);
|
|
363
|
+
this.leftGroupRowEls = this.groupHeaderBuilder.buildGroupRows(this.groupModel.getRootNodes('left'), this.colStyles, maxDepth, cellOpts);
|
|
364
|
+
this.centerGroupRowEls = this.groupHeaderBuilder.buildGroupRows(this.groupModel.getRootNodes('center'), this.colStyles, maxDepth, cellOpts);
|
|
365
|
+
this.rightGroupRowEls = this.groupHeaderBuilder.buildGroupRows(this.groupModel.getRootNodes('right'), this.colStyles, maxDepth, cellOpts);
|
|
366
|
+
for (const el of this.leftGroupRowEls)
|
|
367
|
+
leftContainer.appendChild(el);
|
|
368
|
+
for (const el of this.centerGroupRowEls)
|
|
369
|
+
centerInnerEl.appendChild(el);
|
|
370
|
+
for (const el of this.rightGroupRowEls)
|
|
371
|
+
rightContainer.appendChild(el);
|
|
372
|
+
}
|
|
373
|
+
// ── Leaf header rows ──────────────────────────────────────────────────
|
|
374
|
+
this.leftHeaderRowEl = this.buildHeaderRow(leftCols, options, true);
|
|
375
|
+
leftContainer.appendChild(this.leftHeaderRowEl);
|
|
376
|
+
if (options.showFilterRow)
|
|
377
|
+
leftContainer.appendChild(this.buildFilterRow(leftCols, options, true));
|
|
378
|
+
this.centerHeaderRowEl = this.buildHeaderRow(centerCols, options, false);
|
|
379
|
+
if (options.hasGroupedColumns) {
|
|
380
|
+
this.centerHeaderRowEl.insertBefore(this.buildAutoGroupTh(options.autoGroupColWidth ?? 200), this.centerHeaderRowEl.firstChild);
|
|
381
|
+
}
|
|
382
|
+
centerInnerEl.appendChild(this.centerHeaderRowEl);
|
|
383
|
+
if (options.showFilterRow) {
|
|
384
|
+
const filterRow = this.buildFilterRow(centerCols, options, false);
|
|
385
|
+
this.centerFilterRowEl = filterRow;
|
|
386
|
+
if (options.hasGroupedColumns)
|
|
387
|
+
filterRow.insertBefore(createDiv('pg-filter-cell pg-filter-cell--auto-group'), filterRow.firstChild);
|
|
388
|
+
centerInnerEl.appendChild(filterRow);
|
|
389
|
+
}
|
|
390
|
+
this.rightHeaderRowEl = this.buildHeaderRow(rightCols, options, false);
|
|
391
|
+
rightContainer.appendChild(this.rightHeaderRowEl);
|
|
392
|
+
if (options.showFilterRow)
|
|
393
|
+
rightContainer.appendChild(this.buildFilterRow(rightCols, options, false));
|
|
394
|
+
}
|
|
395
|
+
updateSortIndicator(colId, order) {
|
|
396
|
+
const rows = [this.leftHeaderRowEl, this.centerHeaderRowEl, this.rightHeaderRowEl].filter((r) => r !== null);
|
|
397
|
+
for (const row of rows) {
|
|
398
|
+
for (const cell of Array.from(row.querySelectorAll('.pg-th[data-col-id]'))) {
|
|
399
|
+
const isTarget = cell.getAttribute('data-col-id') === colId;
|
|
400
|
+
toggleClass(cell, 'pg-th--sort-asc', isTarget && order === 'asc');
|
|
401
|
+
toggleClass(cell, 'pg-th--sort-desc', isTarget && order === 'desc');
|
|
402
|
+
toggleClass(cell, 'pg-th--sorted', isTarget && order !== null);
|
|
403
|
+
if (isTarget) {
|
|
404
|
+
const iconEl = cell.querySelector('.pg-th__sort-icon');
|
|
405
|
+
if (iconEl)
|
|
406
|
+
this.iconRenderer.updateIcon(iconEl, order === 'asc' ? 'sortAsc' : order === 'desc' ? 'sortDesc' : 'sortNone');
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
updateAllChecked(isAll, isIndeterminate) {
|
|
412
|
+
if (!this.headerCheckbox)
|
|
413
|
+
return;
|
|
414
|
+
this.headerCheckbox.checked = isAll;
|
|
415
|
+
this.headerCheckbox.indeterminate = isIndeterminate && !isAll;
|
|
416
|
+
}
|
|
417
|
+
setGroupDropZone(zone) {
|
|
418
|
+
this.groupDropZone = zone;
|
|
419
|
+
this.columnMenu.setGroupCallbacks({
|
|
420
|
+
isGrouped: (colId) => zone.isGrouped(colId),
|
|
421
|
+
addGroup: (colId) => zone.dropColumn(colId),
|
|
422
|
+
removeGroup: (colId) => zone.removeColumn(colId),
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
destroy() {
|
|
426
|
+
document.removeEventListener('mousemove', this.boundMouseMove);
|
|
427
|
+
document.removeEventListener('mouseup', this.boundMouseUp);
|
|
428
|
+
this.columnMenu.destroy();
|
|
429
|
+
this.groupContextMenu?.destroy();
|
|
430
|
+
this.leftHeaderRowEl = null;
|
|
431
|
+
this.centerHeaderRowEl = null;
|
|
432
|
+
this.rightHeaderRowEl = null;
|
|
433
|
+
this.centerFilterRowEl = null;
|
|
434
|
+
this.headerCheckbox = null;
|
|
435
|
+
this.leftGroupRowEls = [];
|
|
436
|
+
this.centerGroupRowEls = [];
|
|
437
|
+
this.rightGroupRowEls = [];
|
|
438
|
+
}
|
|
439
|
+
updateCenterVisibleCols(visibleCols, leftSpacerW, rightSpacerW, options) {
|
|
440
|
+
if (!this.centerHeaderRowEl)
|
|
441
|
+
return;
|
|
442
|
+
this.lastGroupRowHeight = options.headerRowHeight ?? this.lastGroupRowHeight;
|
|
443
|
+
// ── displayGroupEngine: rebuild group rows live during drag ──────────────
|
|
444
|
+
// Called when store.columns changes mid-drag (cross-panel move via moveToPanelLive).
|
|
445
|
+
// Same-panel drag rebuilds are handled directly in onDragMove.
|
|
446
|
+
if (this.displayGroupEngine?.hasGroups) {
|
|
447
|
+
const allCols = this.store.get('columns');
|
|
448
|
+
const centerCols = allCols.filter((c) => c.pinned !== 'left' && c.pinned !== 'right' && c.visible !== false);
|
|
449
|
+
this.rebuildGroupRowsForPanel('center', centerCols);
|
|
450
|
+
// When dragging cross-panel, left/right group spans change too.
|
|
451
|
+
if (this.isDragging) {
|
|
452
|
+
this.rebuildGroupRowsForPanel('left', allCols.filter((c) => c.pinned === 'left' && c.visible !== false));
|
|
453
|
+
this.rebuildGroupRowsForPanel('right', allCols.filter((c) => c.pinned === 'right' && c.visible !== false));
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
// ── Legacy ColumnGroupModel: in-place update ─────────────────────────────
|
|
457
|
+
if (this.groupModel?.hasGroups() && this.groupHeaderBuilder && this.centerGroupRowEls.length > 0) {
|
|
458
|
+
const maxDepth = this.groupModel.getMaxDepth();
|
|
459
|
+
const rowHeight = options.headerRowHeight ?? 44;
|
|
460
|
+
const cellOpts = this.buildGroupCellOptions(rowHeight);
|
|
461
|
+
this.groupHeaderBuilder.updateGroupRows(this.centerGroupRowEls, this.groupModel.getRootNodes('center'), this.colStyles, maxDepth, cellOpts);
|
|
462
|
+
}
|
|
463
|
+
// During a column drag, detach the dragging TH before clearing innerHTML so
|
|
464
|
+
// the element survives the rebuild. Re-inserting the live element (rather than
|
|
465
|
+
// recreating it) preserves pg-th--dragging, event listeners, and drag CSS state.
|
|
466
|
+
const dragColId = this.isDragging ? this.draggingColId : null;
|
|
467
|
+
let dragThEl = null;
|
|
468
|
+
if (dragColId) {
|
|
469
|
+
dragThEl = this.centerHeaderRowEl.querySelector(`.pg-th[data-col-id="${dragColId}"]`);
|
|
470
|
+
dragThEl?.remove();
|
|
471
|
+
}
|
|
472
|
+
this.centerHeaderRowEl.innerHTML = '';
|
|
473
|
+
if (options.hasGroupedColumns)
|
|
474
|
+
this.centerHeaderRowEl.appendChild(this.buildAutoGroupTh(options.autoGroupColWidth ?? 200));
|
|
475
|
+
if (leftSpacerW > 0)
|
|
476
|
+
this.centerHeaderRowEl.appendChild(this.makeSpacer('pg-th pg-th--h-spacer', leftSpacerW));
|
|
477
|
+
for (let i = 0; i < visibleCols.length; i++) {
|
|
478
|
+
const col = visibleCols[i];
|
|
479
|
+
if (dragThEl && col.colId === dragColId) {
|
|
480
|
+
// Re-insert the live element — preserves class, listeners, and drag state.
|
|
481
|
+
this.centerHeaderRowEl.appendChild(dragThEl);
|
|
482
|
+
}
|
|
483
|
+
else {
|
|
484
|
+
this.centerHeaderRowEl.appendChild(this.buildHeaderCell(col, i, visibleCols, options, this.centerHeaderRowEl));
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
if (rightSpacerW > 0)
|
|
488
|
+
this.centerHeaderRowEl.appendChild(this.makeSpacer('pg-th pg-th--h-spacer', rightSpacerW));
|
|
489
|
+
if (!this.centerFilterRowEl)
|
|
490
|
+
return;
|
|
491
|
+
this.centerFilterRowEl.innerHTML = '';
|
|
492
|
+
if (options.hasGroupedColumns)
|
|
493
|
+
this.centerFilterRowEl.appendChild(createDiv('pg-filter-cell pg-filter-cell--auto-group'));
|
|
494
|
+
if (leftSpacerW > 0)
|
|
495
|
+
this.centerFilterRowEl.appendChild(this.makeSpacer('pg-filter-cell pg-filter-cell--h-spacer', leftSpacerW));
|
|
496
|
+
for (const col of visibleCols)
|
|
497
|
+
this.centerFilterRowEl.appendChild(this.buildFilterCell(col));
|
|
498
|
+
if (rightSpacerW > 0)
|
|
499
|
+
this.centerFilterRowEl.appendChild(this.makeSpacer('pg-filter-cell pg-filter-cell--h-spacer', rightSpacerW));
|
|
500
|
+
}
|
|
501
|
+
// ─── Private ──────────────────────────────────────────────────────────────
|
|
502
|
+
makeSpacer(cls, w) {
|
|
503
|
+
const sp = createDiv(cls);
|
|
504
|
+
sp.style.cssText = `width:${w}px;min-width:${w}px;flex-shrink:0;`;
|
|
505
|
+
return sp;
|
|
506
|
+
}
|
|
507
|
+
capturePanelDragData() {
|
|
508
|
+
const gatherPD = (panel, rowEl) => {
|
|
509
|
+
if (!rowEl)
|
|
510
|
+
return null;
|
|
511
|
+
const ths = Array.from(rowEl.querySelectorAll('.pg-th[data-col-id]'));
|
|
512
|
+
const headerPanel = rowEl.closest('.pg-panel__header');
|
|
513
|
+
const bounds = headerPanel?.getBoundingClientRect() ?? null;
|
|
514
|
+
if (!bounds || bounds.width === 0)
|
|
515
|
+
return null;
|
|
516
|
+
return {
|
|
517
|
+
panel,
|
|
518
|
+
rects: ths.map((t) => t.getBoundingClientRect()),
|
|
519
|
+
colIds: ths.map((t) => t.getAttribute('data-col-id') ?? ''),
|
|
520
|
+
bounds,
|
|
521
|
+
};
|
|
522
|
+
};
|
|
523
|
+
return [
|
|
524
|
+
gatherPD('left', this.leftHeaderRowEl),
|
|
525
|
+
gatherPD('center', this.centerHeaderRowEl),
|
|
526
|
+
gatherPD('right', this.rightHeaderRowEl),
|
|
527
|
+
].filter((pd) => pd !== null);
|
|
528
|
+
}
|
|
529
|
+
buildHeaderRow(columns, options, isLeft) {
|
|
530
|
+
const row = createDiv('pg-header-row');
|
|
531
|
+
row.setAttribute('role', 'row');
|
|
532
|
+
if (isLeft) {
|
|
533
|
+
if (options.showCheckboxes)
|
|
534
|
+
row.appendChild(this.buildCheckboxHeaderCell());
|
|
535
|
+
if (options.showSerialNumber)
|
|
536
|
+
row.appendChild(this.buildSerialHeaderCell());
|
|
537
|
+
}
|
|
538
|
+
for (let i = 0; i < columns.length; i++)
|
|
539
|
+
row.appendChild(this.buildHeaderCell(columns[i], i, columns, options, row));
|
|
540
|
+
return row;
|
|
541
|
+
}
|
|
542
|
+
buildAutoGroupTh(width) {
|
|
543
|
+
const th = createDiv('pg-th pg-th--auto-group');
|
|
544
|
+
th.setAttribute('role', 'columnheader');
|
|
545
|
+
th.style.width = `${width}px`;
|
|
546
|
+
th.style.minWidth = `${width}px`;
|
|
547
|
+
const content = createDiv('pg-th__content');
|
|
548
|
+
const labelEl = createDiv('pg-th__label');
|
|
549
|
+
labelEl.textContent = 'Groups';
|
|
550
|
+
content.appendChild(labelEl);
|
|
551
|
+
th.appendChild(content);
|
|
552
|
+
return th;
|
|
553
|
+
}
|
|
554
|
+
buildCheckboxHeaderCell() {
|
|
555
|
+
const cell = createDiv('pg-th pg-th--checkbox');
|
|
556
|
+
cell.setAttribute('role', 'columnheader');
|
|
557
|
+
const checkbox = document.createElement('input');
|
|
558
|
+
checkbox.type = 'checkbox';
|
|
559
|
+
checkbox.className = 'pg-checkbox pg-header-checkbox';
|
|
560
|
+
checkbox.setAttribute('aria-label', 'Select all rows');
|
|
561
|
+
this.headerCheckbox = checkbox;
|
|
562
|
+
const isAll = this.store.get('isAllSelected');
|
|
563
|
+
const isInd = this.store.get('isIndeterminate');
|
|
564
|
+
checkbox.checked = isAll;
|
|
565
|
+
checkbox.indeterminate = isInd && !isAll;
|
|
566
|
+
checkbox.addEventListener('change', () => {
|
|
567
|
+
this.eventBus.emit(GridEventType.ALL_ROWS_SELECTED, { action: checkbox.checked ? 'selectAll' : 'deselectAll' });
|
|
568
|
+
});
|
|
569
|
+
cell.appendChild(checkbox);
|
|
570
|
+
return cell;
|
|
571
|
+
}
|
|
572
|
+
buildSerialHeaderCell() {
|
|
573
|
+
const cell = createDiv('pg-th pg-th--serial');
|
|
574
|
+
cell.setAttribute('role', 'columnheader');
|
|
575
|
+
const label = document.createElement('span');
|
|
576
|
+
label.className = 'pg-th__serial-label';
|
|
577
|
+
label.textContent = '#';
|
|
578
|
+
cell.appendChild(label);
|
|
579
|
+
return cell;
|
|
580
|
+
}
|
|
581
|
+
buildHeaderCell(col, index, panelColumns, options, panelRowEl) {
|
|
582
|
+
const th = createDiv('pg-th');
|
|
583
|
+
th.setAttribute('role', 'columnheader');
|
|
584
|
+
th.setAttribute('data-col-id', col.colId);
|
|
585
|
+
th.setAttribute('data-col-index', String(index));
|
|
586
|
+
th.setAttribute('tabindex', '0');
|
|
587
|
+
// When a grouped header is present, flat columns must visually span the
|
|
588
|
+
// full header height (group rows + leaf row). The CSS handles the actual
|
|
589
|
+
// translate + height expansion; this class is the hook.
|
|
590
|
+
if (this.displayGroupEngine?.hasGroups && this.displayGroupEngine.isFlat(col.colId)) {
|
|
591
|
+
th.classList.add('pg-th--no-group');
|
|
592
|
+
}
|
|
593
|
+
if (col.headerCssClass)
|
|
594
|
+
th.className += ` ${col.headerCssClass}`;
|
|
595
|
+
toggleClass(th, 'pg-th--sortable', col.sortable !== false);
|
|
596
|
+
toggleClass(th, 'pg-th--sorted', !!col.sortOrder);
|
|
597
|
+
toggleClass(th, 'pg-th--sort-asc', col.sortOrder === 'asc');
|
|
598
|
+
toggleClass(th, 'pg-th--sort-desc', col.sortOrder === 'desc');
|
|
599
|
+
const align = col.textAlign ?? (col.type === 'number' || col.type === 'currency' ? 'right' : 'left');
|
|
600
|
+
if (align !== 'left')
|
|
601
|
+
th.classList.add(`pg-th--align-${align}`);
|
|
602
|
+
if (align === 'right')
|
|
603
|
+
th.classList.add('pg-th--reverse');
|
|
604
|
+
const headerFn = resolveColumnRenderer(col, 'header');
|
|
605
|
+
if (headerFn) {
|
|
606
|
+
const rendered = headerFn({ colDef: col, sortOrder: col.sortOrder ?? null, filterActive: !!col.filterActive, api: null });
|
|
607
|
+
if (typeof rendered === 'string')
|
|
608
|
+
th.innerHTML = rendered;
|
|
609
|
+
else
|
|
610
|
+
th.appendChild(rendered);
|
|
611
|
+
}
|
|
612
|
+
else {
|
|
613
|
+
const content = createDiv('pg-th__content');
|
|
614
|
+
const labelEl = createDiv('pg-th__label');
|
|
615
|
+
labelEl.textContent = col.header;
|
|
616
|
+
labelEl.title = col.header;
|
|
617
|
+
content.appendChild(labelEl);
|
|
618
|
+
if (col.sortable !== false) {
|
|
619
|
+
content.appendChild(this.iconRenderer.render(col.sortOrder === 'asc' ? 'sortAsc' : col.sortOrder === 'desc' ? 'sortDesc' : 'sortNone', { size: 14, className: 'pg-th__sort-icon' }));
|
|
620
|
+
}
|
|
621
|
+
th.appendChild(content);
|
|
622
|
+
}
|
|
623
|
+
// Filter icon — visible on hover; always visible when a filter is active.
|
|
624
|
+
if (col.filterable !== false) {
|
|
625
|
+
const filterBtn = createDiv('pg-th__filter-btn');
|
|
626
|
+
const filterActive = col.filterActive === true;
|
|
627
|
+
if (filterActive)
|
|
628
|
+
filterBtn.classList.add('pg-th__filter-btn--active');
|
|
629
|
+
filterBtn.innerHTML = this.iconRenderer.renderToString(filterActive ? 'filterActive' : 'filter', 14);
|
|
630
|
+
filterBtn.title = 'Filter column';
|
|
631
|
+
filterBtn.setAttribute('tabindex', '0');
|
|
632
|
+
filterBtn.setAttribute('aria-label', `Filter ${col.header}`);
|
|
633
|
+
filterBtn.addEventListener('click', (e) => {
|
|
634
|
+
e.stopPropagation();
|
|
635
|
+
this.openFilterPanelFn?.(col, filterBtn);
|
|
636
|
+
});
|
|
637
|
+
th.appendChild(filterBtn);
|
|
638
|
+
}
|
|
639
|
+
if (options.showColumnMenu !== false) {
|
|
640
|
+
const menuBtn = createDiv('pg-th__menu-btn');
|
|
641
|
+
menuBtn.innerHTML = this.iconRenderer.renderToString('menuHorizontal', 14);
|
|
642
|
+
menuBtn.title = 'Column options';
|
|
643
|
+
menuBtn.setAttribute('tabindex', '0');
|
|
644
|
+
menuBtn.addEventListener('click', (e) => { e.stopPropagation(); this.columnMenu.show(col, menuBtn); });
|
|
645
|
+
th.appendChild(menuBtn);
|
|
646
|
+
}
|
|
647
|
+
// Right-click on the header cell opens the context menu at cursor position.
|
|
648
|
+
th.addEventListener('contextmenu', (e) => {
|
|
649
|
+
e.preventDefault();
|
|
650
|
+
e.stopPropagation();
|
|
651
|
+
this.columnMenu.show(col, th, e.clientX, e.clientY);
|
|
652
|
+
});
|
|
653
|
+
if (col.resizable !== false) {
|
|
654
|
+
const resizeHandle = createDiv('pg-th__resize-handle');
|
|
655
|
+
resizeHandle.innerHTML = '|';
|
|
656
|
+
resizeHandle.addEventListener('mousedown', (e) => { e.preventDefault(); e.stopPropagation(); this.startResize(e, col, th); });
|
|
657
|
+
th.appendChild(resizeHandle);
|
|
658
|
+
}
|
|
659
|
+
if (col.sortable !== false) {
|
|
660
|
+
th.addEventListener('click', (e) => {
|
|
661
|
+
if (e.target.closest('.pg-th__resize-handle, .pg-th__menu-btn, .pg-th__filter-btn'))
|
|
662
|
+
return;
|
|
663
|
+
const next = col.sortOrder === null ? 'asc' : col.sortOrder === 'asc' ? 'desc' : null;
|
|
664
|
+
if (next)
|
|
665
|
+
this.sortEngine.sort(col.colId, col.field, next);
|
|
666
|
+
else
|
|
667
|
+
this.sortEngine.clearSort();
|
|
668
|
+
this.columnModel.setColumnSort(col.colId, next);
|
|
669
|
+
this.updateSortIndicator(col.colId, next);
|
|
670
|
+
this.onAction('sort', col.colId);
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
this.attachColumnDragListeners(th, col, panelColumns, panelRowEl);
|
|
674
|
+
return th;
|
|
675
|
+
}
|
|
676
|
+
buildFilterCell(col) {
|
|
677
|
+
const cell = createDiv('pg-filter-cell');
|
|
678
|
+
cell.setAttribute('data-col-id', col.colId);
|
|
679
|
+
if (col.filterable !== false) {
|
|
680
|
+
const input = document.createElement('input');
|
|
681
|
+
input.type = 'text';
|
|
682
|
+
input.className = 'pg-filter-input';
|
|
683
|
+
input.placeholder = `${col.header}…`;
|
|
684
|
+
input.setAttribute('data-col-id', col.colId);
|
|
685
|
+
input.addEventListener('input', (e) => {
|
|
686
|
+
this.eventBus.emit(GridEventType.COLUMN_FILTER_CHANGED, {
|
|
687
|
+
colId: col.colId, field: col.field, term: e.target.value,
|
|
688
|
+
});
|
|
689
|
+
});
|
|
690
|
+
cell.appendChild(input);
|
|
691
|
+
}
|
|
692
|
+
return cell;
|
|
693
|
+
}
|
|
694
|
+
buildFilterRow(columns, options, isLeft) {
|
|
695
|
+
const row = createDiv('pg-filter-row');
|
|
696
|
+
row.setAttribute('role', 'row');
|
|
697
|
+
if (isLeft) {
|
|
698
|
+
if (options.showCheckboxes)
|
|
699
|
+
row.appendChild(createDiv('pg-filter-cell pg-filter-cell--checkbox'));
|
|
700
|
+
if (options.showSerialNumber)
|
|
701
|
+
row.appendChild(createDiv('pg-filter-cell pg-filter-cell--serial'));
|
|
702
|
+
}
|
|
703
|
+
for (const col of columns)
|
|
704
|
+
row.appendChild(this.buildFilterCell(col));
|
|
705
|
+
return row;
|
|
706
|
+
}
|
|
707
|
+
attachColumnDragListeners(th, col, _panelColumns, panelRowEl) {
|
|
708
|
+
th.addEventListener('mousedown', (e) => {
|
|
709
|
+
if (e.target.closest('.pg-th__resize-handle, .pg-th__menu-btn, .pg-th__filter-btn, .pg-checkbox'))
|
|
710
|
+
return;
|
|
711
|
+
if (col.draggable === false || e.button !== 0)
|
|
712
|
+
return;
|
|
713
|
+
const startX = e.clientX;
|
|
714
|
+
let moved = false;
|
|
715
|
+
const onMoveCheck = (ev) => {
|
|
716
|
+
if (!moved && Math.abs(ev.clientX - startX) > 5) {
|
|
717
|
+
moved = true;
|
|
718
|
+
this.startColumnDrag(col, panelRowEl);
|
|
719
|
+
document.removeEventListener('mousemove', onMoveCheck);
|
|
720
|
+
document.addEventListener('mousemove', this.boundMouseMove);
|
|
721
|
+
document.addEventListener('mouseup', this.boundMouseUp);
|
|
722
|
+
}
|
|
723
|
+
if (moved)
|
|
724
|
+
this.onDragMove(ev.clientX);
|
|
725
|
+
};
|
|
726
|
+
const onUpEarly = () => {
|
|
727
|
+
document.removeEventListener('mousemove', onMoveCheck);
|
|
728
|
+
document.removeEventListener('mouseup', onUpEarly);
|
|
729
|
+
};
|
|
730
|
+
document.addEventListener('mousemove', onMoveCheck);
|
|
731
|
+
document.addEventListener('mouseup', onUpEarly);
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
startColumnDrag(col, panelRowEl) {
|
|
735
|
+
this.draggingColId = col.colId;
|
|
736
|
+
this.isDragging = true;
|
|
737
|
+
this.draggingPanelRowEl = panelRowEl;
|
|
738
|
+
this.draggingIsGroupable = col.groupable === true && this.groupDropZone !== null;
|
|
739
|
+
this.isOverGroupZone = false;
|
|
740
|
+
this.dragIsHideMode = false;
|
|
741
|
+
this.livePanelMoveInProgress = false;
|
|
742
|
+
this.dragSourcePanel = panelRowEl === this.leftHeaderRowEl ? 'left'
|
|
743
|
+
: panelRowEl === this.rightHeaderRowEl ? 'right' : 'center';
|
|
744
|
+
this.dragTargetPanel = this.dragSourcePanel;
|
|
745
|
+
this.dragTargetLocalIdx = -1;
|
|
746
|
+
// Build ghost chip
|
|
747
|
+
const ghost = createDiv('pg-col-drag-ghost');
|
|
748
|
+
const mkIcon = (cls, name) => {
|
|
749
|
+
const s = document.createElement('span');
|
|
750
|
+
s.className = `pg-col-drag-ghost__icon ${cls}`;
|
|
751
|
+
s.innerHTML = this.iconRenderer.renderToString(name, 14);
|
|
752
|
+
return s;
|
|
753
|
+
};
|
|
754
|
+
ghost.appendChild(mkIcon('pg-col-drag-ghost__icon--arrow-left', 'chevronLeft'));
|
|
755
|
+
ghost.appendChild(mkIcon('pg-col-drag-ghost__icon--move', 'drag'));
|
|
756
|
+
ghost.appendChild(mkIcon('pg-col-drag-ghost__icon--ban', 'ban'));
|
|
757
|
+
ghost.appendChild(mkIcon('pg-col-drag-ghost__icon--hide', 'eyeOff'));
|
|
758
|
+
const ghostLabel = document.createElement('span');
|
|
759
|
+
ghostLabel.className = 'pg-col-drag-ghost__label';
|
|
760
|
+
ghostLabel.textContent = col.header;
|
|
761
|
+
ghost.appendChild(ghostLabel);
|
|
762
|
+
ghost.appendChild(mkIcon('pg-col-drag-ghost__icon--arrow-right', 'chevronRight'));
|
|
763
|
+
document.body.appendChild(ghost);
|
|
764
|
+
this.ghostEl = ghost;
|
|
765
|
+
const srcPD = this.panelDragData.find((pd) => pd.panel === this.dragSourcePanel);
|
|
766
|
+
const srcThEl = panelRowEl.querySelector(`[data-col-id="${col.colId}"]`);
|
|
767
|
+
srcThEl?.classList.add('pg-th--dragging');
|
|
768
|
+
const gridEl = panelRowEl.closest('.pg-grid');
|
|
769
|
+
this.draggingGridEl = gridEl;
|
|
770
|
+
// Capture all panel rects before any transforms
|
|
771
|
+
this.panelDragData = this.capturePanelDragData();
|
|
772
|
+
const freshSrcPD = this.panelDragData.find((pd) => pd.panel === this.dragSourcePanel);
|
|
773
|
+
const srcIdx = freshSrcPD?.colIds.indexOf(col.colId) ?? -1;
|
|
774
|
+
this.draggedColWidth = (srcIdx >= 0 && freshSrcPD ? freshSrcPD.rects[srcIdx].width : 0)
|
|
775
|
+
|| srcThEl?.getBoundingClientRect().width || 0;
|
|
776
|
+
void srcPD;
|
|
777
|
+
this.dragStartScrollX = parseFloat(gridEl?.style.getPropertyValue('--pg-scroll-x') ?? '0');
|
|
778
|
+
const centerPD = this.panelDragData.find((pd) => pd.panel === 'center');
|
|
779
|
+
this.centerPanelRect = centerPD?.bounds ?? null;
|
|
780
|
+
const styleEl = document.createElement('style');
|
|
781
|
+
styleEl.setAttribute('data-pg-drag', '');
|
|
782
|
+
document.head.appendChild(styleEl);
|
|
783
|
+
this.dragStyleEl = styleEl;
|
|
784
|
+
gridEl?.classList.add('pg-grid--col-dragging');
|
|
785
|
+
// Suppress the 180 ms drag-shift transition while the virtual column range
|
|
786
|
+
// expands to all columns on the first performRender after drag start.
|
|
787
|
+
// Without this guard, newly-added body cells animate in from transform:0.
|
|
788
|
+
// The class is removed 2 frames later so smooth transitions resume for
|
|
789
|
+
// ordinary mouse movement.
|
|
790
|
+
gridEl?.classList.add('pg-grid--col-autoscrolling');
|
|
791
|
+
requestAnimationFrame(() => requestAnimationFrame(() => {
|
|
792
|
+
if (this.isDragging)
|
|
793
|
+
this.draggingGridEl?.classList.remove('pg-grid--col-autoscrolling');
|
|
794
|
+
}));
|
|
795
|
+
document.body.style.cursor = 'grabbing';
|
|
796
|
+
document.body.style.userSelect = 'none';
|
|
797
|
+
}
|
|
798
|
+
// ─── Live cross-panel move ─────────────────────────────────────────────────
|
|
799
|
+
/**
|
|
800
|
+
* When the cursor crosses into a new panel:
|
|
801
|
+
* 1. Immediately DOM-move the source TH into the target panel header row
|
|
802
|
+
* 2. Call moveAndPin() so body cells and panel widths update via the guarded re-render
|
|
803
|
+
* 3. After 2 frames (re-render complete), re-capture rects and continue drag
|
|
804
|
+
*/
|
|
805
|
+
moveToPanelLive(newPanel, insertIdx) {
|
|
806
|
+
if (this.livePanelMoveInProgress)
|
|
807
|
+
return;
|
|
808
|
+
this.livePanelMoveInProgress = true;
|
|
809
|
+
const colId = this.draggingColId;
|
|
810
|
+
const targetPD = this.panelDragData.find((pd) => pd.panel === newPanel);
|
|
811
|
+
const insertBeforeColId = targetPD?.colIds[insertIdx] ?? null;
|
|
812
|
+
const newPin = newPanel === 'left' ? 'left' : newPanel === 'right' ? 'right' : null;
|
|
813
|
+
// Step 1: immediately DOM-move the TH for instant visual feedback in the header
|
|
814
|
+
const targetRowEl = newPanel === 'left' ? this.leftHeaderRowEl
|
|
815
|
+
: newPanel === 'right' ? this.rightHeaderRowEl
|
|
816
|
+
: this.centerHeaderRowEl;
|
|
817
|
+
const srcThEl = this.draggingGridEl?.querySelector(`.pg-th[data-col-id="${colId}"]`);
|
|
818
|
+
if (srcThEl && targetRowEl) {
|
|
819
|
+
const realThs = Array.from(targetRowEl.querySelectorAll('.pg-th[data-col-id]'));
|
|
820
|
+
const refEl = insertIdx < realThs.length ? realThs[insertIdx] : null;
|
|
821
|
+
if (refEl)
|
|
822
|
+
targetRowEl.insertBefore(srcThEl, refEl);
|
|
823
|
+
else {
|
|
824
|
+
const lastTh = realThs[realThs.length - 1];
|
|
825
|
+
if (lastTh?.nextSibling)
|
|
826
|
+
targetRowEl.insertBefore(srcThEl, lastTh.nextSibling);
|
|
827
|
+
else
|
|
828
|
+
targetRowEl.appendChild(srcThEl);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
// Clear any drag transforms during the transition
|
|
832
|
+
if (this.dragStyleEl)
|
|
833
|
+
this.dragStyleEl.textContent = '';
|
|
834
|
+
// Update drag source state immediately
|
|
835
|
+
this.dragSourcePanel = newPanel;
|
|
836
|
+
this.dragTargetPanel = newPanel;
|
|
837
|
+
this.dragTargetLocalIdx = -1;
|
|
838
|
+
// Step 2: update column model → body cells re-render + panel width CSS var updates
|
|
839
|
+
// The grid-renderer columns watcher checks isDraggingCol and skips header.destroy()
|
|
840
|
+
this.columnModel.moveAndPin(colId, newPin, insertBeforeColId);
|
|
841
|
+
// Step 3: after re-render (2 frames), re-capture rects and re-apply dragging state
|
|
842
|
+
requestAnimationFrame(() => {
|
|
843
|
+
requestAnimationFrame(() => {
|
|
844
|
+
if (!this.isDragging || this.draggingColId !== colId) {
|
|
845
|
+
this.livePanelMoveInProgress = false;
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
// Re-apply pg-th--dragging (the TH may have been rebuilt by updateCenterVisibleCols)
|
|
849
|
+
this.draggingGridEl?.querySelector(`.pg-th[data-col-id="${colId}"]`)
|
|
850
|
+
?.classList.add('pg-th--dragging');
|
|
851
|
+
// Re-capture rects with the new panel layout
|
|
852
|
+
this.panelDragData = this.capturePanelDragData();
|
|
853
|
+
this.dragStartScrollX = parseFloat(this.draggingGridEl?.style.getPropertyValue('--pg-scroll-x') ?? '0');
|
|
854
|
+
const centerPD = this.panelDragData.find((pd) => pd.panel === 'center');
|
|
855
|
+
this.centerPanelRect = centerPD?.bounds ?? null;
|
|
856
|
+
this.livePanelMoveInProgress = false;
|
|
857
|
+
});
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
updateAutoScroll(clientX) {
|
|
861
|
+
if (!this.centerPanelRect || !this.scrollByX)
|
|
862
|
+
return;
|
|
863
|
+
const EDGE = 80;
|
|
864
|
+
const { left, right } = this.centerPanelRect;
|
|
865
|
+
let speed = 0;
|
|
866
|
+
if (clientX < left + EDGE) {
|
|
867
|
+
const raw = -Math.round(((left + EDGE - clientX) / EDGE) * 10);
|
|
868
|
+
speed = (this.canScrollX?.(-1) ?? true) ? raw : 0;
|
|
869
|
+
}
|
|
870
|
+
else if (clientX > right - EDGE) {
|
|
871
|
+
const raw = Math.round(((clientX - right + EDGE) / EDGE) * 10);
|
|
872
|
+
speed = (this.canScrollX?.(1) ?? true) ? raw : 0;
|
|
873
|
+
}
|
|
874
|
+
const wasScrolling = this.autoScrollSpeed !== 0;
|
|
875
|
+
this.autoScrollSpeed = speed;
|
|
876
|
+
if (speed !== 0 && !wasScrolling)
|
|
877
|
+
this.autoScrollRAF = requestAnimationFrame(this.tickAutoScroll);
|
|
878
|
+
else if (speed === 0 && wasScrolling)
|
|
879
|
+
this.stopAutoScroll();
|
|
880
|
+
this.ghostEl?.classList.toggle('pg-col-drag-ghost--scroll-left', speed < 0);
|
|
881
|
+
this.ghostEl?.classList.toggle('pg-col-drag-ghost--scroll-right', speed > 0);
|
|
882
|
+
}
|
|
883
|
+
stopAutoScroll() {
|
|
884
|
+
cancelAnimationFrame(this.autoScrollRAF);
|
|
885
|
+
this.autoScrollRAF = 0;
|
|
886
|
+
this.autoScrollSpeed = 0;
|
|
887
|
+
if (this.isDragging && !this.livePanelMoveInProgress && this.dragStyleEl) {
|
|
888
|
+
// Temporarily suppress all column transitions while resetting the drag baseline.
|
|
889
|
+
// Without this guard, sibling columns animate back to zero when their transforms
|
|
890
|
+
// are cleared, then re-animate forward — a visible snap-and-reanimate sequence.
|
|
891
|
+
this.draggingGridEl?.classList.add('pg-grid--col-autoscrolling');
|
|
892
|
+
this.refreshDragAfterScroll();
|
|
893
|
+
this.draggingGridEl?.classList.remove('pg-grid--col-autoscrolling');
|
|
894
|
+
}
|
|
895
|
+
this.ghostEl?.classList.remove('pg-col-drag-ghost--scroll-left', 'pg-col-drag-ghost--scroll-right');
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Re-captures header column rects and re-applies drag transforms after each
|
|
899
|
+
* auto-scroll step. Runs 2 animation frames after the scroll so the grid's
|
|
900
|
+
* virtual column render (`updateCenterVisibleCols`) has completed and the DOM
|
|
901
|
+
* reflects any newly visible columns before `getBoundingClientRect` is called.
|
|
902
|
+
*
|
|
903
|
+
* This mirrors the 2-frame pattern used by `moveToPanelLive` and ensures the
|
|
904
|
+
* dragged-column ghost and sibling transforms stay accurate even when the
|
|
905
|
+
* mouse is stationary at the viewport edge while auto-scroll is running.
|
|
906
|
+
*/
|
|
907
|
+
refreshDragAfterScroll() {
|
|
908
|
+
if (!this.isDragging || this.livePanelMoveInProgress)
|
|
909
|
+
return;
|
|
910
|
+
// CRITICAL: clear drag transforms before calling getBoundingClientRect.
|
|
911
|
+
// capturePanelDragData reads viewport positions via getBoundingClientRect.
|
|
912
|
+
// If dragStyleEl still has transforms applied, the captured rects include
|
|
913
|
+
// those offsets — the next onDragMove then compounds transforms on top of
|
|
914
|
+
// already-transformed positions, creating an oscillating feedback loop that
|
|
915
|
+
// causes blinking and column misalignment.
|
|
916
|
+
// getBoundingClientRect forces a synchronous layout flush, so clearing first
|
|
917
|
+
// and recapturing immediately gives clean baseline positions. The clear and
|
|
918
|
+
// re-apply are both in the same JS task, so the browser never paints a
|
|
919
|
+
// transform-less frame.
|
|
920
|
+
if (this.dragStyleEl)
|
|
921
|
+
this.dragStyleEl.textContent = '';
|
|
922
|
+
// Re-apply dragging class — updateCenterVisibleCols may have rebuilt the TH element.
|
|
923
|
+
this.draggingGridEl
|
|
924
|
+
?.querySelector(`.pg-th[data-col-id="${this.draggingColId}"]`)
|
|
925
|
+
?.classList.add('pg-th--dragging');
|
|
926
|
+
// Re-capture clean baseline rects (no transforms) for all currently rendered columns.
|
|
927
|
+
this.panelDragData = this.capturePanelDragData();
|
|
928
|
+
this.dragStartScrollX = parseFloat(this.draggingGridEl?.style.getPropertyValue('--pg-scroll-x') ?? '0');
|
|
929
|
+
const centerPD = this.panelDragData.find((pd) => pd.panel === 'center');
|
|
930
|
+
this.centerPanelRect = centerPD?.bounds ?? null;
|
|
931
|
+
// Re-apply correct transforms from the fresh baseline rects.
|
|
932
|
+
this.onDragMove(this.lastDragClientX);
|
|
933
|
+
}
|
|
934
|
+
// ─── Live group row preview (DisplayGroupEngine) ─────────────────────────
|
|
935
|
+
/**
|
|
936
|
+
* Rebuild the group header rows for one panel using a new (possibly preview)
|
|
937
|
+
* column order. Safe to call during drag — only the group row `<div>`s are
|
|
938
|
+
* replaced; the leaf row `<tr>` that carries the live drag element is untouched.
|
|
939
|
+
*
|
|
940
|
+
* @param panel - Which panel's group rows to refresh.
|
|
941
|
+
* @param cols - Ordered visible columns for this panel (preview or committed).
|
|
942
|
+
*/
|
|
943
|
+
rebuildGroupRowsForPanel(panel, cols) {
|
|
944
|
+
if (!this.displayGroupEngine?.hasGroups)
|
|
945
|
+
return;
|
|
946
|
+
const leafRowEl = panel === 'left' ? this.leftHeaderRowEl
|
|
947
|
+
: panel === 'right' ? this.rightHeaderRowEl
|
|
948
|
+
: this.centerHeaderRowEl;
|
|
949
|
+
if (!leafRowEl)
|
|
950
|
+
return;
|
|
951
|
+
const container = leafRowEl.parentElement;
|
|
952
|
+
if (!container)
|
|
953
|
+
return;
|
|
954
|
+
const oldRows = panel === 'left' ? this.leftGroupRowEls
|
|
955
|
+
: panel === 'right' ? this.rightGroupRowEls
|
|
956
|
+
: this.centerGroupRowEls;
|
|
957
|
+
for (const el of oldRows)
|
|
958
|
+
el.remove();
|
|
959
|
+
const engine = this.displayGroupEngine;
|
|
960
|
+
const dragHandler = engine.getDragHandler();
|
|
961
|
+
const cellOpts = {
|
|
962
|
+
rowHeight: this.lastGroupRowHeight,
|
|
963
|
+
onCollapseToggle: (id) => this.onGroupToggleFn?.(id),
|
|
964
|
+
onGroupResize: (id, w) => this.onGroupResizeFn?.(id, w),
|
|
965
|
+
onGroupHeaderMouseDown: dragHandler
|
|
966
|
+
? (e, node, el) => dragHandler.onHeaderMouseDown(e, node, el)
|
|
967
|
+
: undefined,
|
|
968
|
+
didJustDragFn: dragHandler ? () => dragHandler.didJustDrag : undefined,
|
|
969
|
+
onGroupContextMenu: (e, node, el) => this.groupContextMenu?.show(node, el, e.clientX, e.clientY),
|
|
970
|
+
};
|
|
971
|
+
const newRows = engine.headerBuilder.buildGroupRows(engine.buildTree(cols), cellOpts);
|
|
972
|
+
for (const el of newRows)
|
|
973
|
+
container.insertBefore(el, leafRowEl);
|
|
974
|
+
if (panel === 'left')
|
|
975
|
+
this.leftGroupRowEls = newRows;
|
|
976
|
+
else if (panel === 'right')
|
|
977
|
+
this.rightGroupRowEls = newRows;
|
|
978
|
+
else
|
|
979
|
+
this.centerGroupRowEls = newRows;
|
|
980
|
+
// Keep the flat-column height variable in sync whenever group rows change.
|
|
981
|
+
container.style.setProperty('--pg-group-rows-count', String(newRows.length));
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* Compute the preview column order for the drag source panel (same-panel drag)
|
|
985
|
+
* and rebuild its group rows.
|
|
986
|
+
*
|
|
987
|
+
* Called from `onDragMove` whenever the effective drop slot changes. Always
|
|
988
|
+
* derives the preview from the captured `panelDragData` colIds so the
|
|
989
|
+
* `LogicalGroupRegistry` sees the exact order the column would land in on drop.
|
|
990
|
+
*
|
|
991
|
+
* @param targetIdx - Effective slot index the dragged column is hovering over.
|
|
992
|
+
* @param sourceIdx - Original slot index of the dragged column in its panel.
|
|
993
|
+
* @param pd - Panel drag data for the source panel.
|
|
994
|
+
*/
|
|
995
|
+
rebuildGroupRowsWithPreview(targetIdx, sourceIdx, pd) {
|
|
996
|
+
// Build preview colId order: move dragged column from sourceIdx to targetIdx.
|
|
997
|
+
const previewIds = [...pd.colIds];
|
|
998
|
+
const [movedId] = previewIds.splice(sourceIdx, 1);
|
|
999
|
+
previewIds.splice(targetIdx, 0, movedId);
|
|
1000
|
+
// Map to ColumnDef[] using store (live source of truth for metadata).
|
|
1001
|
+
const allCols = this.store.get('columns');
|
|
1002
|
+
const colMap = new Map(allCols.map((c) => [c.colId, c]));
|
|
1003
|
+
const previewCols = previewIds
|
|
1004
|
+
.map((id) => colMap.get(id))
|
|
1005
|
+
.filter((c) => c !== undefined);
|
|
1006
|
+
this.rebuildGroupRowsForPanel(this.dragSourcePanel, previewCols);
|
|
1007
|
+
}
|
|
1008
|
+
// ─── Drag move ────────────────────────────────────────────────────────────
|
|
1009
|
+
onDragMove(clientX) {
|
|
1010
|
+
if (!this.isDragging || !this.draggingColId || !this.panelDragData.length || !this.dragStyleEl)
|
|
1011
|
+
return;
|
|
1012
|
+
if (this.livePanelMoveInProgress) {
|
|
1013
|
+
this.dragStyleEl.textContent = '';
|
|
1014
|
+
return;
|
|
1015
|
+
}
|
|
1016
|
+
// Which panel is the cursor over?
|
|
1017
|
+
let targetPD = this.panelDragData.find((pd) => {
|
|
1018
|
+
if (!pd.bounds)
|
|
1019
|
+
return false;
|
|
1020
|
+
return clientX >= pd.bounds.left && clientX <= pd.bounds.right;
|
|
1021
|
+
});
|
|
1022
|
+
if (!targetPD)
|
|
1023
|
+
targetPD = this.panelDragData.find((pd) => pd.panel === this.dragSourcePanel);
|
|
1024
|
+
if (!targetPD)
|
|
1025
|
+
return;
|
|
1026
|
+
this.dragTargetPanel = targetPD.panel;
|
|
1027
|
+
const crossPanel = targetPD.panel !== this.dragSourcePanel;
|
|
1028
|
+
// Scroll correction for center panel
|
|
1029
|
+
const scrollDelta = targetPD.panel === 'center'
|
|
1030
|
+
? parseFloat(this.draggingGridEl?.style.getPropertyValue('--pg-scroll-x') ?? '0') - this.dragStartScrollX
|
|
1031
|
+
: 0;
|
|
1032
|
+
const { rects: tRects, colIds: tIds } = targetPD;
|
|
1033
|
+
const srcPD = this.panelDragData.find((pd) => pd.panel === this.dragSourcePanel);
|
|
1034
|
+
const sourceIdxInPanel = srcPD.colIds.indexOf(this.draggingColId);
|
|
1035
|
+
if (crossPanel) {
|
|
1036
|
+
// Zone-entry: insert before the first column whose right edge the cursor hasn't passed
|
|
1037
|
+
let insertIdx = tIds.length;
|
|
1038
|
+
for (let i = 0; i < tRects.length; i++) {
|
|
1039
|
+
if (clientX < tRects[i].right + scrollDelta) {
|
|
1040
|
+
insertIdx = i;
|
|
1041
|
+
break;
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
this.moveToPanelLive(targetPD.panel, insertIdx);
|
|
1045
|
+
this.dragStyleEl.textContent = '';
|
|
1046
|
+
return;
|
|
1047
|
+
}
|
|
1048
|
+
// Same-panel: find which non-source column zone the cursor is directly over
|
|
1049
|
+
let effectiveTarget = sourceIdxInPanel;
|
|
1050
|
+
for (let i = 0; i < tRects.length; i++) {
|
|
1051
|
+
if (i === sourceIdxInPanel)
|
|
1052
|
+
continue;
|
|
1053
|
+
const colLeft = tRects[i].left + scrollDelta;
|
|
1054
|
+
const colRight = tRects[i].right + scrollDelta;
|
|
1055
|
+
if (clientX >= colLeft && clientX < colRight) {
|
|
1056
|
+
effectiveTarget = i;
|
|
1057
|
+
break;
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
// Cursor before all columns: snap to leftmost non-source column
|
|
1061
|
+
if (effectiveTarget === sourceIdxInPanel && tRects.length > 0 && clientX < tRects[0].left + scrollDelta) {
|
|
1062
|
+
effectiveTarget = sourceIdxInPanel === 0 ? 1 : 0;
|
|
1063
|
+
}
|
|
1064
|
+
// Cursor after all columns: snap to rightmost non-source column
|
|
1065
|
+
if (effectiveTarget === sourceIdxInPanel && tRects.length > 0 && clientX >= tRects[tRects.length - 1].right + scrollDelta) {
|
|
1066
|
+
const lastIdx = tRects.length - 1;
|
|
1067
|
+
effectiveTarget = sourceIdxInPanel === lastIdx ? lastIdx - 1 : lastIdx;
|
|
1068
|
+
}
|
|
1069
|
+
const prevSlot = this.dragTargetLocalIdx;
|
|
1070
|
+
this.dragTargetLocalIdx = effectiveTarget;
|
|
1071
|
+
// Rebuild group rows whenever the effective drop slot changes so group spans
|
|
1072
|
+
// reflect the pending position in real time — identical to AG Grid behaviour.
|
|
1073
|
+
if (this.displayGroupEngine?.hasGroups && effectiveTarget !== prevSlot) {
|
|
1074
|
+
this.rebuildGroupRowsWithPreview(effectiveTarget, sourceIdxInPanel, srcPD);
|
|
1075
|
+
}
|
|
1076
|
+
// Same-panel: apply CSS transforms
|
|
1077
|
+
const gridId = this.draggingGridEl?.getAttribute('data-photon-grid-id') ?? '';
|
|
1078
|
+
const scope = gridId ? `[data-photon-grid-id="${gridId}"] ` : '';
|
|
1079
|
+
let css = '';
|
|
1080
|
+
if (effectiveTarget === sourceIdxInPanel) {
|
|
1081
|
+
this.dragStyleEl.textContent = '';
|
|
1082
|
+
return;
|
|
1083
|
+
}
|
|
1084
|
+
const srcRect = srcPD.rects[sourceIdxInPanel];
|
|
1085
|
+
const tgtRect = tRects[effectiveTarget];
|
|
1086
|
+
const srcOffset = effectiveTarget > sourceIdxInPanel ? tgtRect.right - srcRect.right : tgtRect.left - srcRect.left;
|
|
1087
|
+
css += `${scope}[data-col-id="${tIds[sourceIdxInPanel]}"] { --pg-drag-x: ${srcOffset}px; z-index: 10; position: relative; transition: none; }\n`;
|
|
1088
|
+
for (let i = 0; i < tRects.length; i++) {
|
|
1089
|
+
if (i === sourceIdxInPanel)
|
|
1090
|
+
continue;
|
|
1091
|
+
let offset = 0;
|
|
1092
|
+
if (effectiveTarget > sourceIdxInPanel && i > sourceIdxInPanel && i <= effectiveTarget)
|
|
1093
|
+
offset = -this.draggedColWidth;
|
|
1094
|
+
else if (effectiveTarget < sourceIdxInPanel && i >= effectiveTarget && i < sourceIdxInPanel)
|
|
1095
|
+
offset = this.draggedColWidth;
|
|
1096
|
+
if (offset !== 0)
|
|
1097
|
+
css += `${scope}[data-col-id="${tIds[i]}"] { --pg-drag-x: ${offset}px; }\n`;
|
|
1098
|
+
}
|
|
1099
|
+
this.dragStyleEl.textContent = css;
|
|
1100
|
+
}
|
|
1101
|
+
onGlobalMouseMove(e) {
|
|
1102
|
+
if (!this.isDragging || !this.draggingPanelRowEl)
|
|
1103
|
+
return;
|
|
1104
|
+
if (this.ghostEl) {
|
|
1105
|
+
this.ghostEl.style.left = `${e.clientX + 14}px`;
|
|
1106
|
+
this.ghostEl.style.top = `${e.clientY}px`;
|
|
1107
|
+
}
|
|
1108
|
+
// Outside grid → hide-column mode
|
|
1109
|
+
const gridBounds = this.draggingGridEl?.getBoundingClientRect();
|
|
1110
|
+
const isOutside = !!gridBounds && (e.clientX < gridBounds.left || e.clientX > gridBounds.right ||
|
|
1111
|
+
e.clientY < gridBounds.top || e.clientY > gridBounds.bottom);
|
|
1112
|
+
if (isOutside) {
|
|
1113
|
+
this.dragIsHideMode = true;
|
|
1114
|
+
this.stopAutoScroll();
|
|
1115
|
+
this.ghostEl?.classList.add('pg-col-drag-ghost--hide');
|
|
1116
|
+
this.ghostEl?.classList.remove('pg-col-drag-ghost--no-drop', 'pg-col-drag-ghost--scroll-left', 'pg-col-drag-ghost--scroll-right');
|
|
1117
|
+
if (this.dragStyleEl)
|
|
1118
|
+
this.dragStyleEl.textContent = '';
|
|
1119
|
+
return;
|
|
1120
|
+
}
|
|
1121
|
+
this.dragIsHideMode = false;
|
|
1122
|
+
this.ghostEl?.classList.remove('pg-col-drag-ghost--hide');
|
|
1123
|
+
// Group zone
|
|
1124
|
+
const overGroupZone = this.groupDropZone?.isOver(e.clientX, e.clientY) ?? false;
|
|
1125
|
+
if (overGroupZone && !this.draggingIsGroupable) {
|
|
1126
|
+
this.stopAutoScroll();
|
|
1127
|
+
this.ghostEl?.classList.add('pg-col-drag-ghost--no-drop');
|
|
1128
|
+
document.body.style.cursor = 'no-drop';
|
|
1129
|
+
if (this.dragStyleEl)
|
|
1130
|
+
this.dragStyleEl.textContent = '';
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
1133
|
+
this.ghostEl?.classList.remove('pg-col-drag-ghost--no-drop');
|
|
1134
|
+
document.body.style.cursor = 'grabbing';
|
|
1135
|
+
if (this.draggingIsGroupable && this.groupDropZone) {
|
|
1136
|
+
this.groupDropZone.highlight(overGroupZone);
|
|
1137
|
+
this.isOverGroupZone = overGroupZone;
|
|
1138
|
+
if (overGroupZone) {
|
|
1139
|
+
this.stopAutoScroll();
|
|
1140
|
+
if (this.dragStyleEl)
|
|
1141
|
+
this.dragStyleEl.textContent = '';
|
|
1142
|
+
return;
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
this.lastDragClientX = e.clientX;
|
|
1146
|
+
this.updateAutoScroll(e.clientX);
|
|
1147
|
+
this.onDragMove(e.clientX);
|
|
1148
|
+
}
|
|
1149
|
+
onGlobalMouseUp(_e) {
|
|
1150
|
+
if (!this.isDragging) {
|
|
1151
|
+
this.cleanupDrag();
|
|
1152
|
+
return;
|
|
1153
|
+
}
|
|
1154
|
+
const colId = this.draggingColId;
|
|
1155
|
+
if (!colId) {
|
|
1156
|
+
this.cleanupDrag();
|
|
1157
|
+
return;
|
|
1158
|
+
}
|
|
1159
|
+
// Capture state before cleanup resets everything
|
|
1160
|
+
const sourcePanel = this.dragSourcePanel;
|
|
1161
|
+
const targetPanel = this.dragTargetPanel;
|
|
1162
|
+
const targetLocalIdx = this.dragTargetLocalIdx;
|
|
1163
|
+
const targetPD = this.panelDragData.find((pd) => pd.panel === targetPanel);
|
|
1164
|
+
const srcPD = this.panelDragData.find((pd) => pd.panel === sourcePanel);
|
|
1165
|
+
const srcLocalIdx = srcPD?.colIds.indexOf(colId) ?? -1;
|
|
1166
|
+
const isHide = this.dragIsHideMode;
|
|
1167
|
+
const isGroup = this.draggingIsGroupable && this.isOverGroupZone;
|
|
1168
|
+
// Capture the element under the cursor BEFORE cleanupDrag removes the ghost —
|
|
1169
|
+
// this is used below to detect drops on group header cells.
|
|
1170
|
+
const dropEl = document.elementFromPoint(_e.clientX, _e.clientY);
|
|
1171
|
+
const droppedOnGroupId = dropEl?.closest('[data-group-id]')
|
|
1172
|
+
?.getAttribute('data-group-id') ?? null;
|
|
1173
|
+
// Cleanup first → sets isDragging = false → next model change triggers full header rebuild
|
|
1174
|
+
this.cleanupDrag();
|
|
1175
|
+
if (isHide) {
|
|
1176
|
+
this.columnModel.setColumnVisible(colId, false);
|
|
1177
|
+
return;
|
|
1178
|
+
}
|
|
1179
|
+
if (isGroup && this.groupDropZone) {
|
|
1180
|
+
this.groupDropZone.dropColumn(colId);
|
|
1181
|
+
return;
|
|
1182
|
+
}
|
|
1183
|
+
// When a grouped leaf is dropped onto a DIFFERENT group's header cell, create a
|
|
1184
|
+
// solo clone group rather than doing a plain column reorder. Dropping on the
|
|
1185
|
+
// leaf's own parent group header is treated as a no-op clone check (no action).
|
|
1186
|
+
if (droppedOnGroupId && this.groupModel && this.groupDragHandler) {
|
|
1187
|
+
const parentGroup = this.groupModel.getParent(colId);
|
|
1188
|
+
if (parentGroup) {
|
|
1189
|
+
// Dropped on its own parent → leave in place (within-group reorder already done)
|
|
1190
|
+
if (droppedOnGroupId !== parentGroup.groupId) {
|
|
1191
|
+
this.groupDragHandler.createLeafClone(colId, droppedOnGroupId);
|
|
1192
|
+
return;
|
|
1193
|
+
}
|
|
1194
|
+
return; // same parent — no clone needed
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
if (sourcePanel === targetPanel) {
|
|
1198
|
+
// Same-panel (or live-moved, then fine-tuned within new panel)
|
|
1199
|
+
const visibleCols = this.columnModel.getVisibleColumns();
|
|
1200
|
+
const globalFrom = visibleCols.findIndex((c) => c.colId === colId);
|
|
1201
|
+
if (globalFrom === -1)
|
|
1202
|
+
return;
|
|
1203
|
+
const targetColId = targetLocalIdx !== -1 && targetPD ? targetPD.colIds[targetLocalIdx] : null;
|
|
1204
|
+
const globalTo = targetColId ? visibleCols.findIndex((c) => c.colId === targetColId) : globalFrom;
|
|
1205
|
+
// Always call moveColumn to trigger the full header rebuild (even if same position)
|
|
1206
|
+
this.columnModel.moveColumn(globalFrom, globalTo !== -1 ? globalTo : globalFrom);
|
|
1207
|
+
// If the leaf left its parent group's contiguous span, extract it into a
|
|
1208
|
+
// solo clone group so a group header appears at the new position.
|
|
1209
|
+
if (this.groupModel && this.groupDragHandler) {
|
|
1210
|
+
const parent = this.groupModel.getParent(colId);
|
|
1211
|
+
if (parent) {
|
|
1212
|
+
const updatedCols = this.store.get('columns').filter((c) => c.visible !== false);
|
|
1213
|
+
const newIdx = updatedCols.findIndex((c) => c.colId === colId);
|
|
1214
|
+
if (newIdx !== -1 && this.isLeafOutsideGroup(colId, newIdx, updatedCols)) {
|
|
1215
|
+
// insertBeforeId: the column that now follows the leaf in the flat list
|
|
1216
|
+
const insertBeforeId = updatedCols[newIdx + 1]?.colId ?? null;
|
|
1217
|
+
this.groupDragHandler.extractLeafToSoloGroup(colId, insertBeforeId);
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
else {
|
|
1223
|
+
// Cursor dropped in a different panel than dragSourcePanel (fast move before live rects update)
|
|
1224
|
+
const targetPin = targetPanel === 'left' ? 'left' : targetPanel === 'right' ? 'right' : null;
|
|
1225
|
+
const insertBeforeColId = targetPD ? (targetPD.colIds[targetLocalIdx] ?? null) : null;
|
|
1226
|
+
this.columnModel.moveAndPin(colId, targetPin, insertBeforeColId);
|
|
1227
|
+
// Moving a grouped leaf cross-panel always places it outside its original
|
|
1228
|
+
// group — create a solo clone group in the target panel so the group
|
|
1229
|
+
// header follows the column.
|
|
1230
|
+
if (this.groupModel && this.groupDragHandler) {
|
|
1231
|
+
const parent = this.groupModel.getParent(colId);
|
|
1232
|
+
if (parent) {
|
|
1233
|
+
this.groupDragHandler.extractLeafToSoloGroup(colId, insertBeforeColId);
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
void srcLocalIdx;
|
|
1238
|
+
}
|
|
1239
|
+
cleanupDrag() {
|
|
1240
|
+
this.isDragging = false;
|
|
1241
|
+
this.livePanelMoveInProgress = false;
|
|
1242
|
+
this.draggingIsGroupable = false;
|
|
1243
|
+
this.isOverGroupZone = false;
|
|
1244
|
+
this.dragIsHideMode = false;
|
|
1245
|
+
this.groupDropZone?.highlight(false);
|
|
1246
|
+
this.draggingPanelRowEl?.querySelector('.pg-th--dragging')?.classList.remove('pg-th--dragging');
|
|
1247
|
+
this.ghostEl?.remove();
|
|
1248
|
+
this.ghostEl = null;
|
|
1249
|
+
this.dragStyleEl?.remove();
|
|
1250
|
+
this.dragStyleEl = null;
|
|
1251
|
+
this.draggingGridEl?.classList.remove('pg-grid--col-dragging', 'pg-grid--col-autoscrolling');
|
|
1252
|
+
this.draggingGridEl = null;
|
|
1253
|
+
this.draggedColWidth = 0;
|
|
1254
|
+
this.panelDragData = [];
|
|
1255
|
+
this.dragStartScrollX = 0;
|
|
1256
|
+
this.stopAutoScroll();
|
|
1257
|
+
this.centerPanelRect = null;
|
|
1258
|
+
this.draggingColId = null;
|
|
1259
|
+
this.dragTargetLocalIdx = -1;
|
|
1260
|
+
this.draggingPanelRowEl = null;
|
|
1261
|
+
document.body.style.cursor = '';
|
|
1262
|
+
document.body.style.userSelect = '';
|
|
1263
|
+
document.removeEventListener('mousemove', this.boundMouseMove);
|
|
1264
|
+
document.removeEventListener('mouseup', this.boundMouseUp);
|
|
1265
|
+
}
|
|
1266
|
+
startResize(e, col, thEl) {
|
|
1267
|
+
const startX = e.clientX;
|
|
1268
|
+
const startWidth = this.colStyles.getWidth(col.colId);
|
|
1269
|
+
thEl.classList.add('pg-th--resizing');
|
|
1270
|
+
document.body.style.cursor = 'col-resize';
|
|
1271
|
+
document.body.style.userSelect = 'none';
|
|
1272
|
+
this._isResizingColumn = true;
|
|
1273
|
+
const onMove = (ev) => {
|
|
1274
|
+
this.colStyles.setWidth(col.colId, Math.max(col.minWidth ?? 60, startWidth + (ev.clientX - startX)));
|
|
1275
|
+
this.onResizeCb?.();
|
|
1276
|
+
};
|
|
1277
|
+
const onUp = (ev) => {
|
|
1278
|
+
// Clear the flag BEFORE setColumnWidth fires an event so the final
|
|
1279
|
+
// post-resize render calls renderRows normally and the body is correct.
|
|
1280
|
+
this._isResizingColumn = false;
|
|
1281
|
+
const newWidth = Math.max(col.minWidth ?? 60, startWidth + (ev.clientX - startX));
|
|
1282
|
+
this.colStyles.setWidth(col.colId, newWidth);
|
|
1283
|
+
this.columnModel.setColumnWidth(col.colId, newWidth, true);
|
|
1284
|
+
thEl.classList.remove('pg-th--resizing');
|
|
1285
|
+
document.body.style.cursor = '';
|
|
1286
|
+
document.body.style.userSelect = '';
|
|
1287
|
+
document.removeEventListener('mousemove', onMove);
|
|
1288
|
+
document.removeEventListener('mouseup', onUp);
|
|
1289
|
+
};
|
|
1290
|
+
document.addEventListener('mousemove', onMove);
|
|
1291
|
+
document.addEventListener('mouseup', onUp);
|
|
1292
|
+
}
|
|
1293
|
+
/**
|
|
1294
|
+
* Returns `true` when `colId` (at its new position `newIdx` in the visible
|
|
1295
|
+
* columns array) is no longer adjacent to any sibling leaf from its parent
|
|
1296
|
+
* group — meaning it has been dragged outside the group's contiguous span.
|
|
1297
|
+
*
|
|
1298
|
+
* @param colId - The moved leaf column.
|
|
1299
|
+
* @param newIdx - Its new index in `cols`.
|
|
1300
|
+
* @param cols - Current flat visible-column array (after the move).
|
|
1301
|
+
*/
|
|
1302
|
+
isLeafOutsideGroup(colId, newIdx, cols) {
|
|
1303
|
+
if (!this.groupModel)
|
|
1304
|
+
return false;
|
|
1305
|
+
const parent = this.groupModel.getParent(colId);
|
|
1306
|
+
if (!parent)
|
|
1307
|
+
return false;
|
|
1308
|
+
const siblings = new Set(this.groupModel.getLeavesInGroup(parent.groupId)
|
|
1309
|
+
.map((l) => l.colId)
|
|
1310
|
+
.filter((id) => id !== colId));
|
|
1311
|
+
const left = cols[newIdx - 1];
|
|
1312
|
+
const right = cols[newIdx + 1];
|
|
1313
|
+
return !(left && siblings.has(left.colId)) && !(right && siblings.has(right.colId));
|
|
1314
|
+
}
|
|
1315
|
+
onAction(action, colId) {
|
|
1316
|
+
this.eventBus.emit(GridEventType.COLUMNS_STATE_CHANGED, {
|
|
1317
|
+
action, colId, states: this.columnModel.getColumnStates(),
|
|
1318
|
+
});
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
//# sourceMappingURL=header-renderer.js.map
|