gp-grid-vue 0.5.3 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # gp-grid-vue 🏁 🏎️
2
2
 
3
3
  <div align="center">
4
- <a href="https://gp-grid-docs.vercel.app">
4
+ <a href="https://www.gp-grid.io">
5
5
  <picture>
6
6
  <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/GioPat/gp-grid-docs/refs/heads/master/public/logo-light.svg"/>
7
7
  <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/GioPat/gp-grid-docs/refs/heads/master/public/logo-dark.svg"/>
@@ -10,10 +10,11 @@
10
10
  </a>
11
11
  <div align="center">
12
12
  Logo by <a href="https://github.com/camillo18tre">camillo18tre ❤️</a>
13
- <h4><a href="https://gp-grid-docs.vercel.app/">🎮 Demo</a> • <a href="https://gp-grid-docs.vercel.app/docs/vue">📖 Documentation</a>
13
+ <h4><a href="https://www.gp-grid.io/">🎮 Demo</a> • <a href="https://www.gp-grid.io/docs/vue">📖 Documentation</a>
14
14
  </div>
15
15
  </div>
16
16
 
17
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/GioPat/gp-grid)
17
18
 
18
19
  A high-performance, feature lean Vue 3 data grid component built to manage grids with huge amount (millions) of rows. It's based on its core dependency: `gp-grid-core`, featuring virtual scrolling, cell selection, sorting, filtering, editing, and Excel-like fill handle.
19
20
 
@@ -299,8 +300,7 @@ const cellRenderers: Record<string, VueCellRenderer> = {
299
300
  },
300
301
 
301
302
  // Bold text
302
- bold: (params: CellRendererParams) =>
303
- h("strong", String(params.value ?? "")),
303
+ bold: (params: CellRendererParams) => h("strong", String(params.value ?? "")),
304
304
  };
305
305
 
306
306
  const columns: ColumnDefinition[] = [
@@ -375,30 +375,34 @@ interface Task {
375
375
  // Custom select editor for priority field
376
376
  const editRenderers: Record<string, VueEditRenderer> = {
377
377
  prioritySelect: (params: EditRendererParams) => {
378
- return h("select", {
379
- autofocus: true,
380
- value: params.initialValue as string,
381
- onChange: (e: Event) => {
382
- const target = e.target as HTMLSelectElement;
383
- params.onValueChange(target.value);
384
- },
385
- onBlur: () => params.onCommit(),
386
- onKeydown: (e: KeyboardEvent) => {
387
- if (e.key === "Enter") params.onCommit();
388
- if (e.key === "Escape") params.onCancel();
389
- },
390
- style: {
391
- width: "100%",
392
- height: "100%",
393
- border: "none",
394
- outline: "none",
395
- padding: "0 8px",
378
+ return h(
379
+ "select",
380
+ {
381
+ autofocus: true,
382
+ value: params.initialValue as string,
383
+ onChange: (e: Event) => {
384
+ const target = e.target as HTMLSelectElement;
385
+ params.onValueChange(target.value);
386
+ },
387
+ onBlur: () => params.onCommit(),
388
+ onKeydown: (e: KeyboardEvent) => {
389
+ if (e.key === "Enter") params.onCommit();
390
+ if (e.key === "Escape") params.onCancel();
391
+ },
392
+ style: {
393
+ width: "100%",
394
+ height: "100%",
395
+ border: "none",
396
+ outline: "none",
397
+ padding: "0 8px",
398
+ },
396
399
  },
397
- }, [
398
- h("option", { value: "low" }, "Low"),
399
- h("option", { value: "medium" }, "Medium"),
400
- h("option", { value: "high" }, "High"),
401
- ]);
400
+ [
401
+ h("option", { value: "low" }, "Low"),
402
+ h("option", { value: "medium" }, "Medium"),
403
+ h("option", { value: "high" }, "High"),
404
+ ],
405
+ );
402
406
  },
403
407
 
404
408
  checkbox: (params: EditRendererParams) =>
@@ -467,7 +471,12 @@ const dataSource = createClientDataSource(tasks);
467
471
 
468
472
  ```vue
469
473
  <template>
470
- <GpGrid :columns="columns" :row-data="data" :row-height="36" :dark-mode="true" />
474
+ <GpGrid
475
+ :columns="columns"
476
+ :row-data="data"
477
+ :row-height="36"
478
+ :dark-mode="true"
479
+ />
471
480
  </template>
472
481
  ```
473
482
 
@@ -548,7 +557,9 @@ interface HeaderRendererParams {
548
557
  }
549
558
 
550
559
  // Vue header renderer
551
- type VueHeaderRenderer = (params: HeaderRendererParams) => VNode | string | null;
560
+ type VueHeaderRenderer = (
561
+ params: HeaderRendererParams,
562
+ ) => VNode | string | null;
552
563
  ```
553
564
 
554
565
  ## Keyboard Shortcuts
package/dist/index.d.ts CHANGED
@@ -61,6 +61,81 @@ interface FillHandleState {
61
61
  targetCol: number;
62
62
  }
63
63
  //#endregion
64
+ //#region ../core/src/types/highlighting.d.ts
65
+ /**
66
+ * Minimal column info for highlighting context.
67
+ * Uses structural typing to avoid circular dependency with columns.ts.
68
+ */
69
+ interface HighlightColumnInfo {
70
+ field: string;
71
+ colId?: string;
72
+ }
73
+ /**
74
+ * Unified context for row, column, and cell highlighting.
75
+ *
76
+ * - Row context: `rowIndex` is set, `colIndex` is null
77
+ * - Column context: `colIndex` is set, `rowIndex` is null
78
+ * - Cell context: both `rowIndex` and `colIndex` are set
79
+ */
80
+ interface HighlightContext<TData = Record<string, unknown>> {
81
+ /** Row index. Null for column-only context. */
82
+ rowIndex: number | null;
83
+ /** Column index. Null for row-only context. */
84
+ colIndex: number | null;
85
+ /** Column definition. Present for column and cell contexts. */
86
+ column?: HighlightColumnInfo;
87
+ /** Row data. Present for row and cell contexts. */
88
+ rowData?: TData;
89
+ /** Currently hovered cell position, null if not hovering */
90
+ hoverPosition: CellPosition | null;
91
+ /** Currently active (focused) cell position */
92
+ activeCell: CellPosition | null;
93
+ /** Current selection range */
94
+ selectionRange: CellRange | null;
95
+ /** Whether this row/column/cell is hovered (respects hoverScope) */
96
+ isHovered: boolean;
97
+ /** Whether this row/column contains or is the active cell */
98
+ isActive: boolean;
99
+ /** Whether this row/column/cell overlaps or is in the selection range */
100
+ isSelected: boolean;
101
+ }
102
+ /**
103
+ * Grid-level highlighting options.
104
+ * Hover tracking is automatically enabled when any highlighting callback is defined.
105
+ * Each callback type has its own natural interpretation of `isHovered`:
106
+ * - computeRowClasses: isHovered = mouse is on any cell in this row
107
+ * - computeColumnClasses: isHovered = mouse is on any cell in this column
108
+ * - computeCellClasses: isHovered = mouse is on this exact cell
109
+ *
110
+ * For a crosshair effect, implement both computeRowClasses and computeColumnClasses.
111
+ */
112
+ interface HighlightingOptions<TData = Record<string, unknown>> {
113
+ /**
114
+ * Row-level class callback.
115
+ * Classes returned are applied to the row container element.
116
+ * Context has `rowIndex` set, `colIndex` is null.
117
+ * `isHovered` is true when the mouse is on any cell in this row.
118
+ * @returns Array of CSS class names
119
+ */
120
+ computeRowClasses?: (context: HighlightContext<TData>) => string[];
121
+ /**
122
+ * Column-level class callback.
123
+ * Classes returned are applied to all cells in that column (not header).
124
+ * Context has `colIndex` set, `rowIndex` is null.
125
+ * `isHovered` is true when the mouse is on any cell in this column.
126
+ * @returns Array of CSS class names
127
+ */
128
+ computeColumnClasses?: (context: HighlightContext<TData>) => string[];
129
+ /**
130
+ * Cell-level class callback.
131
+ * Classes returned are applied to individual cells for fine-grained control.
132
+ * Context has both `rowIndex` and `colIndex` set.
133
+ * `isHovered` is true only when the mouse is on this exact cell.
134
+ * @returns Array of CSS class names
135
+ */
136
+ computeCellClasses?: (context: HighlightContext<TData>) => string[];
137
+ }
138
+ //#endregion
64
139
  //#region ../core/src/types/columns.d.ts
65
140
  /** Column definition */
66
141
  interface ColumnDefinition {
@@ -74,10 +149,26 @@ interface ColumnDefinition {
74
149
  sortable?: boolean;
75
150
  /** Whether column is filterable. Default: true */
76
151
  filterable?: boolean;
152
+ /** Whether column is hidden. Hidden columns are not rendered but still exist in the definition. Default: false */
153
+ hidden?: boolean;
77
154
  /** Renderer key for adapter lookup, or inline renderer function */
78
155
  cellRenderer?: string;
79
156
  editRenderer?: string;
80
157
  headerRenderer?: string;
158
+ /**
159
+ * Per-column override for column-level highlighting.
160
+ * If defined, overrides grid-level computeColumnClasses for this column.
161
+ * Context has `colIndex` set, `rowIndex` is null.
162
+ * @returns Array of CSS class names to apply to all cells in this column
163
+ */
164
+ computeColumnClasses?: (context: HighlightContext) => string[];
165
+ /**
166
+ * Per-column override for cell-level highlighting.
167
+ * If defined, overrides grid-level computeCellClasses for cells in this column.
168
+ * Context has both `rowIndex` and `colIndex` set.
169
+ * @returns Array of CSS class names to apply to individual cells
170
+ */
171
+ computeCellClasses?: (context: HighlightContext) => string[];
81
172
  }
82
173
  //#endregion
83
174
  //#region ../core/src/types/filters.d.ts
@@ -189,6 +280,11 @@ interface SetActiveCellInstruction {
189
280
  type: "SET_ACTIVE_CELL";
190
281
  position: CellPosition | null;
191
282
  }
283
+ /** Set hover position instruction (for highlighting) */
284
+ interface SetHoverPositionInstruction {
285
+ type: "SET_HOVER_POSITION";
286
+ position: CellPosition | null;
287
+ }
192
288
  /** Set selection range instruction */
193
289
  interface SetSelectionRangeInstruction {
194
290
  type: "SET_SELECTION_RANGE";
@@ -298,19 +394,20 @@ interface DataErrorInstruction {
298
394
  /** Rows added instruction */
299
395
  interface RowsAddedInstruction {
300
396
  type: "ROWS_ADDED";
397
+ indices: number[];
301
398
  count: number;
302
399
  totalRows: number;
303
400
  }
304
401
  /** Rows removed instruction */
305
402
  interface RowsRemovedInstruction {
306
403
  type: "ROWS_REMOVED";
307
- count: number;
404
+ indices: number[];
308
405
  totalRows: number;
309
406
  }
310
407
  /** Rows updated instruction */
311
408
  interface RowsUpdatedInstruction {
312
409
  type: "ROWS_UPDATED";
313
- count: number;
410
+ indices: number[];
314
411
  }
315
412
  /** Transaction processed instruction */
316
413
  interface TransactionProcessedInstruction {
@@ -323,6 +420,7 @@ interface TransactionProcessedInstruction {
323
420
  type GridInstruction = /** Slot lifecycle */
324
421
  CreateSlotInstruction | DestroySlotInstruction | AssignSlotInstruction | MoveSlotInstruction
325
422
  /** Selection */ | SetActiveCellInstruction | SetSelectionRangeInstruction | UpdateVisibleRangeInstruction
423
+ /** Highlighting */ | SetHoverPositionInstruction
326
424
  /** Editing */ | StartEditInstruction | StopEditInstruction | CommitEditInstruction
327
425
  /** Layout */ | SetContentSizeInstruction | UpdateHeaderInstruction
328
426
  /** Filter popup */ | OpenFilterPopupInstruction | CloseFilterPopupInstruction
@@ -331,8 +429,6 @@ CreateSlotInstruction | DestroySlotInstruction | AssignSlotInstruction | MoveSlo
331
429
  /** Transactions */ | RowsAddedInstruction | RowsRemovedInstruction | RowsUpdatedInstruction | TransactionProcessedInstruction;
332
430
  /** Instruction listener: Single instruction Listener that receives a single instruction, used by frameworks to update their state */
333
431
  type InstructionListener = (instruction: GridInstruction) => void;
334
- /** Batch instruction listener: Batch instruction Listener that receives an array of instructions, used by frameworks to update their state */
335
- type BatchInstructionListener = (instructions: GridInstruction[]) => void;
336
432
  //#endregion
337
433
  //#region ../core/src/types/renderers.d.ts
338
434
  /** Cell renderer params */
@@ -406,6 +502,8 @@ interface GridCoreOptions<TData = Row> {
406
502
  transactionDebounceMs?: number;
407
503
  /** Function to extract unique ID from row. Required for mutations. */
408
504
  getRowId?: (row: TData) => RowId;
505
+ /** Row/column/cell highlighting configuration */
506
+ highlighting?: HighlightingOptions<TData>;
409
507
  }
410
508
  //#endregion
411
509
  //#region ../core/src/types/input.d.ts
@@ -486,10 +584,16 @@ interface InputHandlerDeps {
486
584
  getHeaderHeight: () => number;
487
585
  /** Get row height */
488
586
  getRowHeight: () => number;
489
- /** Get column positions array */
587
+ /** Get column positions array (indexed by visible column) */
490
588
  getColumnPositions: () => number[];
491
- /** Get column count */
589
+ /** Get visible column count */
492
590
  getColumnCount: () => number;
591
+ /**
592
+ * Convert visible column index to original column index.
593
+ * Used when columns can be hidden. Returns the original index for selection tracking.
594
+ * If not provided, visible index is used directly (no hidden columns).
595
+ */
596
+ getOriginalColumnIndex?: (visibleIndex: number) => number;
493
597
  }
494
598
  /** Current drag state for UI rendering */
495
599
  interface DragState {
@@ -506,6 +610,63 @@ interface DragState {
506
610
  } | null;
507
611
  }
508
612
  //#endregion
613
+ //#region ../core/src/utils/positioning.d.ts
614
+ /**
615
+ * Calculate cumulative column positions (prefix sums)
616
+ * Returns an array where positions[i] is the left position of column i
617
+ * positions[columns.length] is the total width
618
+ */
619
+ declare const calculateColumnPositions: (columns: ColumnDefinition[]) => number[];
620
+ /**
621
+ * Get total width from column positions
622
+ */
623
+ declare const getTotalWidth: (columnPositions: number[]) => number;
624
+ /**
625
+ * Find column index at a given X coordinate
626
+ */
627
+ declare const findColumnAtX: (x: number, columnPositions: number[]) => number;
628
+ //#endregion
629
+ //#region ../core/src/utils/classNames.d.ts
630
+ /**
631
+ * Check if a cell is within the selection range
632
+ */
633
+ declare const isCellSelected: (row: number, col: number, selectionRange: CellRange | null) => boolean;
634
+ /**
635
+ * Check if a cell is the active cell
636
+ */
637
+ declare const isCellActive: (row: number, col: number, activeCell: CellPosition | null) => boolean;
638
+ /**
639
+ * Check if a row is within the visible range (not in overscan)
640
+ */
641
+ declare const isRowVisible: (row: number, visibleRowRange: {
642
+ start: number;
643
+ end: number;
644
+ } | null) => boolean;
645
+ /**
646
+ * Check if a cell is being edited
647
+ */
648
+ declare const isCellEditing: (row: number, col: number, editingCell: {
649
+ row: number;
650
+ col: number;
651
+ } | null) => boolean;
652
+ /**
653
+ * Check if a cell is in the fill preview range (vertical-only fill)
654
+ */
655
+ declare const isCellInFillPreview: (row: number, col: number, isDraggingFill: boolean, fillSourceRange: CellRange | null, fillTarget: {
656
+ row: number;
657
+ col: number;
658
+ } | null) => boolean;
659
+ /**
660
+ * Build cell CSS classes based on state
661
+ */
662
+ declare const buildCellClasses: (isActive: boolean, isSelected: boolean, isEditing: boolean, inFillPreview: boolean) => string;
663
+ //#endregion
664
+ //#region ../core/src/utils/event-emitter.d.ts
665
+ /**
666
+ * Batch instruction listener for efficient state updates
667
+ */
668
+ type BatchInstructionListener = (instructions: GridInstruction[]) => void;
669
+ //#endregion
509
670
  //#region ../core/src/selection.d.ts
510
671
  type Direction = "up" | "down" | "left" | "right";
511
672
  interface SelectionManagerOptions {
@@ -521,10 +682,10 @@ interface SelectionManagerOptions {
521
682
  declare class SelectionManager {
522
683
  private state;
523
684
  private options;
524
- private listeners;
525
- constructor(options: SelectionManagerOptions);
526
- onInstruction(listener: InstructionListener): () => void;
685
+ private emitter;
686
+ onInstruction: (listener: InstructionListener) => () => void;
527
687
  private emit;
688
+ constructor(options: SelectionManagerOptions);
528
689
  getState(): SelectionState;
529
690
  getActiveCell(): CellPosition | null;
530
691
  getSelectionRange(): CellRange | null;
@@ -589,10 +750,10 @@ interface FillManagerOptions {
589
750
  declare class FillManager {
590
751
  private state;
591
752
  private options;
592
- private listeners;
593
- constructor(options: FillManagerOptions);
594
- onInstruction(listener: InstructionListener): () => void;
753
+ private emitter;
754
+ onInstruction: (listener: InstructionListener) => () => void;
595
755
  private emit;
756
+ constructor(options: FillManagerOptions);
596
757
  getState(): FillHandleState | null;
597
758
  isActive(): boolean;
598
759
  /**
@@ -649,6 +810,14 @@ declare class InputHandler<TData extends Row = Row> {
649
810
  * Handle cell double click event (start editing)
650
811
  */
651
812
  handleCellDoubleClick(rowIndex: number, colIndex: number): void;
813
+ /**
814
+ * Handle cell mouse enter event (for hover highlighting)
815
+ */
816
+ handleCellMouseEnter(rowIndex: number, colIndex: number): void;
817
+ /**
818
+ * Handle cell mouse leave event (for hover highlighting)
819
+ */
820
+ handleCellMouseLeave(): void;
652
821
  /**
653
822
  * Handle fill handle mouse down event
654
823
  */
@@ -684,16 +853,222 @@ declare class InputHandler<TData extends Row = Row> {
684
853
  row: number;
685
854
  col: number;
686
855
  } | null, filterPopupOpen: boolean): KeyboardResult;
687
- /**
688
- * Find column index at a given X coordinate
689
- */
690
- private findColumnAtX;
691
856
  /**
692
857
  * Calculate auto-scroll deltas based on mouse position
693
858
  */
694
859
  private calculateAutoScroll;
695
860
  }
696
861
  //#endregion
862
+ //#region ../core/src/highlight-manager.d.ts
863
+ interface HighlightManagerOptions {
864
+ getActiveCell: () => CellPosition | null;
865
+ getSelectionRange: () => CellRange | null;
866
+ getColumn: (colIndex: number) => ColumnDefinition | undefined;
867
+ }
868
+ /**
869
+ * Manages row/column/cell highlighting state and class computation.
870
+ * Emits SET_HOVER_POSITION instructions when hover position changes.
871
+ */
872
+ declare class HighlightManager<TData = Record<string, unknown>> {
873
+ private options;
874
+ private highlightingOptions;
875
+ private hoverPosition;
876
+ private emitter;
877
+ onInstruction: (listener: InstructionListener) => () => void;
878
+ private emit;
879
+ private rowClassCache;
880
+ private columnClassCache;
881
+ private cellClassCache;
882
+ constructor(options: HighlightManagerOptions, highlightingOptions?: HighlightingOptions<TData>);
883
+ /**
884
+ * Check if highlighting is enabled (any callback defined).
885
+ * Hover tracking is automatically enabled when highlighting is enabled.
886
+ */
887
+ isEnabled(): boolean;
888
+ /**
889
+ * Set the current hover position. Clears caches and emits instruction.
890
+ * Hover tracking is automatically enabled when any highlighting callback is defined.
891
+ */
892
+ setHoverPosition(position: CellPosition | null): void;
893
+ /**
894
+ * Get the current hover position
895
+ */
896
+ getHoverPosition(): CellPosition | null;
897
+ /**
898
+ * Called when selection changes. Clears all caches.
899
+ */
900
+ onSelectionChange(): void;
901
+ /**
902
+ * Build context for row highlighting callback.
903
+ * Returns context with `rowIndex` set, `colIndex` is null.
904
+ * `isHovered` is true when the mouse is on any cell in this row.
905
+ */
906
+ buildRowContext(rowIndex: number, rowData?: TData): HighlightContext<TData>;
907
+ /**
908
+ * Build context for column highlighting callback.
909
+ * Returns context with `colIndex` set, `rowIndex` is null.
910
+ * `isHovered` is true when the mouse is on any cell in this column.
911
+ */
912
+ buildColumnContext(colIndex: number, column: ColumnDefinition): HighlightContext<TData>;
913
+ /**
914
+ * Build context for cell highlighting callback.
915
+ * Returns context with both `rowIndex` and `colIndex` set.
916
+ * `isHovered` is true only when the mouse is on this exact cell.
917
+ */
918
+ buildCellContext(rowIndex: number, colIndex: number, column: ColumnDefinition, rowData?: TData): HighlightContext<TData>;
919
+ /**
920
+ * Compute row classes using cache and user callback
921
+ */
922
+ computeRowClasses(rowIndex: number, rowData?: TData): string[];
923
+ /**
924
+ * Compute column classes using cache and user callback (or per-column override)
925
+ */
926
+ computeColumnClasses(colIndex: number, column: ColumnDefinition): string[];
927
+ /**
928
+ * Compute cell classes using cache and user callback (or per-column override)
929
+ */
930
+ computeCellClasses(rowIndex: number, colIndex: number, column: ColumnDefinition, rowData?: TData): string[];
931
+ /**
932
+ * Compute combined cell classes (column + cell classes flattened)
933
+ */
934
+ computeCombinedCellClasses(rowIndex: number, colIndex: number, column: ColumnDefinition, rowData?: TData): string[];
935
+ /**
936
+ * Clear all caches
937
+ */
938
+ clearAllCaches(): void;
939
+ /**
940
+ * Destroy the manager and release resources
941
+ */
942
+ destroy(): void;
943
+ }
944
+ //#endregion
945
+ //#region ../core/src/sort-filter-manager.d.ts
946
+ interface SortFilterManagerOptions<TData> {
947
+ /** Get all columns */
948
+ getColumns: () => ColumnDefinition[];
949
+ /** Check if sorting is enabled globally */
950
+ isSortingEnabled: () => boolean;
951
+ /** Get cached rows for distinct value computation */
952
+ getCachedRows: () => Map<number, TData>;
953
+ /** Called when sort/filter changes to trigger data refresh */
954
+ onSortFilterChange: () => Promise<void>;
955
+ /** Called after data refresh to update UI */
956
+ onDataRefreshed: () => void;
957
+ }
958
+ /**
959
+ * Manages sorting and filtering state and operations.
960
+ */
961
+ declare class SortFilterManager<TData = Record<string, unknown>> {
962
+ private options;
963
+ private emitter;
964
+ private sortModel;
965
+ private filterModel;
966
+ private openFilterColIndex;
967
+ onInstruction: (listener: InstructionListener) => () => void;
968
+ private emit;
969
+ constructor(options: SortFilterManagerOptions<TData>);
970
+ setSort(colId: string, direction: SortDirection | null, addToExisting?: boolean): Promise<void>;
971
+ getSortModel(): SortModel[];
972
+ setFilter(colId: string, filter: ColumnFilterModel | string | null): Promise<void>;
973
+ getFilterModel(): FilterModel;
974
+ /**
975
+ * Check if a column has an active filter
976
+ */
977
+ hasActiveFilter(colId: string): boolean;
978
+ /**
979
+ * Check if a column is sortable
980
+ */
981
+ isColumnSortable(colIndex: number): boolean;
982
+ /**
983
+ * Check if a column is filterable
984
+ */
985
+ isColumnFilterable(colIndex: number): boolean;
986
+ /**
987
+ * Get distinct values for a column (for filter dropdowns)
988
+ * For array-type columns (like tags), each unique array combination is returned.
989
+ * Arrays are sorted internally for consistent comparison.
990
+ * Limited to maxValues to avoid performance issues with large datasets.
991
+ */
992
+ getDistinctValuesForColumn(colId: string, maxValues?: number): CellValue[];
993
+ /**
994
+ * Open filter popup for a column (toggles if already open for same column)
995
+ */
996
+ openFilterPopup(colIndex: number, anchorRect: {
997
+ top: number;
998
+ left: number;
999
+ width: number;
1000
+ height: number;
1001
+ }): void;
1002
+ /**
1003
+ * Close filter popup
1004
+ */
1005
+ closeFilterPopup(): void;
1006
+ /**
1007
+ * Get sort info map for header rendering
1008
+ */
1009
+ getSortInfoMap(): Map<string, {
1010
+ direction: SortDirection;
1011
+ index: number;
1012
+ }>;
1013
+ destroy(): void;
1014
+ }
1015
+ //#endregion
1016
+ //#region ../core/src/row-mutation-manager.d.ts
1017
+ interface RowMutationManagerOptions<TData> {
1018
+ /** Get the cached rows map */
1019
+ getCachedRows: () => Map<number, TData>;
1020
+ /** Set the cached rows map (for bulk operations) */
1021
+ setCachedRows: (rows: Map<number, TData>) => void;
1022
+ /** Get total row count */
1023
+ getTotalRows: () => number;
1024
+ /** Set total row count */
1025
+ setTotalRows: (count: number) => void;
1026
+ /** Update a single slot after row change */
1027
+ updateSlot: (rowIndex: number) => void;
1028
+ /** Refresh all slots after bulk changes */
1029
+ refreshAllSlots: () => void;
1030
+ /** Emit content size change */
1031
+ emitContentSize: () => void;
1032
+ /** Clear selection if it references invalid rows */
1033
+ clearSelectionIfInvalid: (maxValidRow: number) => void;
1034
+ }
1035
+ /**
1036
+ * Manages row CRUD operations and cache management.
1037
+ */
1038
+ declare class RowMutationManager<TData extends Row = Row> {
1039
+ private options;
1040
+ private emitter;
1041
+ onInstruction: (listener: InstructionListener) => () => void;
1042
+ private emit;
1043
+ constructor(options: RowMutationManagerOptions<TData>);
1044
+ /**
1045
+ * Get a row by index.
1046
+ */
1047
+ getRow(index: number): TData | undefined;
1048
+ /**
1049
+ * Add rows to the grid at the specified index.
1050
+ * If no index is provided, rows are added at the end.
1051
+ */
1052
+ addRows(rows: TData[], index?: number): void;
1053
+ /**
1054
+ * Update existing rows with partial data.
1055
+ */
1056
+ updateRows(updates: Array<{
1057
+ index: number;
1058
+ data: Partial<TData>;
1059
+ }>): void;
1060
+ /**
1061
+ * Delete rows at the specified indices.
1062
+ */
1063
+ deleteRows(indices: number[]): void;
1064
+ /**
1065
+ * Set a complete row at the specified index.
1066
+ * Use this for complete row replacement. For partial updates, use updateRows.
1067
+ */
1068
+ setRow(index: number, data: TData): void;
1069
+ destroy(): void;
1070
+ }
1071
+ //#endregion
697
1072
  //#region ../core/src/grid-core.d.ts
698
1073
  declare class GridCore<TData extends Row = Row> {
699
1074
  private columns;
@@ -710,29 +1085,25 @@ declare class GridCore<TData extends Row = Row> {
710
1085
  private totalRows;
711
1086
  private currentPageIndex;
712
1087
  private pageSize;
713
- private sortModel;
714
- private filterModel;
715
- private openFilterColIndex;
716
1088
  readonly selection: SelectionManager;
717
1089
  readonly fill: FillManager;
718
1090
  readonly input: InputHandler<TData>;
1091
+ readonly highlight: HighlightManager<TData> | null;
1092
+ readonly sortFilter: SortFilterManager<TData>;
1093
+ readonly rowMutation: RowMutationManager<TData>;
719
1094
  private readonly slotPool;
720
1095
  private readonly editManager;
721
1096
  private columnPositions;
722
- private listeners;
723
- private batchListeners;
1097
+ private emitter;
1098
+ onInstruction: (listener: InstructionListener) => () => void;
1099
+ onBatchInstruction: (listener: BatchInstructionListener) => () => void;
1100
+ private emit;
1101
+ private emitBatch;
724
1102
  private naturalContentHeight;
725
1103
  private virtualContentHeight;
726
1104
  private scrollRatio;
1105
+ private isDestroyed;
727
1106
  constructor(options: GridCoreOptions<TData>);
728
- onInstruction(listener: InstructionListener): () => void;
729
- /**
730
- * Subscribe to batched instructions for efficient React state updates.
731
- * Batch listeners receive arrays of instructions instead of individual ones.
732
- */
733
- onBatchInstruction(listener: BatchInstructionListener): () => void;
734
- private emit;
735
- private emitBatch;
736
1107
  /**
737
1108
  * Initialize the grid and load initial data.
738
1109
  */
@@ -746,37 +1117,16 @@ declare class GridCore<TData extends Row = Row> {
746
1117
  private fetchAllData;
747
1118
  setSort(colId: string, direction: SortDirection | null, addToExisting?: boolean): Promise<void>;
748
1119
  setFilter(colId: string, filter: ColumnFilterModel | string | null): Promise<void>;
749
- /**
750
- * Check if a column has an active filter
751
- */
752
1120
  hasActiveFilter(colId: string): boolean;
753
- /**
754
- * Check if a column is sortable
755
- */
756
1121
  isColumnSortable(colIndex: number): boolean;
757
- /**
758
- * Check if a column is filterable
759
- */
760
1122
  isColumnFilterable(colIndex: number): boolean;
761
- /**
762
- * Get distinct values for a column (for filter dropdowns)
763
- * For array-type columns (like tags), each unique array combination is returned.
764
- * Arrays are sorted internally for consistent comparison.
765
- * Limited to MAX_DISTINCT_VALUES to avoid performance issues with large datasets.
766
- */
767
1123
  getDistinctValuesForColumn(colId: string, maxValues?: number): CellValue[];
768
- /**
769
- * Open filter popup for a column (toggles if already open for same column)
770
- */
771
1124
  openFilterPopup(colIndex: number, anchorRect: {
772
1125
  top: number;
773
1126
  left: number;
774
1127
  width: number;
775
1128
  height: number;
776
1129
  }): void;
777
- /**
778
- * Close filter popup
779
- */
780
1130
  closeFilterPopup(): void;
781
1131
  getSortModel(): SortModel[];
782
1132
  getFilterModel(): FilterModel;
@@ -787,8 +1137,6 @@ declare class GridCore<TData extends Row = Row> {
787
1137
  getEditState(): EditState | null;
788
1138
  getCellValue(row: number, col: number): CellValue;
789
1139
  setCellValue(row: number, col: number, value: CellValue): void;
790
- private getFieldValue;
791
- private setFieldValue;
792
1140
  private computeColumnPositions;
793
1141
  private emitContentSize;
794
1142
  private emitHeaders;
@@ -845,6 +1193,31 @@ declare class GridCore<TData extends Row = Row> {
845
1193
  * Useful after in-place data modifications like fill operations.
846
1194
  */
847
1195
  refreshSlotData(): void;
1196
+ /**
1197
+ * Add rows to the grid at the specified index.
1198
+ * If no index is provided, rows are added at the end.
1199
+ */
1200
+ addRows(rows: TData[], index?: number): void;
1201
+ /**
1202
+ * Update existing rows with partial data.
1203
+ */
1204
+ updateRows(updates: Array<{
1205
+ index: number;
1206
+ data: Partial<TData>;
1207
+ }>): void;
1208
+ /**
1209
+ * Delete rows at the specified indices.
1210
+ */
1211
+ deleteRows(indices: number[]): void;
1212
+ /**
1213
+ * Get a row by index.
1214
+ */
1215
+ getRow(index: number): TData | undefined;
1216
+ /**
1217
+ * Set a complete row at the specified index.
1218
+ * Use this for complete row replacement. For partial updates, use updateRows.
1219
+ */
1220
+ setRow(index: number, data: TData): void;
848
1221
  /**
849
1222
  * Update the data source and refresh.
850
1223
  */
@@ -853,6 +1226,22 @@ declare class GridCore<TData extends Row = Row> {
853
1226
  * Update columns and recompute layout.
854
1227
  */
855
1228
  setColumns(columns: ColumnDefinition[]): void;
1229
+ /**
1230
+ * Destroy the grid core and release all references.
1231
+ * Call this before discarding the GridCore to ensure proper cleanup.
1232
+ * This method is idempotent - safe to call multiple times.
1233
+ */
1234
+ destroy(): void;
1235
+ }
1236
+ //#endregion
1237
+ //#region ../core/src/sorting/parallel-sort-manager.d.ts
1238
+ interface ParallelSortOptions {
1239
+ /** Maximum number of workers (default: navigator.hardwareConcurrency || 4) */
1240
+ maxWorkers?: number;
1241
+ /** Threshold for parallel sorting (default: 400000) */
1242
+ parallelThreshold?: number;
1243
+ /** Minimum chunk size (default: 50000) */
1244
+ minChunkSize?: number;
856
1245
  }
857
1246
  //#endregion
858
1247
  //#region ../core/src/data-source/client-data-source.d.ts
@@ -861,6 +1250,8 @@ interface ClientDataSourceOptions<TData> {
861
1250
  getFieldValue?: (row: TData, field: string) => CellValue;
862
1251
  /** Use Web Worker for sorting large datasets (default: true) */
863
1252
  useWorker?: boolean;
1253
+ /** Options for parallel sorting (only used when useWorker is true) */
1254
+ parallelSort?: ParallelSortOptions | false;
864
1255
  }
865
1256
  /**
866
1257
  * Creates a client-side data source that holds all data in memory.
@@ -948,67 +1339,11 @@ declare const gridStyles: string;
948
1339
  */
949
1340
  declare function injectStyles(): void;
950
1341
  //#endregion
951
- //#region ../core/src/utils/positioning.d.ts
952
- /**
953
- * Calculate cumulative column positions (prefix sums)
954
- * Returns an array where positions[i] is the left position of column i
955
- * positions[columns.length] is the total width
956
- */
957
- declare function calculateColumnPositions(columns: ColumnDefinition[]): number[];
958
- /**
959
- * Get total width from column positions
960
- */
961
- declare function getTotalWidth(columnPositions: number[]): number;
962
- /**
963
- * Find column index at a given X coordinate
964
- */
965
- declare function findColumnAtX(x: number, columnPositions: number[]): number;
966
- //#endregion
967
- //#region ../core/src/utils/classNames.d.ts
968
- /**
969
- * Check if a cell is within the selection range
970
- */
971
- declare function isCellSelected(row: number, col: number, selectionRange: CellRange | null): boolean;
972
- /**
973
- * Check if a cell is the active cell
974
- */
975
- declare function isCellActive(row: number, col: number, activeCell: CellPosition | null): boolean;
976
- /**
977
- * Check if a row is within the visible range (not in overscan)
978
- */
979
- declare function isRowVisible(row: number, visibleRowRange: {
980
- start: number;
981
- end: number;
982
- } | null): boolean;
983
- /**
984
- * Check if a cell is being edited
985
- */
986
- declare function isCellEditing(row: number, col: number, editingCell: {
987
- row: number;
988
- col: number;
989
- } | null): boolean;
990
- /**
991
- * Check if a cell is in the fill preview range (vertical-only fill)
992
- */
993
- declare function isCellInFillPreview(row: number, col: number, isDraggingFill: boolean, fillSourceRange: {
994
- startRow: number;
995
- startCol: number;
996
- endRow: number;
997
- endCol: number;
998
- } | null, fillTarget: {
999
- row: number;
1000
- col: number;
1001
- } | null): boolean;
1002
- /**
1003
- * Build cell CSS classes based on state
1004
- */
1005
- declare function buildCellClasses(isActive: boolean, isSelected: boolean, isEditing: boolean, inFillPreview: boolean): string;
1006
- //#endregion
1007
1342
  //#region ../core/src/types/ui-state.d.ts
1008
- interface SlotData {
1343
+ interface SlotData<TData = Row> {
1009
1344
  slotId: string;
1010
1345
  rowIndex: number;
1011
- rowData: Row;
1346
+ rowData: TData;
1012
1347
  translateY: number;
1013
1348
  }
1014
1349
  interface HeaderData {
@@ -1032,8 +1367,8 @@ interface FilterPopupState {
1032
1367
  distinctValues: CellValue[];
1033
1368
  currentFilter?: ColumnFilterModel;
1034
1369
  }
1035
- interface GridState {
1036
- slots: Map<string, SlotData>;
1370
+ interface GridState<TData = Row> {
1371
+ slots: Map<string, SlotData<TData>>;
1037
1372
  activeCell: CellPosition | null;
1038
1373
  selectionRange: CellRange | null;
1039
1374
  editingCell: {
@@ -1055,6 +1390,8 @@ interface GridState {
1055
1390
  start: number;
1056
1391
  end: number;
1057
1392
  } | null;
1393
+ /** Currently hovered cell position (for highlighting) */
1394
+ hoverPosition: CellPosition | null;
1058
1395
  }
1059
1396
  //#endregion
1060
1397
  //#region src/types.d.ts
@@ -1109,8 +1446,12 @@ type __VLS_Props = {
1109
1446
  initialWidth?: number;
1110
1447
  /** Initial viewport height for SSR (pixels). ResizeObserver takes over on client. */
1111
1448
  initialHeight?: number;
1449
+ /** Row/column/cell highlighting configuration */
1450
+ highlighting?: HighlightingOptions<Row>;
1112
1451
  };
1113
- declare const __VLS_export: vue0.DefineComponent<__VLS_Props, {}, {}, {}, {}, vue0.ComponentOptionsMixin, vue0.ComponentOptionsMixin, {}, string, vue0.PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
1452
+ declare const __VLS_export: vue0.DefineComponent<__VLS_Props, {
1453
+ core: vue0.ShallowRef<GridCore<unknown> | null, GridCore<unknown> | null>;
1454
+ }, {}, {}, {}, vue0.ComponentOptionsMixin, vue0.ComponentOptionsMixin, {}, string, vue0.PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
1114
1455
  overscan: number;
1115
1456
  sortingEnabled: boolean;
1116
1457
  darkMode: boolean;
@@ -1132,6 +1473,7 @@ interface UseGpGridOptions<TData extends Row = Row> {
1132
1473
  sortingEnabled?: boolean;
1133
1474
  darkMode?: boolean;
1134
1475
  wheelDampening?: number;
1476
+ highlighting?: HighlightingOptions<TData>;
1135
1477
  cellRenderers?: Record<string, VueCellRenderer<TData>>;
1136
1478
  editRenderers?: Record<string, VueEditRenderer<TData>>;
1137
1479
  headerRenderers?: Record<string, VueHeaderRenderer>;
@@ -1161,6 +1503,8 @@ interface UseGpGridResult<TData extends Row = Row> {
1161
1503
  handleWheel: (e: WheelEvent, wheelDampening: number) => void;
1162
1504
  handleFilterApply: (colId: string, filter: ColumnFilterModel | null) => void;
1163
1505
  handleFilterPopupClose: () => void;
1506
+ handleCellMouseEnter: (rowIndex: number, colIndex: number) => void;
1507
+ handleCellMouseLeave: () => void;
1164
1508
  dragState: Ref<{
1165
1509
  isDragging: boolean;
1166
1510
  dragType: "selection" | "fill" | null;
@@ -1188,6 +1532,10 @@ interface UseGpGridResult<TData extends Row = Row> {
1188
1532
  declare function useGpGrid<TData extends Row = Row>(options: UseGpGridOptions<TData>): UseGpGridResult<TData>;
1189
1533
  //#endregion
1190
1534
  //#region src/composables/useInputHandler.d.ts
1535
+ interface VisibleColumnInfo$1 {
1536
+ column: ColumnDefinition;
1537
+ originalIndex: number;
1538
+ }
1191
1539
  interface UseInputHandlerOptions {
1192
1540
  activeCell: ComputedRef<CellPosition | null>;
1193
1541
  selectionRange: ComputedRef<CellRange | null>;
@@ -1199,6 +1547,8 @@ interface UseInputHandlerOptions {
1199
1547
  rowHeight: number;
1200
1548
  headerHeight: number;
1201
1549
  columnPositions: ComputedRef<number[]>;
1550
+ /** Visible columns with their original indices (for hidden column support) */
1551
+ visibleColumnsWithIndices: ComputedRef<VisibleColumnInfo$1[]>;
1202
1552
  slots: ComputedRef<Map<string, SlotData>>;
1203
1553
  }
1204
1554
  interface UseInputHandlerResult {
@@ -1225,11 +1575,16 @@ declare function useAutoScroll(containerRef: Ref<HTMLDivElement | null>): {
1225
1575
  };
1226
1576
  //#endregion
1227
1577
  //#region src/composables/useFillHandle.d.ts
1578
+ interface VisibleColumnInfo {
1579
+ column: ColumnDefinition;
1580
+ originalIndex: number;
1581
+ }
1228
1582
  interface UseFillHandleOptions {
1229
1583
  activeCell: ComputedRef<CellPosition | null>;
1230
1584
  selectionRange: ComputedRef<CellRange | null>;
1231
1585
  slots: ComputedRef<Map<string, SlotData>>;
1232
1586
  columns: ComputedRef<ColumnDefinition[]>;
1587
+ visibleColumnsWithIndices: ComputedRef<VisibleColumnInfo[]>;
1233
1588
  columnPositions: ComputedRef<number[]>;
1234
1589
  columnWidths: ComputedRef<number[]>;
1235
1590
  rowHeight: number;
@@ -1292,9 +1647,9 @@ declare function useGridState(args?: InitialStateArgs): {
1292
1647
  slots: Map<string, {
1293
1648
  slotId: string;
1294
1649
  rowIndex: number;
1295
- rowData: Row;
1650
+ rowData: unknown;
1296
1651
  translateY: number;
1297
- }> & Omit<Map<string, SlotData>, keyof Map<any, any>>;
1652
+ }> & Omit<Map<string, SlotData<unknown>>, keyof Map<any, any>>;
1298
1653
  activeCell: {
1299
1654
  row: number;
1300
1655
  col: number;
@@ -1323,9 +1678,12 @@ declare function useGridState(args?: InitialStateArgs): {
1323
1678
  editable?: boolean | undefined;
1324
1679
  sortable?: boolean | undefined;
1325
1680
  filterable?: boolean | undefined;
1681
+ hidden?: boolean | undefined;
1326
1682
  cellRenderer?: string | undefined;
1327
1683
  editRenderer?: string | undefined;
1328
1684
  headerRenderer?: string | undefined;
1685
+ computeColumnClasses?: ((context: HighlightContext) => string[]) | undefined;
1686
+ computeCellClasses?: ((context: HighlightContext) => string[]) | undefined;
1329
1687
  };
1330
1688
  sortDirection?: SortDirection | undefined;
1331
1689
  sortIndex?: number | undefined;
@@ -1345,9 +1703,12 @@ declare function useGridState(args?: InitialStateArgs): {
1345
1703
  editable?: boolean | undefined;
1346
1704
  sortable?: boolean | undefined;
1347
1705
  filterable?: boolean | undefined;
1706
+ hidden?: boolean | undefined;
1348
1707
  cellRenderer?: string | undefined;
1349
1708
  editRenderer?: string | undefined;
1350
1709
  headerRenderer?: string | undefined;
1710
+ computeColumnClasses?: ((context: HighlightContext) => string[]) | undefined;
1711
+ computeCellClasses?: ((context: HighlightContext) => string[]) | undefined;
1351
1712
  } | null;
1352
1713
  anchorRect: {
1353
1714
  top: number;
@@ -1387,6 +1748,10 @@ declare function useGridState(args?: InitialStateArgs): {
1387
1748
  start: number;
1388
1749
  end: number;
1389
1750
  } | null;
1751
+ hoverPosition: {
1752
+ row: number;
1753
+ col: number;
1754
+ } | null;
1390
1755
  };
1391
1756
  applyInstructions: (instructions: GridInstruction[]) => void;
1392
1757
  reset: () => void;
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{Fragment as e,computed as t,createBlock as n,createCommentVNode as r,createElementBlock as i,createElementVNode as a,createTextVNode as o,createVNode as s,defineComponent as c,h as l,normalizeClass as u,normalizeStyle as d,onMounted as f,onUnmounted as p,openBlock as m,reactive as h,ref as g,renderList as _,resolveDynamicComponent as v,shallowRef as y,toDisplayString as b,unref as x,vModelText as S,watch as C,withDirectives as w}from"vue";import{GridCore as T,GridCore as E,buildCellClasses as D,buildCellClasses as ee,calculateColumnPositions as O,calculateScaledColumnPositions as k,createClientDataSource as A,createClientDataSource as j,createDataSourceFromArray as M,createDataSourceFromArray as N,createMutableClientDataSource as P,createServerDataSource as F,findColumnAtX as I,getTotalWidth as L,getTotalWidth as R,gridStyles as te,injectStyles as z,injectStyles as B,isCellActive as ne,isCellActive as V,isCellEditing as H,isCellEditing as U,isCellInFillPreview as W,isCellInFillPreview as re,isCellSelected as ie,isCellSelected as G,isRowVisible as ae}from"gp-grid-core";function K(e){return{slots:new Map,activeCell:null,selectionRange:null,editingCell:null,contentWidth:0,contentHeight:e?.initialHeight??0,viewportWidth:e?.initialWidth??0,headers:new Map,filterPopup:null,isLoading:!1,error:null,totalRows:0,visibleRowRange:null}}function q(e,t){switch(e.type){case`CREATE_SLOT`:t.slots.set(e.slotId,{slotId:e.slotId,rowIndex:-1,rowData:{},translateY:0});break;case`DESTROY_SLOT`:t.slots.delete(e.slotId);break;case`ASSIGN_SLOT`:{let n=t.slots.get(e.slotId);n&&t.slots.set(e.slotId,{...n,rowIndex:e.rowIndex,rowData:e.rowData});break}case`MOVE_SLOT`:{let n=t.slots.get(e.slotId);n&&t.slots.set(e.slotId,{...n,translateY:e.translateY});break}case`SET_ACTIVE_CELL`:t.activeCell=e.position;break;case`SET_SELECTION_RANGE`:t.selectionRange=e.range;break;case`UPDATE_VISIBLE_RANGE`:t.visibleRowRange={start:e.start,end:e.end};break;case`START_EDIT`:t.editingCell={row:e.row,col:e.col,initialValue:e.initialValue};break;case`STOP_EDIT`:t.editingCell=null;break;case`SET_CONTENT_SIZE`:t.contentWidth=e.width,t.contentHeight=e.height,t.viewportWidth=e.viewportWidth;break;case`UPDATE_HEADER`:t.headers.set(e.colIndex,{column:e.column,sortDirection:e.sortDirection,sortIndex:e.sortIndex,sortable:e.sortable,filterable:e.filterable,hasFilter:e.hasFilter});break;case`OPEN_FILTER_POPUP`:t.filterPopup={isOpen:!0,colIndex:e.colIndex,column:e.column,anchorRect:e.anchorRect,distinctValues:e.distinctValues,currentFilter:e.currentFilter};break;case`CLOSE_FILTER_POPUP`:t.filterPopup=null;break;case`DATA_LOADING`:t.isLoading=!0,t.error=null;break;case`DATA_LOADED`:t.isLoading=!1,t.totalRows=e.totalRows;break;case`DATA_ERROR`:t.isLoading=!1,t.error=e.error;break;case`ROWS_ADDED`:case`ROWS_REMOVED`:t.totalRows=e.totalRows;break;case`ROWS_UPDATED`:case`TRANSACTION_PROCESSED`:break}}function J(e){let t=h(K(e));function n(e){for(let n of e)q(n,t)}function r(){let e=K();t.slots=e.slots,t.activeCell=e.activeCell,t.selectionRange=e.selectionRange,t.editingCell=e.editingCell,t.contentWidth=e.contentWidth,t.contentHeight=e.contentHeight,t.viewportWidth=e.viewportWidth,t.headers=e.headers,t.filterPopup=e.filterPopup,t.isLoading=e.isLoading,t.error=e.error,t.totalRows=e.totalRows,t.visibleRowRange=e.visibleRowRange}return{state:t,applyInstructions:n,reset:r}}function oe(e){let t=g(null);function n(n,r){t.value&&clearInterval(t.value),t.value=setInterval(()=>{let t=e.value;t&&(t.scrollTop+=r,t.scrollLeft+=n)},16)}function r(){t.value&&=(clearInterval(t.value),null)}return p(()=>{r()}),{startAutoScroll:n,stopAutoScroll:r}}function se(e,t){for(let n of e.values())if(n.rowIndex===t)return n;return null}function ce(e,t,n,r,i,a){let o=se(a,n),s=(o?o.translateY:i+n*r)-t.scrollTop,c=s+r,l=i,u=t.clientHeight;if(s<l)t.scrollTop=e.getScrollTopForRow(n);else if(c>u){let a=t.clientHeight-i,o=Math.floor(a/r),s=Math.max(0,n-o+1);t.scrollTop=e.getScrollTopForRow(s)}}function Y(e,t,n,r){let{activeCell:i,selectionRange:a,editingCell:o,filterPopupOpen:s,rowHeight:c,headerHeight:l,columnPositions:u,slots:d}=r,{startAutoScroll:f,stopAutoScroll:m}=oe(t),h=g({isDragging:!1,dragType:null,fillSourceRange:null,fillTarget:null});C([()=>l,()=>c,u,()=>n.value.length],()=>{let t=e.value;t?.input&&t.input.updateDeps({getHeaderHeight:()=>l,getRowHeight:()=>c,getColumnPositions:()=>u.value,getColumnCount:()=>n.value.length})},{immediate:!0});function _(){let e=t.value;if(!e)return null;let n=e.getBoundingClientRect();return{top:n.top,left:n.left,width:n.width,height:n.height,scrollTop:e.scrollTop,scrollLeft:e.scrollLeft}}function v(e){return{clientX:e.clientX,clientY:e.clientY,button:e.button,shiftKey:e.shiftKey,ctrlKey:e.ctrlKey,metaKey:e.metaKey}}function y(){let t=t=>{let n=e.value,r=_();if(!n?.input||!r)return;let i=n.input.handleDragMove(v(t),r);i&&(i.autoScroll?f(i.autoScroll.dx,i.autoScroll.dy):m(),h.value=n.input.getDragState())},n=()=>{let r=e.value;r?.input&&(r.input.handleDragEnd(),h.value=r.input.getDragState()),m(),document.removeEventListener(`mousemove`,t),document.removeEventListener(`mouseup`,n)};document.addEventListener(`mousemove`,t),document.addEventListener(`mouseup`,n)}function b(n,r,i){let a=e.value;if(!a?.input)return;let o=a.input.handleCellMouseDown(n,r,v(i));o.focusContainer&&t.value?.focus(),o.startDrag===`selection`&&(a.input.startSelectionDrag(),h.value=a.input.getDragState(),y())}function x(t,n){let r=e.value;r?.input&&r.input.handleCellDoubleClick(t,n)}function S(t){let n=e.value;if(!n?.input)return;let r=n.input.handleFillHandleMouseDown(i.value,a.value,v(t));r.preventDefault&&t.preventDefault(),r.stopPropagation&&t.stopPropagation(),r.startDrag===`fill`&&(h.value=n.input.getDragState(),y())}function w(t,r){let i=e.value;if(!i?.input)return;let a=n.value[t];if(!a)return;let o=a.colId??a.field;i.input.handleHeaderClick(o,r.shiftKey)}function T(n){let r=e.value,a=t.value;if(!r?.input)return;let u=r.input.handleKeyDown({key:n.key,shiftKey:n.shiftKey,ctrlKey:n.ctrlKey,metaKey:n.metaKey},i.value,o.value,s.value);u.preventDefault&&n.preventDefault(),u.scrollToCell&&a&&ce(r,a,u.scrollToCell.row,c,l,d.value)}function E(n,r){let i=e.value,a=t.value;if(!i?.input||!a)return;let o=i.input.handleWheel(n.deltaY,n.deltaX,r);o&&(n.preventDefault(),a.scrollTop+=o.dy,a.scrollLeft+=o.dx)}return p(()=>{m()}),{handleCellMouseDown:b,handleCellDoubleClick:x,handleFillHandleMouseDown:S,handleHeaderClick:w,handleKeyDown:T,handleWheel:E,dragState:h}}function X(e){let{activeCell:n,selectionRange:r,slots:i,columns:a,columnPositions:o,columnWidths:s,rowHeight:c}=e;return{fillHandlePosition:t(()=>{let e=n.value,t=r.value,l=i.value;if(!e&&!t)return null;let u,d,f,p;if(t)u=Math.max(t.startRow,t.endRow),d=Math.max(t.startCol,t.endCol),f=Math.min(t.startCol,t.endCol),p=Math.max(t.startCol,t.endCol);else if(e)u=e.row,d=e.col,f=d,p=d;else return null;let m=a.value;for(let e=f;e<=p;e++){let t=m[e];if(!t||t.editable!==!0)return null}let h=null;for(let e of l.values())if(e.rowIndex===u){h=e.translateY;break}if(h===null)return null;let g=o.value[d]??0,_=s.value[d]??0;return{top:h+c-5,left:g+_-20}})}}function Z(e){return e==null||e===``?o(``):typeof e==`string`?o(e):e}function Q(e,t){let n=t.split(`.`),r=e;for(let e of n){if(typeof r!=`object`||!r)return null;r=r[e]}return r??null}function le(e){let{column:t,rowData:n,rowIndex:r,colIndex:i,isActive:a,isSelected:s,isEditing:c,cellRenderers:l,globalCellRenderer:u}=e,d=Q(n,t.field),f={value:d,rowData:n,column:t,rowIndex:r,colIndex:i,isActive:a,isSelected:s,isEditing:c};if(t.cellRenderer&&typeof t.cellRenderer==`string`){let e=l[t.cellRenderer];if(e)return Z(e(f))}return u?Z(u(f)):o(d==null?``:String(d))}function ue(e){return e==null||e===``?o(``):typeof e==`string`?o(e):e}function de(e){let{column:t,rowData:n,rowIndex:r,colIndex:i,initialValue:a,core:s,editRenderers:c,globalEditRenderer:u}=e;if(!s)return o(``);let d={value:Q(n,t.field),rowData:n,column:t,rowIndex:r,colIndex:i,isActive:!0,isSelected:!0,isEditing:!0,initialValue:a,onValueChange:e=>s.updateEditValue(e),onCommit:()=>s.commitEdit(),onCancel:()=>s.cancelEdit()};if(t.editRenderer&&typeof t.editRenderer==`string`){let e=c[t.editRenderer];if(e)return ue(e(d))}return u?ue(u(d)):l(`input`,{class:`gp-grid-edit-input`,type:`text`,value:a==null?``:String(a),autofocus:!0,onFocus:e=>e.target.select(),onInput:e=>s.updateEditValue(e.target.value),onKeydown:e=>{e.stopPropagation(),e.key===`Enter`?s.commitEdit():e.key===`Escape`?s.cancelEdit():e.key===`Tab`&&(e.preventDefault(),s.commitEdit(),s.selection.moveFocus(e.shiftKey?`left`:`right`,!1))},onBlur:()=>s.commitEdit()})}function fe(e){return e==null||e===``?o(``):typeof e==`string`?o(e):e}function pe(t){let{column:n,colIndex:r,sortDirection:i,sortIndex:a,sortable:o,filterable:s,hasFilter:c,core:u,container:d,headerRenderers:f,globalHeaderRenderer:p}=t,m={column:n,colIndex:r,sortDirection:i,sortIndex:a,sortable:o,filterable:s,hasFilter:c,onSort:(e,t)=>{u&&o&&u.setSort(n.colId??n.field,e,t)},onFilterClick:()=>{if(u&&s){let e=d?.querySelector(`[data-col-index="${r}"]`);if(e){let t=e.getBoundingClientRect();u.openFilterPopup(r,{top:t.top,left:t.left,width:t.width,height:t.height})}}}};if(n.headerRenderer&&typeof n.headerRenderer==`string`){let e=f[n.headerRenderer];if(e)return fe(e(m))}if(p)return fe(p(m));let h=[l(`span`,{class:`gp-grid-header-text`},n.headerName??n.field)],g=[];if(o){let e=[l(`span`,{class:`gp-grid-sort-arrows-stack`},[l(`svg`,{class:`gp-grid-sort-arrow-up${i===`asc`?` active`:``}`,width:`8`,height:`6`,viewBox:`0 0 8 6`},[l(`path`,{d:`M4 0L8 6H0L4 0Z`,fill:`currentColor`})]),l(`svg`,{class:`gp-grid-sort-arrow-down${i===`desc`?` active`:``}`,width:`8`,height:`6`,viewBox:`0 0 8 6`},[l(`path`,{d:`M4 6L0 0H8L4 6Z`,fill:`currentColor`})])])];a!==void 0&&a>0&&e.push(l(`span`,{class:`gp-grid-sort-index`},String(a))),g.push(l(`span`,{class:`gp-grid-sort-arrows`},e))}return s&&g.push(l(`span`,{class:`gp-grid-filter-icon${c?` active`:``}`,onMousedown:e=>{e.stopPropagation(),e.preventDefault(),m.onFilterClick()},onClick:e=>{e.stopPropagation()}},[l(`svg`,{width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`currentColor`},[l(`path`,{d:`M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z`})])])),g.length>0&&h.push(l(`span`,{class:`gp-grid-header-icons`},g)),l(e,h)}function me(e,t){let{onClose:n,ignoreSelector:r=`.gp-grid-filter-icon`}=t,i=null,a=null;f(()=>{i=t=>{let i=t.target;r&&i.closest(r)||e.value&&!e.value.contains(i)&&n()},a=e=>{e.key===`Escape`&&n()},requestAnimationFrame(()=>{i&&document.addEventListener(`mousedown`,i),a&&document.addEventListener(`keydown`,a)})}),p(()=>{i&&document.removeEventListener(`mousedown`,i),a&&document.removeEventListener(`keydown`,a)})}function $(e,t=`and`){let n=g([...e]);return{conditions:n,combination:g(t),updateCondition:(e,t)=>{let r=[...n.value];r[e]={...r[e],...t},n.value=r},addCondition:e=>{n.value=[...n.value,{operator:e,value:``,valueTo:``,nextOperator:`and`}]},removeCondition:e=>{n.value=n.value.filter((t,n)=>n!==e)}}}const he={class:`gp-grid-filter-content gp-grid-filter-text`},ge={key:0,class:`gp-grid-filter-mode-toggle`},_e={key:1,class:`gp-grid-filter-info`},ve={class:`gp-grid-filter-actions`},ye=[`disabled`],be={class:`gp-grid-filter-list`},xe={key:0,class:`gp-grid-filter-option`},Se=[`checked`],Ce=[`checked`,`onChange`],we={key:0,class:`gp-grid-filter-combination`},Te=[`onClick`],Ee=[`onClick`],De={class:`gp-grid-filter-row`},Oe=[`value`,`autofocus`,`onChange`],ke=[`value`],Ae=[`value`,`onInput`],je=[`onClick`];var Me=c({__name:`TextFilterContent`,props:{distinctValues:{},currentFilter:{}},emits:[`apply`,`close`],setup(n,{emit:o}){let s=[{value:`contains`,label:`Contains`},{value:`notContains`,label:`Does not contain`},{value:`equals`,label:`Equals`},{value:`notEquals`,label:`Does not equal`},{value:`startsWith`,label:`Starts with`},{value:`endsWith`,label:`Ends with`},{value:`blank`,label:`Is blank`},{value:`notBlank`,label:`Is not blank`}],c=n,l=o;function d(e){return Array.isArray(e)?e.join(`, `):String(e??``)}let f=t(()=>{let e=c.distinctValues.filter(e=>e!=null&&e!==``&&!(Array.isArray(e)&&e.length===0)).map(e=>d(e));return Array.from(new Set(e)).sort((e,t)=>{let n=parseFloat(e),r=parseFloat(t);return!isNaN(n)&&!isNaN(r)?n-r:e.localeCompare(t,void 0,{numeric:!0,sensitivity:`base`})})}),p=t(()=>f.value.length>100),h=g(t(()=>{if(!c.currentFilter?.conditions[0])return p.value?`condition`:`values`;let e=c.currentFilter.conditions[0];return e.selectedValues&&e.selectedValues.size>0?`values`:`condition`}).value),v=t(()=>c.currentFilter?.conditions[0]?c.currentFilter.conditions[0].selectedValues??new Set:new Set),y=t(()=>c.currentFilter?.conditions[0]?c.currentFilter.conditions[0].includeBlank??!0:!0),C=g(``),T=g(new Set(v.value)),E=g(y.value),{conditions:D,combination:ee,updateCondition:O,addCondition:k,removeCondition:A}=$(t(()=>{if(!c.currentFilter?.conditions.length)return[{operator:`contains`,value:``,valueTo:``,nextOperator:`and`}];let e=c.currentFilter.conditions[0];if(e.selectedValues&&e.selectedValues.size>0)return[{operator:`contains`,value:``,valueTo:``,nextOperator:`and`}];let t=c.currentFilter.combination??`and`;return c.currentFilter.conditions.map(e=>{let n=e;return{operator:n.operator,value:n.value??``,valueTo:``,nextOperator:n.nextOperator??t}})}).value,c.currentFilter?.combination??`and`),j=t(()=>{if(!C.value)return f.value;let e=C.value.toLowerCase();return f.value.filter(t=>t.toLowerCase().includes(e))}),M=t(()=>c.distinctValues.some(e=>e==null||e===``)),N=t(()=>j.value.every(e=>T.value.has(e))&&(!M.value||E.value));function P(){T.value=new Set(j.value),M.value&&(E.value=!0)}function F(){T.value=new Set,E.value=!1}function I(e){let t=new Set(T.value);t.has(e)?t.delete(e):t.add(e),T.value=t}function L(){if(h.value===`values`){if(f.value.every(e=>T.value.has(e))&&(!M.value||E.value)){l(`apply`,null);return}l(`apply`,{conditions:[{type:`text`,operator:`equals`,selectedValues:T.value,includeBlank:E.value}],combination:`and`})}else{let e=D.value.filter(e=>e.operator===`blank`||e.operator===`notBlank`?!0:e.value.trim()!==``);if(e.length===0){l(`apply`,null);return}l(`apply`,{conditions:e.map(e=>({type:`text`,operator:e.operator,value:e.value,nextOperator:e.nextOperator})),combination:`and`})}}function R(){l(`apply`,null)}return(t,n)=>(m(),i(`div`,he,[r(` Mode toggle - only show if not too many values `),p.value?r(`v-if`,!0):(m(),i(`div`,ge,[a(`button`,{type:`button`,class:u({active:h.value===`values`}),onClick:n[0]||=e=>h.value=`values`},` Values `,2),a(`button`,{type:`button`,class:u({active:h.value===`condition`}),onClick:n[1]||=e=>h.value=`condition`},` Condition `,2)])),r(` Too many values message `),p.value&&h.value===`condition`?(m(),i(`div`,_e,` Too many unique values (`+b(f.value.length)+`). Use conditions to filter. `,1)):r(`v-if`,!0),r(` VALUES MODE `),h.value===`values`?(m(),i(e,{key:2},[r(` Search input `),w(a(`input`,{"onUpdate:modelValue":n[2]||=e=>C.value=e,class:`gp-grid-filter-search`,type:`text`,placeholder:`Search...`,autofocus:``},null,512),[[S,C.value]]),r(` Select all / Deselect all `),a(`div`,ve,[a(`button`,{type:`button`,disabled:N.value,onClick:P},` Select All `,8,ye),a(`button`,{type:`button`,onClick:F},` Deselect All `)]),r(` Checkbox list `),a(`div`,be,[r(` Blanks option `),M.value?(m(),i(`label`,xe,[a(`input`,{type:`checkbox`,checked:E.value,onChange:n[3]||=e=>E.value=!E.value},null,40,Se),n[5]||=a(`span`,{class:`gp-grid-filter-blank`},`(Blanks)`,-1)])):r(`v-if`,!0),r(` Values `),(m(!0),i(e,null,_(j.value,e=>(m(),i(`label`,{key:e,class:`gp-grid-filter-option`},[a(`input`,{type:`checkbox`,checked:T.value.has(e),onChange:t=>I(e)},null,40,Ce),a(`span`,null,b(e),1)]))),128))])],64)):r(`v-if`,!0),r(` CONDITION MODE `),h.value===`condition`?(m(),i(e,{key:3},[(m(!0),i(e,null,_(x(D),(t,n)=>(m(),i(`div`,{key:n,class:`gp-grid-filter-condition`},[r(` Combination toggle (AND/OR) for conditions after the first `),n>0?(m(),i(`div`,we,[a(`button`,{type:`button`,class:u({active:x(D)[n-1]?.nextOperator===`and`}),onClick:e=>x(O)(n-1,{nextOperator:`and`})},` AND `,10,Te),a(`button`,{type:`button`,class:u({active:x(D)[n-1]?.nextOperator===`or`}),onClick:e=>x(O)(n-1,{nextOperator:`or`})},` OR `,10,Ee)])):r(`v-if`,!0),a(`div`,De,[r(` Operator select `),a(`select`,{value:t.operator,autofocus:n===0,onChange:e=>x(O)(n,{operator:e.target.value})},[(m(),i(e,null,_(s,e=>a(`option`,{key:e.value,value:e.value},b(e.label),9,ke)),64))],40,Oe),r(` Text input (hidden for blank/notBlank) `),t.operator!==`blank`&&t.operator!==`notBlank`?(m(),i(`input`,{key:0,type:`text`,value:t.value,placeholder:`Value`,class:`gp-grid-filter-text-input`,onInput:e=>x(O)(n,{value:e.target.value})},null,40,Ae)):r(`v-if`,!0),r(` Remove button (only if more than one condition) `),x(D).length>1?(m(),i(`button`,{key:1,type:`button`,class:`gp-grid-filter-remove`,onClick:e=>x(A)(n)},` × `,8,je)):r(`v-if`,!0)])]))),128)),r(` Add condition button `),a(`button`,{type:`button`,class:`gp-grid-filter-add`,onClick:n[4]||=e=>x(k)(`contains`)},` + Add condition `)],64)):r(`v-if`,!0),r(` Apply/Clear buttons `),a(`div`,{class:`gp-grid-filter-buttons`},[a(`button`,{type:`button`,class:`gp-grid-filter-btn-clear`,onClick:R},` Clear `),a(`button`,{type:`button`,class:`gp-grid-filter-btn-apply`,onClick:L},` Apply `)])]))}});const Ne={class:`gp-grid-filter-content gp-grid-filter-number`},Pe={key:0,class:`gp-grid-filter-combination`},Fe=[`onClick`],Ie=[`onClick`],Le={class:`gp-grid-filter-row`},Re=[`value`,`onChange`],ze=[`value`],Be=[`value`,`onInput`],Ve=[`value`,`onInput`],He=[`onClick`];var Ue=c({__name:`NumberFilterContent`,props:{currentFilter:{}},emits:[`apply`,`close`],setup(n,{emit:o}){let s=[{value:`=`,label:`=`},{value:`!=`,label:`≠`},{value:`>`,label:`>`},{value:`<`,label:`<`},{value:`>=`,label:`≥`},{value:`<=`,label:`≤`},{value:`between`,label:`↔`},{value:`blank`,label:`Is blank`},{value:`notBlank`,label:`Not blank`}],c=n,l=o,{conditions:d,combination:f,updateCondition:p,addCondition:h,removeCondition:g}=$(t(()=>{if(!c.currentFilter?.conditions.length)return[{operator:`=`,value:``,valueTo:``,nextOperator:`and`}];let e=c.currentFilter.combination??`and`;return c.currentFilter.conditions.map(t=>{let n=t;return{operator:n.operator,value:n.value==null?``:String(n.value),valueTo:n.valueTo==null?``:String(n.valueTo),nextOperator:n.nextOperator??e}})}).value,c.currentFilter?.combination??`and`);function v(){let e=d.value.filter(e=>e.operator===`blank`||e.operator===`notBlank`?!0:e.operator===`between`?e.value!==``&&e.valueTo!==``:e.value!==``);if(e.length===0){l(`apply`,null);return}l(`apply`,{conditions:e.map(e=>({type:`number`,operator:e.operator,value:e.value?parseFloat(e.value):void 0,valueTo:e.valueTo?parseFloat(e.valueTo):void 0,nextOperator:e.nextOperator})),combination:`and`})}function y(){l(`apply`,null)}return(t,n)=>(m(),i(`div`,Ne,[(m(!0),i(e,null,_(x(d),(t,o)=>(m(),i(`div`,{key:o,class:`gp-grid-filter-condition`},[r(` Combination toggle (AND/OR) for conditions after the first `),o>0?(m(),i(`div`,Pe,[a(`button`,{type:`button`,class:u({active:x(d)[o-1]?.nextOperator===`and`}),onClick:e=>x(p)(o-1,{nextOperator:`and`})},` AND `,10,Fe),a(`button`,{type:`button`,class:u({active:x(d)[o-1]?.nextOperator===`or`}),onClick:e=>x(p)(o-1,{nextOperator:`or`})},` OR `,10,Ie)])):r(`v-if`,!0),a(`div`,Le,[r(` Operator select `),a(`select`,{value:t.operator,onChange:e=>x(p)(o,{operator:e.target.value})},[(m(),i(e,null,_(s,e=>a(`option`,{key:e.value,value:e.value},b(e.label),9,ze)),64))],40,Re),r(` Number input (hidden for blank/notBlank) `),t.operator!==`blank`&&t.operator!==`notBlank`?(m(),i(`input`,{key:0,type:`number`,value:t.value,placeholder:`Value`,onInput:e=>x(p)(o,{value:e.target.value})},null,40,Be)):r(`v-if`,!0),r(` Second number input for "between" `),t.operator===`between`?(m(),i(e,{key:1},[n[1]||=a(`span`,{class:`gp-grid-filter-to`},`to`,-1),a(`input`,{type:`number`,value:t.valueTo,placeholder:`Value`,onInput:e=>x(p)(o,{valueTo:e.target.value})},null,40,Ve)],64)):r(`v-if`,!0),r(` Remove button (only if more than one condition) `),x(d).length>1?(m(),i(`button`,{key:2,type:`button`,class:`gp-grid-filter-remove`,onClick:e=>x(g)(o)},` × `,8,He)):r(`v-if`,!0)])]))),128)),r(` Add condition button `),a(`button`,{type:`button`,class:`gp-grid-filter-add`,onClick:n[0]||=e=>x(h)(`=`)},` + Add condition `),r(` Apply/Clear buttons `),a(`div`,{class:`gp-grid-filter-buttons`},[a(`button`,{type:`button`,class:`gp-grid-filter-btn-clear`,onClick:y},` Clear `),a(`button`,{type:`button`,class:`gp-grid-filter-btn-apply`,onClick:v},` Apply `)])]))}});const We={class:`gp-grid-filter-content gp-grid-filter-date`},Ge={key:0,class:`gp-grid-filter-combination`},Ke=[`onClick`],qe=[`onClick`],Je={class:`gp-grid-filter-row`},Ye=[`value`,`onChange`],Xe=[`value`],Ze=[`value`,`onInput`],Qe=[`value`,`onInput`],$e=[`onClick`];var et=c({__name:`DateFilterContent`,props:{currentFilter:{}},emits:[`apply`,`close`],setup(n,{emit:o}){let s=[{value:`=`,label:`=`},{value:`!=`,label:`≠`},{value:`>`,label:`>`},{value:`<`,label:`<`},{value:`between`,label:`↔`},{value:`blank`,label:`Is blank`},{value:`notBlank`,label:`Not blank`}],c=n,l=o;function d(e){if(!e)return``;let t=typeof e==`string`?new Date(e):e;return isNaN(t.getTime())?``:t.toISOString().split(`T`)[0]}let{conditions:f,combination:p,updateCondition:h,addCondition:g,removeCondition:v}=$(t(()=>{if(!c.currentFilter?.conditions.length)return[{operator:`=`,value:``,valueTo:``,nextOperator:`and`}];let e=c.currentFilter.combination??`and`;return c.currentFilter.conditions.map(t=>{let n=t;return{operator:n.operator,value:d(n.value),valueTo:d(n.valueTo),nextOperator:n.nextOperator??e}})}).value,c.currentFilter?.combination??`and`);function y(){let e=f.value.filter(e=>e.operator===`blank`||e.operator===`notBlank`?!0:e.operator===`between`?e.value!==``&&e.valueTo!==``:e.value!==``);if(e.length===0){l(`apply`,null);return}l(`apply`,{conditions:e.map(e=>({type:`date`,operator:e.operator,value:e.value||void 0,valueTo:e.valueTo||void 0,nextOperator:e.nextOperator})),combination:`and`})}function S(){l(`apply`,null)}return(t,n)=>(m(),i(`div`,We,[(m(!0),i(e,null,_(x(f),(t,o)=>(m(),i(`div`,{key:o,class:`gp-grid-filter-condition`},[r(` Combination toggle (AND/OR) for conditions after the first `),o>0?(m(),i(`div`,Ge,[a(`button`,{type:`button`,class:u({active:x(f)[o-1]?.nextOperator===`and`}),onClick:e=>x(h)(o-1,{nextOperator:`and`})},` AND `,10,Ke),a(`button`,{type:`button`,class:u({active:x(f)[o-1]?.nextOperator===`or`}),onClick:e=>x(h)(o-1,{nextOperator:`or`})},` OR `,10,qe)])):r(`v-if`,!0),a(`div`,Je,[r(` Operator select `),a(`select`,{value:t.operator,onChange:e=>x(h)(o,{operator:e.target.value})},[(m(),i(e,null,_(s,e=>a(`option`,{key:e.value,value:e.value},b(e.label),9,Xe)),64))],40,Ye),r(` Date input (hidden for blank/notBlank) `),t.operator!==`blank`&&t.operator!==`notBlank`?(m(),i(`input`,{key:0,type:`date`,value:t.value,onInput:e=>x(h)(o,{value:e.target.value})},null,40,Ze)):r(`v-if`,!0),r(` Second date input for "between" `),t.operator===`between`?(m(),i(e,{key:1},[n[1]||=a(`span`,{class:`gp-grid-filter-to`},`to`,-1),a(`input`,{type:`date`,value:t.valueTo,onInput:e=>x(h)(o,{valueTo:e.target.value})},null,40,Qe)],64)):r(`v-if`,!0),r(` Remove button (only if more than one condition) `),x(f).length>1?(m(),i(`button`,{key:2,type:`button`,class:`gp-grid-filter-remove`,onClick:e=>x(v)(o)},` × `,8,$e)):r(`v-if`,!0)])]))),128)),r(` Add condition button `),a(`button`,{type:`button`,class:`gp-grid-filter-add`,onClick:n[0]||=e=>x(g)(`=`)},` + Add condition `),r(` Apply/Clear buttons `),a(`div`,{class:`gp-grid-filter-buttons`},[a(`button`,{type:`button`,class:`gp-grid-filter-btn-clear`,onClick:S},` Clear `),a(`button`,{type:`button`,class:`gp-grid-filter-btn-apply`,onClick:y},` Apply `)])]))}});const tt={class:`gp-grid-filter-header`};var nt=c({__name:`FilterPopup`,props:{column:{},colIndex:{},anchorRect:{},distinctValues:{},currentFilter:{}},emits:[`apply`,`close`],setup(o,{emit:c}){let l=o,u=c,f=g(null);me(f,{onClose:()=>u(`close`),ignoreSelector:`.gp-grid-filter-icon`});let p=t(()=>l.column.colId??l.column.field);function h(e){u(`apply`,p.value,e),u(`close`)}function _(){u(`close`)}let v=t(()=>l.column.cellDataType);t(()=>v.value===`text`||v.value===`object`);let y=t(()=>v.value===`number`),x=t(()=>v.value===`date`||v.value===`dateString`||v.value===`dateTime`||v.value===`dateTimeString`),S=t(()=>({position:`fixed`,top:`${l.anchorRect.top+l.anchorRect.height+4}px`,left:`${l.anchorRect.left}px`,minWidth:`${Math.max(200,l.anchorRect.width)}px`,zIndex:1e4}));return(t,c)=>(m(),i(`div`,{ref_key:`popupRef`,ref:f,class:`gp-grid-filter-popup`,style:d(S.value)},[a(`div`,tt,` Filter: `+b(o.column.headerName??o.column.field),1),r(` Number filter `),y.value?(m(),n(Ue,{key:0,"current-filter":o.currentFilter,onApply:h,onClose:_},null,8,[`current-filter`])):x.value?(m(),i(e,{key:1},[r(` Date filter `),s(et,{"current-filter":o.currentFilter,onApply:h,onClose:_},null,8,[`current-filter`])],2112)):(m(),i(e,{key:2},[r(` Text filter (default) `),s(Me,{"distinct-values":o.distinctValues,"current-filter":o.currentFilter,onApply:h,onClose:_},null,8,[`distinct-values`,`current-filter`])],2112))],4))}});const rt=[`data-col-index`,`onClick`],it=[`onMousedown`,`onDblclick`],at={key:1,class:`gp-grid-loading`},ot={key:2,class:`gp-grid-error`},st={key:3,class:`gp-grid-empty`};var ct=c({__name:`GpGrid`,props:{columns:{},dataSource:{},rowData:{},rowHeight:{},headerHeight:{},overscan:{default:3},sortingEnabled:{type:Boolean,default:!0},darkMode:{type:Boolean,default:!1},wheelDampening:{default:.1},cellRenderers:{default:()=>({})},editRenderers:{default:()=>({})},headerRenderers:{default:()=>({})},cellRenderer:{},editRenderer:{},headerRenderer:{},initialWidth:{},initialHeight:{}},setup(s){B();let c=s,l=g(null),h=y(null),{state:S,applyInstructions:w}=J({initialWidth:c.initialWidth,initialHeight:c.initialHeight}),T=t(()=>c.headerHeight??c.rowHeight),D=t(()=>k(c.columns,S.viewportWidth)),O=t(()=>D.value.positions),A=t(()=>D.value.widths),M=t(()=>R(O.value)),P=t(()=>Array.from(S.slots.values())),{handleCellMouseDown:F,handleCellDoubleClick:I,handleFillHandleMouseDown:L,handleHeaderClick:te,handleKeyDown:z,handleWheel:ne,dragState:H}=Y(h,l,t(()=>c.columns),{activeCell:t(()=>S.activeCell),selectionRange:t(()=>S.selectionRange),editingCell:t(()=>S.editingCell),filterPopupOpen:t(()=>S.filterPopup?.isOpen??!1),rowHeight:c.rowHeight,headerHeight:T.value,columnPositions:O,slots:t(()=>S.slots)}),{fillHandlePosition:W}=X({activeCell:t(()=>S.activeCell),selectionRange:t(()=>S.selectionRange),slots:t(()=>S.slots),columns:t(()=>c.columns),columnPositions:O,columnWidths:A,rowHeight:c.rowHeight});function ie(){let e=l.value,t=h.value;!e||!t||t.setViewport(e.scrollTop,e.scrollLeft,e.clientWidth,e.clientHeight)}function ae(e,t){let n=h.value;n&&n.setFilter(e,t)}function K(){let e=h.value;e&&e.closeFilterPopup()}function q(e,t){let n=U(e,t,S.editingCell);return ee(V(e,t,S.activeCell),G(e,t,S.selectionRange),n,re(e,t,H.value.dragType===`fill`,H.value.fillSourceRange,H.value.fillTarget))}return f(()=>{let e=c.dataSource??(c.rowData?N(c.rowData):j([])),t=new E({columns:c.columns,dataSource:e,rowHeight:c.rowHeight,headerHeight:T.value,overscan:c.overscan,sortingEnabled:c.sortingEnabled});h.value=t;let n=t.onBatchInstruction(e=>{w(e)});t.initialize();let r=l.value;if(r){if(t.setViewport(r.scrollTop,r.scrollLeft,r.clientWidth,r.clientHeight),typeof ResizeObserver<`u`){let e=new ResizeObserver(()=>{t.setViewport(r.scrollTop,r.scrollLeft,r.clientWidth,r.clientHeight)});e.observe(r),p(()=>{e.disconnect()})}p(()=>{n(),h.value=null})}}),C(()=>c.dataSource,e=>{if(e){let t=e;if(t.subscribe){let e=t.subscribe(()=>{h.value?.refresh()});p(()=>e())}}},{immediate:!0}),(t,c)=>(m(),i(`div`,{ref_key:`containerRef`,ref:l,class:u([`gp-grid-container`,{"gp-grid-container--dark":s.darkMode}]),style:{width:`100%`,height:`100%`,overflow:`auto`,position:`relative`},tabindex:`0`,onScroll:ie,onWheel:c[1]||=e=>x(ne)(e,s.wheelDampening),onKeydown:c[2]||=(...e)=>x(z)&&x(z)(...e)},[r(` Content sizer `),a(`div`,{style:d({width:`${Math.max(x(S).contentWidth,M.value)}px`,height:`${Math.max(x(S).contentHeight,T.value)}px`,position:`relative`,minWidth:`100%`})},[r(` Headers `),a(`div`,{class:`gp-grid-header`,style:d({position:`sticky`,top:0,left:0,height:`${T.value}px`,width:`${Math.max(x(S).contentWidth,M.value)}px`,minWidth:`100%`})},[(m(!0),i(e,null,_(s.columns,(e,t)=>(m(),i(`div`,{key:e.colId??e.field,class:`gp-grid-header-cell`,"data-col-index":t,style:d({position:`absolute`,left:`${O.value[t]}px`,top:0,width:`${A.value[t]}px`,height:`${T.value}px`,background:`transparent`}),onClick:e=>x(te)(t,e)},[(m(),n(v(x(pe)({column:e,colIndex:t,sortDirection:x(S).headers.get(t)?.sortDirection,sortIndex:x(S).headers.get(t)?.sortIndex,sortable:x(S).headers.get(t)?.sortable??!0,filterable:x(S).headers.get(t)?.filterable??!0,hasFilter:x(S).headers.get(t)?.hasFilter??!1,core:h.value,container:l.value,headerRenderers:s.headerRenderers??{},globalHeaderRenderer:s.headerRenderer}))))],12,rt))),128))],4),r(` Row slots `),(m(!0),i(e,null,_(P.value.filter(e=>e.rowIndex>=0),t=>(m(),i(`div`,{key:t.slotId,class:u([`gp-grid-row`,{"gp-grid-row--even":t.rowIndex%2==0}]),style:d({position:`absolute`,top:0,left:0,transform:`translateY(${t.translateY}px)`,width:`${Math.max(x(S).contentWidth,M.value)}px`,height:`${s.rowHeight}px`})},[(m(!0),i(e,null,_(s.columns,(a,o)=>(m(),i(`div`,{key:`${t.slotId}-${o}`,class:u(q(t.rowIndex,o)),style:d({position:`absolute`,left:`${O.value[o]}px`,top:0,width:`${A.value[o]}px`,height:`${s.rowHeight}px`}),onMousedown:e=>x(F)(t.rowIndex,o,e),onDblclick:()=>x(I)(t.rowIndex,o)},[r(` Edit mode `),x(U)(t.rowIndex,o,x(S).editingCell)&&x(S).editingCell?(m(),n(v(x(de)({column:a,rowData:t.rowData,rowIndex:t.rowIndex,colIndex:o,initialValue:x(S).editingCell.initialValue,core:h.value,editRenderers:s.editRenderers??{},globalEditRenderer:s.editRenderer})),{key:0})):(m(),i(e,{key:1},[r(` View mode `),(m(),n(v(x(le)({column:a,rowData:t.rowData,rowIndex:t.rowIndex,colIndex:o,isActive:x(V)(t.rowIndex,o,x(S).activeCell),isSelected:x(G)(t.rowIndex,o,x(S).selectionRange),isEditing:!1,cellRenderers:s.cellRenderers??{},globalCellRenderer:s.cellRenderer}))))],64))],46,it))),128))],6))),128)),r(` Fill handle `),x(W)&&!x(S).editingCell?(m(),i(`div`,{key:0,class:`gp-grid-fill-handle`,style:d({position:`absolute`,top:`${x(W).top}px`,left:`${x(W).left}px`,zIndex:200}),onMousedown:c[0]||=(...e)=>x(L)&&x(L)(...e)},null,36)):r(`v-if`,!0),r(` Loading indicator `),x(S).isLoading?(m(),i(`div`,at,[...c[3]||=[a(`div`,{class:`gp-grid-loading-spinner`},null,-1),o(` Loading... `,-1)]])):r(`v-if`,!0),r(` Error message `),x(S).error?(m(),i(`div`,ot,` Error: `+b(x(S).error),1)):r(`v-if`,!0),r(` Empty state `),!x(S).isLoading&&!x(S).error&&x(S).totalRows===0?(m(),i(`div`,st,` No data to display `)):r(`v-if`,!0)],4),r(` Filter Popup `),x(S).filterPopup?.isOpen&&x(S).filterPopup.column&&x(S).filterPopup.anchorRect?(m(),n(nt,{key:0,column:x(S).filterPopup.column,"col-index":x(S).filterPopup.colIndex,"anchor-rect":x(S).filterPopup.anchorRect,"distinct-values":x(S).filterPopup.distinctValues,"current-filter":x(S).filterPopup.currentFilter,onApply:ae,onClose:K},null,8,[`column`,`col-index`,`anchor-rect`,`distinct-values`,`current-filter`])):r(`v-if`,!0)],34))}});function lt(e){B();let n=g(null),r=g(null),{state:i,applyInstructions:a}=J(),o=t(()=>e.headerHeight??e.rowHeight),s=t(()=>k(e.columns,i.viewportWidth)),c=t(()=>s.value.positions),l=t(()=>s.value.widths),u=t(()=>R(c.value)),d=t(()=>Array.from(i.slots.values())),{handleCellMouseDown:m,handleCellDoubleClick:h,handleFillHandleMouseDown:_,handleHeaderClick:v,handleKeyDown:y,handleWheel:b,dragState:x}=Y(r,n,t(()=>e.columns),{activeCell:t(()=>i.activeCell),selectionRange:t(()=>i.selectionRange),editingCell:t(()=>i.editingCell),filterPopupOpen:t(()=>i.filterPopup?.isOpen??!1),rowHeight:e.rowHeight,headerHeight:o.value,columnPositions:c,slots:t(()=>i.slots)}),S=()=>{let e=n.value,t=r.value;!e||!t||t.setViewport(e.scrollTop,e.scrollLeft,e.clientWidth,e.clientHeight)},w=(e,t)=>{let n=r.value;n&&n.setFilter(e,t)},T=()=>{let e=r.value;e&&e.closeFilterPopup()};f(()=>{let t=e.dataSource??(e.rowData?N(e.rowData):j([])),i=new E({columns:e.columns,dataSource:t,rowHeight:e.rowHeight,headerHeight:o.value,overscan:e.overscan??3,sortingEnabled:e.sortingEnabled??!0});r.value=i;let s=i.onBatchInstruction(e=>{a(e)});i.initialize();let c=n.value;if(c){i.setViewport(c.scrollTop,c.scrollLeft,c.clientWidth,c.clientHeight);let e=new ResizeObserver(()=>{i.setViewport(c.scrollTop,c.scrollLeft,c.clientWidth,c.clientHeight)});e.observe(c),p(()=>{e.disconnect(),s(),r.value=null})}}),C(()=>e.dataSource,e=>{if(e){let t=e;if(t.subscribe){let e=t.subscribe(()=>{r.value?.refresh()});p(()=>e())}}},{immediate:!0});let{fillHandlePosition:D}=X({activeCell:t(()=>i.activeCell),selectionRange:t(()=>i.selectionRange),slots:t(()=>i.slots),columns:t(()=>e.columns),columnPositions:c,columnWidths:l,rowHeight:e.rowHeight});return{containerRef:n,coreRef:r,state:i,slotsArray:d,totalHeaderHeight:o,columnPositions:c,columnWidths:l,totalWidth:u,fillHandlePosition:D,handleScroll:S,handleCellMouseDown:m,handleCellDoubleClick:h,handleFillHandleMouseDown:_,handleHeaderClick:v,handleKeyDown:y,handleWheel:b,handleFilterApply:w,handleFilterPopupClose:T,dragState:x,isCellSelected:G,isCellActive:V,isCellEditing:U,isCellInFillPreview:re,buildCellClasses:ee}}export{ct as GpGrid,ct as default,T as GridCore,D as buildCellClasses,O as calculateColumnPositions,A as createClientDataSource,M as createDataSourceFromArray,K as createInitialState,P as createMutableClientDataSource,F as createServerDataSource,I as findColumnAtX,Q as getCellValue,L as getTotalWidth,te as gridStyles,z as injectStyles,ne as isCellActive,H as isCellEditing,W as isCellInFillPreview,ie as isCellSelected,ae as isRowVisible,le as renderCell,de as renderEditCell,pe as renderHeader,oe as useAutoScroll,X as useFillHandle,$ as useFilterConditions,me as useFilterPopup,lt as useGpGrid,J as useGridState,Y as useInputHandler};
1
+ import{Fragment as e,computed as t,createBlock as n,createCommentVNode as r,createElementBlock as i,createElementVNode as a,createTextVNode as o,createVNode as s,defineComponent as c,h as l,normalizeClass as u,normalizeStyle as d,onMounted as f,onUnmounted as p,openBlock as m,reactive as h,ref as g,renderList as _,resolveDynamicComponent as v,shallowRef as y,toDisplayString as b,unref as x,vModelText as S,watch as C,withDirectives as w}from"vue";import{GridCore as T,GridCore as E,buildCellClasses as D,buildCellClasses as ee,calculateColumnPositions as O,calculateScaledColumnPositions as k,createClientDataSource as A,createClientDataSource as j,createDataSourceFromArray as M,createDataSourceFromArray as N,createMutableClientDataSource as P,createServerDataSource as F,findColumnAtX as I,getTotalWidth as L,getTotalWidth as R,gridStyles as z,injectStyles as te,injectStyles as ne,isCellActive as re,isCellActive as B,isCellEditing as ie,isCellEditing as V,isCellInFillPreview as H,isCellInFillPreview as ae,isCellSelected as oe,isCellSelected as U,isRowVisible as W}from"gp-grid-core";function G(e){return{slots:new Map,activeCell:null,selectionRange:null,editingCell:null,contentWidth:0,contentHeight:e?.initialHeight??0,viewportWidth:e?.initialWidth??0,headers:new Map,filterPopup:null,isLoading:!1,error:null,totalRows:0,visibleRowRange:null,hoverPosition:null}}function K(e,t){switch(e.type){case`CREATE_SLOT`:t.slots.set(e.slotId,{slotId:e.slotId,rowIndex:-1,rowData:{},translateY:0});break;case`DESTROY_SLOT`:t.slots.delete(e.slotId);break;case`ASSIGN_SLOT`:{let n=t.slots.get(e.slotId);n&&t.slots.set(e.slotId,{...n,rowIndex:e.rowIndex,rowData:e.rowData});break}case`MOVE_SLOT`:{let n=t.slots.get(e.slotId);n&&t.slots.set(e.slotId,{...n,translateY:e.translateY});break}case`SET_ACTIVE_CELL`:t.activeCell=e.position;break;case`SET_SELECTION_RANGE`:t.selectionRange=e.range;break;case`UPDATE_VISIBLE_RANGE`:t.visibleRowRange={start:e.start,end:e.end};break;case`SET_HOVER_POSITION`:t.hoverPosition=e.position;break;case`START_EDIT`:t.editingCell={row:e.row,col:e.col,initialValue:e.initialValue};break;case`STOP_EDIT`:t.editingCell=null;break;case`SET_CONTENT_SIZE`:t.contentWidth=e.width,t.contentHeight=e.height,t.viewportWidth=e.viewportWidth;break;case`UPDATE_HEADER`:t.headers.set(e.colIndex,{column:e.column,sortDirection:e.sortDirection,sortIndex:e.sortIndex,sortable:e.sortable,filterable:e.filterable,hasFilter:e.hasFilter});break;case`OPEN_FILTER_POPUP`:t.filterPopup={isOpen:!0,colIndex:e.colIndex,column:e.column,anchorRect:e.anchorRect,distinctValues:e.distinctValues,currentFilter:e.currentFilter};break;case`CLOSE_FILTER_POPUP`:t.filterPopup=null;break;case`DATA_LOADING`:t.isLoading=!0,t.error=null;break;case`DATA_LOADED`:t.isLoading=!1,t.totalRows=e.totalRows;break;case`DATA_ERROR`:t.isLoading=!1,t.error=e.error;break;case`ROWS_ADDED`:case`ROWS_REMOVED`:t.totalRows=e.totalRows;break;case`ROWS_UPDATED`:case`TRANSACTION_PROCESSED`:break}}function q(e){let t=h(G(e));function n(e){for(let n of e)K(n,t)}function r(){let e=G();t.slots=e.slots,t.activeCell=e.activeCell,t.selectionRange=e.selectionRange,t.editingCell=e.editingCell,t.contentWidth=e.contentWidth,t.contentHeight=e.contentHeight,t.viewportWidth=e.viewportWidth,t.headers=e.headers,t.filterPopup=e.filterPopup,t.isLoading=e.isLoading,t.error=e.error,t.totalRows=e.totalRows,t.visibleRowRange=e.visibleRowRange,t.hoverPosition=e.hoverPosition}return{state:t,applyInstructions:n,reset:r}}function J(e){let t=g(null);function n(n,r){t.value&&clearInterval(t.value),t.value=setInterval(()=>{let t=e.value;t&&(t.scrollTop+=r,t.scrollLeft+=n)},16)}function r(){t.value&&=(clearInterval(t.value),null)}return p(()=>{r()}),{startAutoScroll:n,stopAutoScroll:r}}function se(e,t){for(let n of e.values())if(n.rowIndex===t)return n;return null}function ce(e,t,n,r,i,a){let o=se(a,n),s=(o?o.translateY:i+n*r)-t.scrollTop,c=s+r,l=i,u=t.clientHeight;if(s<l)t.scrollTop=e.getScrollTopForRow(n);else if(c>u){let a=t.clientHeight-i,o=Math.floor(a/r),s=Math.max(0,n-o+1);t.scrollTop=e.getScrollTopForRow(s)}}function Y(e,t,n,r){let{activeCell:i,selectionRange:a,editingCell:o,filterPopupOpen:s,rowHeight:c,headerHeight:l,columnPositions:u,visibleColumnsWithIndices:d,slots:f}=r,{startAutoScroll:m,stopAutoScroll:h}=J(t),_=g({isDragging:!1,dragType:null,fillSourceRange:null,fillTarget:null});C([()=>l,()=>c,u,d],()=>{let t=e.value;if(t?.input){let e=d.value;t.input.updateDeps({getHeaderHeight:()=>l,getRowHeight:()=>c,getColumnPositions:()=>u.value,getColumnCount:()=>e.length,getOriginalColumnIndex:t=>{let n=e[t];return n?n.originalIndex:t}})}},{immediate:!0});function v(){let e=t.value;if(!e)return null;let n=e.getBoundingClientRect();return{top:n.top,left:n.left,width:n.width,height:n.height,scrollTop:e.scrollTop,scrollLeft:e.scrollLeft}}function y(e){return{clientX:e.clientX,clientY:e.clientY,button:e.button,shiftKey:e.shiftKey,ctrlKey:e.ctrlKey,metaKey:e.metaKey}}function b(){let t=t=>{let n=e.value,r=v();if(!n?.input||!r)return;let i=n.input.handleDragMove(y(t),r);i&&(i.autoScroll?m(i.autoScroll.dx,i.autoScroll.dy):h(),_.value=n.input.getDragState())},n=()=>{let r=e.value;r?.input&&(r.input.handleDragEnd(),_.value=r.input.getDragState()),h(),document.removeEventListener(`mousemove`,t),document.removeEventListener(`mouseup`,n)};document.addEventListener(`mousemove`,t),document.addEventListener(`mouseup`,n)}function x(n,r,i){let a=e.value;if(!a?.input)return;let o=a.input.handleCellMouseDown(n,r,y(i));o.focusContainer&&t.value?.focus(),o.startDrag===`selection`&&(a.input.startSelectionDrag(),_.value=a.input.getDragState(),b())}function S(t,n){let r=e.value;r?.input&&r.input.handleCellDoubleClick(t,n)}function w(t){let n=e.value;if(!n?.input)return;let r=n.input.handleFillHandleMouseDown(i.value,a.value,y(t));r.preventDefault&&t.preventDefault(),r.stopPropagation&&t.stopPropagation(),r.startDrag===`fill`&&(_.value=n.input.getDragState(),b())}function T(t,r){let i=e.value;if(!i?.input)return;let a=n.value[t];if(!a)return;let o=a.colId??a.field;i.input.handleHeaderClick(o,r.shiftKey)}function E(n){let r=e.value,a=t.value;if(!r?.input)return;let u=r.input.handleKeyDown({key:n.key,shiftKey:n.shiftKey,ctrlKey:n.ctrlKey,metaKey:n.metaKey},i.value,o.value,s.value);u.preventDefault&&n.preventDefault(),u.scrollToCell&&a&&ce(r,a,u.scrollToCell.row,c,l,f.value)}function D(n,r){let i=e.value,a=t.value;if(!i?.input||!a)return;let o=i.input.handleWheel(n.deltaY,n.deltaX,r);o&&(n.preventDefault(),a.scrollTop+=o.dy,a.scrollLeft+=o.dx)}return p(()=>{h()}),{handleCellMouseDown:x,handleCellDoubleClick:S,handleFillHandleMouseDown:w,handleHeaderClick:T,handleKeyDown:E,handleWheel:D,dragState:_}}function X(e){let{activeCell:n,selectionRange:r,slots:i,columns:a,visibleColumnsWithIndices:o,columnPositions:s,columnWidths:c,rowHeight:l}=e;return{fillHandlePosition:t(()=>{let e=n.value,t=r.value,u=i.value;if(!e&&!t)return null;let d,f,p,m;if(t)d=Math.max(t.startRow,t.endRow),f=Math.max(t.startCol,t.endCol),p=Math.min(t.startCol,t.endCol),m=Math.max(t.startCol,t.endCol);else if(e)d=e.row,f=e.col,p=f,m=f;else return null;let h=a.value;for(let e=p;e<=m;e++){let t=h[e];if(!(!t||t.hidden)&&t.editable!==!0)return null}let g=o.value.findIndex(e=>e.originalIndex===f);if(g===-1)return null;let _=null;for(let e of u.values())if(e.rowIndex===d){_=e.translateY;break}if(_===null)return null;let v=s.value[g]??0,y=c.value[g]??0;return{top:_+l-5,left:v+y-20}})}}function Z(e){return e==null||e===``?o(``):typeof e==`string`?o(e):e}function Q(e,t){let n=t.split(`.`),r=e;for(let e of n){if(typeof r!=`object`||!r)return null;r=r[e]}return r??null}function le(e){let{column:t,rowData:n,rowIndex:r,colIndex:i,isActive:a,isSelected:s,isEditing:c,cellRenderers:l,globalCellRenderer:u}=e,d=Q(n,t.field),f={value:d,rowData:n,column:t,rowIndex:r,colIndex:i,isActive:a,isSelected:s,isEditing:c};if(t.cellRenderer&&typeof t.cellRenderer==`string`){let e=l[t.cellRenderer];if(e)return Z(e(f))}return u?Z(u(f)):o(d==null?``:String(d))}function ue(e){return e==null||e===``?o(``):typeof e==`string`?o(e):e}function de(e){let{column:t,rowData:n,rowIndex:r,colIndex:i,initialValue:a,core:s,editRenderers:c,globalEditRenderer:u}=e;if(!s)return o(``);let d={value:Q(n,t.field),rowData:n,column:t,rowIndex:r,colIndex:i,isActive:!0,isSelected:!0,isEditing:!0,initialValue:a,onValueChange:e=>s.updateEditValue(e),onCommit:()=>s.commitEdit(),onCancel:()=>s.cancelEdit()};if(t.editRenderer&&typeof t.editRenderer==`string`){let e=c[t.editRenderer];if(e)return ue(e(d))}return u?ue(u(d)):l(`input`,{class:`gp-grid-edit-input`,type:`text`,value:a==null?``:String(a),autofocus:!0,onFocus:e=>e.target.select(),onInput:e=>s.updateEditValue(e.target.value),onKeydown:e=>{e.stopPropagation(),e.key===`Enter`?s.commitEdit():e.key===`Escape`?s.cancelEdit():e.key===`Tab`&&(e.preventDefault(),s.commitEdit(),s.selection.moveFocus(e.shiftKey?`left`:`right`,!1))},onBlur:()=>s.commitEdit()})}function fe(e){return e==null||e===``?o(``):typeof e==`string`?o(e):e}function pe(t){let{column:n,colIndex:r,sortDirection:i,sortIndex:a,sortable:o,filterable:s,hasFilter:c,core:u,container:d,headerRenderers:f,globalHeaderRenderer:p}=t,m={column:n,colIndex:r,sortDirection:i,sortIndex:a,sortable:o,filterable:s,hasFilter:c,onSort:(e,t)=>{u&&o&&u.setSort(n.colId??n.field,e,t)},onFilterClick:()=>{if(u&&s){let e=d?.querySelector(`[data-col-index="${r}"]`);if(e){let t=e.getBoundingClientRect();u.openFilterPopup(r,{top:t.top,left:t.left,width:t.width,height:t.height})}}}};if(n.headerRenderer&&typeof n.headerRenderer==`string`){let e=f[n.headerRenderer];if(e)return fe(e(m))}if(p)return fe(p(m));let h=[l(`span`,{class:`gp-grid-header-text`},n.headerName??n.field)],g=[];if(o){let e=[l(`span`,{class:`gp-grid-sort-arrows-stack`},[l(`svg`,{class:`gp-grid-sort-arrow-up${i===`asc`?` active`:``}`,width:`8`,height:`6`,viewBox:`0 0 8 6`},[l(`path`,{d:`M4 0L8 6H0L4 0Z`,fill:`currentColor`})]),l(`svg`,{class:`gp-grid-sort-arrow-down${i===`desc`?` active`:``}`,width:`8`,height:`6`,viewBox:`0 0 8 6`},[l(`path`,{d:`M4 6L0 0H8L4 6Z`,fill:`currentColor`})])])];a!==void 0&&a>0&&e.push(l(`span`,{class:`gp-grid-sort-index`},String(a))),g.push(l(`span`,{class:`gp-grid-sort-arrows`},e))}return s&&g.push(l(`span`,{class:`gp-grid-filter-icon${c?` active`:``}`,onMousedown:e=>{e.stopPropagation(),e.preventDefault(),m.onFilterClick()},onClick:e=>{e.stopPropagation()}},[l(`svg`,{width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`currentColor`},[l(`path`,{d:`M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z`})])])),g.length>0&&h.push(l(`span`,{class:`gp-grid-header-icons`},g)),l(e,h)}function me(e,t){let{onClose:n,ignoreSelector:r=`.gp-grid-filter-icon`}=t,i=null,a=null;f(()=>{i=t=>{let i=t.target;r&&i.closest(r)||e.value&&!e.value.contains(i)&&n()},a=e=>{e.key===`Escape`&&n()},requestAnimationFrame(()=>{i&&document.addEventListener(`mousedown`,i),a&&document.addEventListener(`keydown`,a)})}),p(()=>{i&&document.removeEventListener(`mousedown`,i),a&&document.removeEventListener(`keydown`,a)})}function $(e,t=`and`){let n=g([...e]);return{conditions:n,combination:g(t),updateCondition:(e,t)=>{let r=[...n.value];r[e]={...r[e],...t},n.value=r},addCondition:e=>{n.value=[...n.value,{operator:e,value:``,valueTo:``,nextOperator:`and`}]},removeCondition:e=>{n.value=n.value.filter((t,n)=>n!==e)}}}const he={class:`gp-grid-filter-content gp-grid-filter-text`},ge={key:0,class:`gp-grid-filter-mode-toggle`},_e={key:1,class:`gp-grid-filter-info`},ve={class:`gp-grid-filter-actions`},ye=[`disabled`],be={class:`gp-grid-filter-list`},xe={key:0,class:`gp-grid-filter-option`},Se=[`checked`],Ce=[`checked`,`onChange`],we={key:0,class:`gp-grid-filter-combination`},Te=[`onClick`],Ee=[`onClick`],De={class:`gp-grid-filter-row`},Oe=[`value`,`autofocus`,`onChange`],ke=[`value`],Ae=[`value`,`onInput`],je=[`onClick`];var Me=c({__name:`TextFilterContent`,props:{distinctValues:{},currentFilter:{}},emits:[`apply`,`close`],setup(n,{emit:o}){let s=[{value:`contains`,label:`Contains`},{value:`notContains`,label:`Does not contain`},{value:`equals`,label:`Equals`},{value:`notEquals`,label:`Does not equal`},{value:`startsWith`,label:`Starts with`},{value:`endsWith`,label:`Ends with`},{value:`blank`,label:`Is blank`},{value:`notBlank`,label:`Is not blank`}],c=n,l=o;function d(e){return Array.isArray(e)?e.join(`, `):String(e??``)}let f=t(()=>{let e=c.distinctValues.filter(e=>e!=null&&e!==``&&!(Array.isArray(e)&&e.length===0)).map(e=>d(e));return Array.from(new Set(e)).sort((e,t)=>{let n=parseFloat(e),r=parseFloat(t);return!isNaN(n)&&!isNaN(r)?n-r:e.localeCompare(t,void 0,{numeric:!0,sensitivity:`base`})})}),p=t(()=>f.value.length>100),h=g(t(()=>{if(!c.currentFilter?.conditions[0])return p.value?`condition`:`values`;let e=c.currentFilter.conditions[0];return e.selectedValues&&e.selectedValues.size>0?`values`:`condition`}).value),v=t(()=>c.currentFilter?.conditions[0]?c.currentFilter.conditions[0].selectedValues??new Set:new Set),y=t(()=>c.currentFilter?.conditions[0]?c.currentFilter.conditions[0].includeBlank??!0:!0),C=g(``),T=g(new Set(v.value)),E=g(y.value),{conditions:D,combination:ee,updateCondition:O,addCondition:k,removeCondition:A}=$(t(()=>{if(!c.currentFilter?.conditions.length)return[{operator:`contains`,value:``,valueTo:``,nextOperator:`and`}];let e=c.currentFilter.conditions[0];if(e.selectedValues&&e.selectedValues.size>0)return[{operator:`contains`,value:``,valueTo:``,nextOperator:`and`}];let t=c.currentFilter.combination??`and`;return c.currentFilter.conditions.map(e=>{let n=e;return{operator:n.operator,value:n.value??``,valueTo:``,nextOperator:n.nextOperator??t}})}).value,c.currentFilter?.combination??`and`),j=t(()=>{if(!C.value)return f.value;let e=C.value.toLowerCase();return f.value.filter(t=>t.toLowerCase().includes(e))}),M=t(()=>c.distinctValues.some(e=>e==null||e===``)),N=t(()=>j.value.every(e=>T.value.has(e))&&(!M.value||E.value));function P(){T.value=new Set(j.value),M.value&&(E.value=!0)}function F(){T.value=new Set,E.value=!1}function I(e){let t=new Set(T.value);t.has(e)?t.delete(e):t.add(e),T.value=t}function L(){if(h.value===`values`){if(f.value.every(e=>T.value.has(e))&&(!M.value||E.value)){l(`apply`,null);return}l(`apply`,{conditions:[{type:`text`,operator:`equals`,selectedValues:T.value,includeBlank:E.value}],combination:`and`})}else{let e=D.value.filter(e=>e.operator===`blank`||e.operator===`notBlank`?!0:e.value.trim()!==``);if(e.length===0){l(`apply`,null);return}l(`apply`,{conditions:e.map(e=>({type:`text`,operator:e.operator,value:e.value,nextOperator:e.nextOperator})),combination:`and`})}}function R(){l(`apply`,null)}return(t,n)=>(m(),i(`div`,he,[r(` Mode toggle - only show if not too many values `),p.value?r(`v-if`,!0):(m(),i(`div`,ge,[a(`button`,{type:`button`,class:u({active:h.value===`values`}),onClick:n[0]||=e=>h.value=`values`},` Values `,2),a(`button`,{type:`button`,class:u({active:h.value===`condition`}),onClick:n[1]||=e=>h.value=`condition`},` Condition `,2)])),r(` Too many values message `),p.value&&h.value===`condition`?(m(),i(`div`,_e,` Too many unique values (`+b(f.value.length)+`). Use conditions to filter. `,1)):r(`v-if`,!0),r(` VALUES MODE `),h.value===`values`?(m(),i(e,{key:2},[r(` Search input `),w(a(`input`,{"onUpdate:modelValue":n[2]||=e=>C.value=e,class:`gp-grid-filter-search`,type:`text`,placeholder:`Search...`,autofocus:``},null,512),[[S,C.value]]),r(` Select all / Deselect all `),a(`div`,ve,[a(`button`,{type:`button`,disabled:N.value,onClick:P},` Select All `,8,ye),a(`button`,{type:`button`,onClick:F},` Deselect All `)]),r(` Checkbox list `),a(`div`,be,[r(` Blanks option `),M.value?(m(),i(`label`,xe,[a(`input`,{type:`checkbox`,checked:E.value,onChange:n[3]||=e=>E.value=!E.value},null,40,Se),n[5]||=a(`span`,{class:`gp-grid-filter-blank`},`(Blanks)`,-1)])):r(`v-if`,!0),r(` Values `),(m(!0),i(e,null,_(j.value,e=>(m(),i(`label`,{key:e,class:`gp-grid-filter-option`},[a(`input`,{type:`checkbox`,checked:T.value.has(e),onChange:t=>I(e)},null,40,Ce),a(`span`,null,b(e),1)]))),128))])],64)):r(`v-if`,!0),r(` CONDITION MODE `),h.value===`condition`?(m(),i(e,{key:3},[(m(!0),i(e,null,_(x(D),(t,n)=>(m(),i(`div`,{key:n,class:`gp-grid-filter-condition`},[r(` Combination toggle (AND/OR) for conditions after the first `),n>0?(m(),i(`div`,we,[a(`button`,{type:`button`,class:u({active:x(D)[n-1]?.nextOperator===`and`}),onClick:e=>x(O)(n-1,{nextOperator:`and`})},` AND `,10,Te),a(`button`,{type:`button`,class:u({active:x(D)[n-1]?.nextOperator===`or`}),onClick:e=>x(O)(n-1,{nextOperator:`or`})},` OR `,10,Ee)])):r(`v-if`,!0),a(`div`,De,[r(` Operator select `),a(`select`,{value:t.operator,autofocus:n===0,onChange:e=>x(O)(n,{operator:e.target.value})},[(m(),i(e,null,_(s,e=>a(`option`,{key:e.value,value:e.value},b(e.label),9,ke)),64))],40,Oe),r(` Text input (hidden for blank/notBlank) `),t.operator!==`blank`&&t.operator!==`notBlank`?(m(),i(`input`,{key:0,type:`text`,value:t.value,placeholder:`Value`,class:`gp-grid-filter-text-input`,onInput:e=>x(O)(n,{value:e.target.value})},null,40,Ae)):r(`v-if`,!0),r(` Remove button (only if more than one condition) `),x(D).length>1?(m(),i(`button`,{key:1,type:`button`,class:`gp-grid-filter-remove`,onClick:e=>x(A)(n)},` × `,8,je)):r(`v-if`,!0)])]))),128)),r(` Add condition button `),a(`button`,{type:`button`,class:`gp-grid-filter-add`,onClick:n[4]||=e=>x(k)(`contains`)},` + Add condition `)],64)):r(`v-if`,!0),r(` Apply/Clear buttons `),a(`div`,{class:`gp-grid-filter-buttons`},[a(`button`,{type:`button`,class:`gp-grid-filter-btn-clear`,onClick:R},` Clear `),a(`button`,{type:`button`,class:`gp-grid-filter-btn-apply`,onClick:L},` Apply `)])]))}});const Ne={class:`gp-grid-filter-content gp-grid-filter-number`},Pe={key:0,class:`gp-grid-filter-combination`},Fe=[`onClick`],Ie=[`onClick`],Le={class:`gp-grid-filter-row`},Re=[`value`,`onChange`],ze=[`value`],Be=[`value`,`onInput`],Ve=[`value`,`onInput`],He=[`onClick`];var Ue=c({__name:`NumberFilterContent`,props:{currentFilter:{}},emits:[`apply`,`close`],setup(n,{emit:o}){let s=[{value:`=`,label:`=`},{value:`!=`,label:`≠`},{value:`>`,label:`>`},{value:`<`,label:`<`},{value:`>=`,label:`≥`},{value:`<=`,label:`≤`},{value:`between`,label:`↔`},{value:`blank`,label:`Is blank`},{value:`notBlank`,label:`Not blank`}],c=n,l=o,{conditions:d,combination:f,updateCondition:p,addCondition:h,removeCondition:g}=$(t(()=>{if(!c.currentFilter?.conditions.length)return[{operator:`=`,value:``,valueTo:``,nextOperator:`and`}];let e=c.currentFilter.combination??`and`;return c.currentFilter.conditions.map(t=>{let n=t;return{operator:n.operator,value:n.value==null?``:String(n.value),valueTo:n.valueTo==null?``:String(n.valueTo),nextOperator:n.nextOperator??e}})}).value,c.currentFilter?.combination??`and`);function v(){let e=d.value.filter(e=>e.operator===`blank`||e.operator===`notBlank`?!0:e.operator===`between`?e.value!==``&&e.valueTo!==``:e.value!==``);if(e.length===0){l(`apply`,null);return}l(`apply`,{conditions:e.map(e=>({type:`number`,operator:e.operator,value:e.value?parseFloat(e.value):void 0,valueTo:e.valueTo?parseFloat(e.valueTo):void 0,nextOperator:e.nextOperator})),combination:`and`})}function y(){l(`apply`,null)}return(t,n)=>(m(),i(`div`,Ne,[(m(!0),i(e,null,_(x(d),(t,o)=>(m(),i(`div`,{key:o,class:`gp-grid-filter-condition`},[r(` Combination toggle (AND/OR) for conditions after the first `),o>0?(m(),i(`div`,Pe,[a(`button`,{type:`button`,class:u({active:x(d)[o-1]?.nextOperator===`and`}),onClick:e=>x(p)(o-1,{nextOperator:`and`})},` AND `,10,Fe),a(`button`,{type:`button`,class:u({active:x(d)[o-1]?.nextOperator===`or`}),onClick:e=>x(p)(o-1,{nextOperator:`or`})},` OR `,10,Ie)])):r(`v-if`,!0),a(`div`,Le,[r(` Operator select `),a(`select`,{value:t.operator,onChange:e=>x(p)(o,{operator:e.target.value})},[(m(),i(e,null,_(s,e=>a(`option`,{key:e.value,value:e.value},b(e.label),9,ze)),64))],40,Re),r(` Number input (hidden for blank/notBlank) `),t.operator!==`blank`&&t.operator!==`notBlank`?(m(),i(`input`,{key:0,type:`number`,value:t.value,placeholder:`Value`,onInput:e=>x(p)(o,{value:e.target.value})},null,40,Be)):r(`v-if`,!0),r(` Second number input for "between" `),t.operator===`between`?(m(),i(e,{key:1},[n[1]||=a(`span`,{class:`gp-grid-filter-to`},`to`,-1),a(`input`,{type:`number`,value:t.valueTo,placeholder:`Value`,onInput:e=>x(p)(o,{valueTo:e.target.value})},null,40,Ve)],64)):r(`v-if`,!0),r(` Remove button (only if more than one condition) `),x(d).length>1?(m(),i(`button`,{key:2,type:`button`,class:`gp-grid-filter-remove`,onClick:e=>x(g)(o)},` × `,8,He)):r(`v-if`,!0)])]))),128)),r(` Add condition button `),a(`button`,{type:`button`,class:`gp-grid-filter-add`,onClick:n[0]||=e=>x(h)(`=`)},` + Add condition `),r(` Apply/Clear buttons `),a(`div`,{class:`gp-grid-filter-buttons`},[a(`button`,{type:`button`,class:`gp-grid-filter-btn-clear`,onClick:y},` Clear `),a(`button`,{type:`button`,class:`gp-grid-filter-btn-apply`,onClick:v},` Apply `)])]))}});const We={class:`gp-grid-filter-content gp-grid-filter-date`},Ge={key:0,class:`gp-grid-filter-combination`},Ke=[`onClick`],qe=[`onClick`],Je={class:`gp-grid-filter-row`},Ye=[`value`,`onChange`],Xe=[`value`],Ze=[`value`,`onInput`],Qe=[`value`,`onInput`],$e=[`onClick`];var et=c({__name:`DateFilterContent`,props:{currentFilter:{}},emits:[`apply`,`close`],setup(n,{emit:o}){let s=[{value:`=`,label:`=`},{value:`!=`,label:`≠`},{value:`>`,label:`>`},{value:`<`,label:`<`},{value:`between`,label:`↔`},{value:`blank`,label:`Is blank`},{value:`notBlank`,label:`Not blank`}],c=n,l=o;function d(e){if(!e)return``;let t=typeof e==`string`?new Date(e):e;return isNaN(t.getTime())?``:t.toISOString().split(`T`)[0]}let{conditions:f,combination:p,updateCondition:h,addCondition:g,removeCondition:v}=$(t(()=>{if(!c.currentFilter?.conditions.length)return[{operator:`=`,value:``,valueTo:``,nextOperator:`and`}];let e=c.currentFilter.combination??`and`;return c.currentFilter.conditions.map(t=>{let n=t;return{operator:n.operator,value:d(n.value),valueTo:d(n.valueTo),nextOperator:n.nextOperator??e}})}).value,c.currentFilter?.combination??`and`);function y(){let e=f.value.filter(e=>e.operator===`blank`||e.operator===`notBlank`?!0:e.operator===`between`?e.value!==``&&e.valueTo!==``:e.value!==``);if(e.length===0){l(`apply`,null);return}l(`apply`,{conditions:e.map(e=>({type:`date`,operator:e.operator,value:e.value||void 0,valueTo:e.valueTo||void 0,nextOperator:e.nextOperator})),combination:`and`})}function S(){l(`apply`,null)}return(t,n)=>(m(),i(`div`,We,[(m(!0),i(e,null,_(x(f),(t,o)=>(m(),i(`div`,{key:o,class:`gp-grid-filter-condition`},[r(` Combination toggle (AND/OR) for conditions after the first `),o>0?(m(),i(`div`,Ge,[a(`button`,{type:`button`,class:u({active:x(f)[o-1]?.nextOperator===`and`}),onClick:e=>x(h)(o-1,{nextOperator:`and`})},` AND `,10,Ke),a(`button`,{type:`button`,class:u({active:x(f)[o-1]?.nextOperator===`or`}),onClick:e=>x(h)(o-1,{nextOperator:`or`})},` OR `,10,qe)])):r(`v-if`,!0),a(`div`,Je,[r(` Operator select `),a(`select`,{value:t.operator,onChange:e=>x(h)(o,{operator:e.target.value})},[(m(),i(e,null,_(s,e=>a(`option`,{key:e.value,value:e.value},b(e.label),9,Xe)),64))],40,Ye),r(` Date input (hidden for blank/notBlank) `),t.operator!==`blank`&&t.operator!==`notBlank`?(m(),i(`input`,{key:0,type:`date`,value:t.value,onInput:e=>x(h)(o,{value:e.target.value})},null,40,Ze)):r(`v-if`,!0),r(` Second date input for "between" `),t.operator===`between`?(m(),i(e,{key:1},[n[1]||=a(`span`,{class:`gp-grid-filter-to`},`to`,-1),a(`input`,{type:`date`,value:t.valueTo,onInput:e=>x(h)(o,{valueTo:e.target.value})},null,40,Qe)],64)):r(`v-if`,!0),r(` Remove button (only if more than one condition) `),x(f).length>1?(m(),i(`button`,{key:2,type:`button`,class:`gp-grid-filter-remove`,onClick:e=>x(v)(o)},` × `,8,$e)):r(`v-if`,!0)])]))),128)),r(` Add condition button `),a(`button`,{type:`button`,class:`gp-grid-filter-add`,onClick:n[0]||=e=>x(g)(`=`)},` + Add condition `),r(` Apply/Clear buttons `),a(`div`,{class:`gp-grid-filter-buttons`},[a(`button`,{type:`button`,class:`gp-grid-filter-btn-clear`,onClick:S},` Clear `),a(`button`,{type:`button`,class:`gp-grid-filter-btn-apply`,onClick:y},` Apply `)])]))}});const tt={class:`gp-grid-filter-header`};var nt=c({__name:`FilterPopup`,props:{column:{},colIndex:{},anchorRect:{},distinctValues:{},currentFilter:{}},emits:[`apply`,`close`],setup(o,{emit:c}){let l=o,u=c,f=g(null);me(f,{onClose:()=>u(`close`),ignoreSelector:`.gp-grid-filter-icon`});let p=t(()=>l.column.colId??l.column.field);function h(e){u(`apply`,p.value,e),u(`close`)}function _(){u(`close`)}let v=t(()=>l.column.cellDataType);t(()=>v.value===`text`||v.value===`object`);let y=t(()=>v.value===`number`),x=t(()=>v.value===`date`||v.value===`dateString`||v.value===`dateTime`||v.value===`dateTimeString`),S=t(()=>({position:`fixed`,top:`${l.anchorRect.top+l.anchorRect.height+4}px`,left:`${l.anchorRect.left}px`,minWidth:`${Math.max(200,l.anchorRect.width)}px`,zIndex:1e4}));return(t,c)=>(m(),i(`div`,{ref_key:`popupRef`,ref:f,class:`gp-grid-filter-popup`,style:d(S.value)},[a(`div`,tt,` Filter: `+b(o.column.headerName??o.column.field),1),r(` Number filter `),y.value?(m(),n(Ue,{key:0,"current-filter":o.currentFilter,onApply:h,onClose:_},null,8,[`current-filter`])):x.value?(m(),i(e,{key:1},[r(` Date filter `),s(et,{"current-filter":o.currentFilter,onApply:h,onClose:_},null,8,[`current-filter`])],2112)):(m(),i(e,{key:2},[r(` Text filter (default) `),s(Me,{"distinct-values":o.distinctValues,"current-filter":o.currentFilter,onApply:h,onClose:_},null,8,[`distinct-values`,`current-filter`])],2112))],4))}});const rt=[`data-col-index`,`onClick`],it=[`onMousedown`,`onDblclick`,`onMouseenter`],at={key:1,class:`gp-grid-loading`},ot={key:2,class:`gp-grid-error`},st={key:3,class:`gp-grid-empty`};var ct=c({__name:`GpGrid`,props:{columns:{},dataSource:{},rowData:{},rowHeight:{},headerHeight:{},overscan:{default:3},sortingEnabled:{type:Boolean,default:!0},darkMode:{type:Boolean,default:!1},wheelDampening:{default:.1},cellRenderers:{default:()=>({})},editRenderers:{default:()=>({})},headerRenderers:{default:()=>({})},cellRenderer:{},editRenderer:{},headerRenderer:{},initialWidth:{},initialHeight:{},highlighting:{}},setup(s,{expose:c}){ne();let l=s,h=g(null),S=y(null),w=y(null),T=y(null),{state:D,applyInstructions:O,reset:A}=q({initialWidth:l.initialWidth,initialHeight:l.initialHeight}),M=t(()=>l.headerHeight??l.rowHeight),P=t(()=>l.columns.map((e,t)=>({column:e,originalIndex:t})).filter(({column:e})=>!e.hidden)),F=t(()=>k(P.value.map(e=>e.column),D.viewportWidth)),I=t(()=>F.value.positions),L=t(()=>F.value.widths),z=t(()=>R(I.value)),te=t(()=>Array.from(D.slots.values())),{handleCellMouseDown:re,handleCellDoubleClick:ie,handleFillHandleMouseDown:H,handleHeaderClick:oe,handleKeyDown:W,handleWheel:G,dragState:K}=Y(S,h,t(()=>l.columns),{activeCell:t(()=>D.activeCell),selectionRange:t(()=>D.selectionRange),editingCell:t(()=>D.editingCell),filterPopupOpen:t(()=>D.filterPopup?.isOpen??!1),rowHeight:l.rowHeight,headerHeight:M.value,columnPositions:I,visibleColumnsWithIndices:P,slots:t(()=>D.slots)}),{fillHandlePosition:J}=X({activeCell:t(()=>D.activeCell),selectionRange:t(()=>D.selectionRange),slots:t(()=>D.slots),columns:t(()=>l.columns),visibleColumnsWithIndices:P,columnPositions:I,columnWidths:L,rowHeight:l.rowHeight});function se(){let e=h.value,t=S.value;!e||!t||t.setViewport(e.scrollTop,e.scrollLeft,e.clientWidth,e.clientHeight)}function ce(e,t){let n=S.value;n&&n.setFilter(e,t)}function Z(){let e=S.value;e&&e.closeFilterPopup()}function Q(e,t){S.value?.input.handleCellMouseEnter(e,t)}function ue(){S.value?.input.handleCellMouseLeave()}function fe(e){return[`gp-grid-row`,...S.value?.highlight?.computeRowClasses(e.rowIndex,e.rowData)??[]].filter(Boolean).join(` `)}function me(e,t,n,r,i){let a=V(e,t,D.editingCell);return[ee(B(e,t,D.activeCell),U(e,t,D.selectionRange),a,ae(e,t,K.value.dragType===`fill`,K.value.fillSourceRange,K.value.fillTarget)),...S.value?.highlight?.computeCombinedCellClasses(e,t,n,r)??[]].filter(Boolean).join(` `)}function $(){return l.dataSource??(l.rowData?N(l.rowData):j([]))}function he(e){T.value&&=(T.value(),null),S.value&&S.value.destroy();let t=new E({columns:l.columns,dataSource:e,rowHeight:l.rowHeight,headerHeight:M.value,overscan:l.overscan,sortingEnabled:l.sortingEnabled,highlighting:l.highlighting});S.value=t,T.value=t.onBatchInstruction(e=>{O(e)}),t.initialize();let n=h.value;n&&t.setViewport(n.scrollTop,n.scrollLeft,n.clientWidth,n.clientHeight)}return f(()=>{let e=$();w.value=e,he(e);let t=h.value;if(t&&typeof ResizeObserver<`u`){let e=new ResizeObserver(()=>{S.value?.setViewport(t.scrollTop,t.scrollLeft,t.clientWidth,t.clientHeight)});e.observe(t),p(()=>{e.disconnect()})}p(()=>{T.value&&=(T.value(),null),S.value&&=(S.value.destroy(),null),w.value&&=(w.value.destroy?.(),null)})}),C([()=>l.dataSource,()=>l.rowData],()=>{let e=$(),t=w.value;t&&t!==e?(t.destroy?.(),A(),w.value=e,he(e)):t||(w.value=e)}),C(()=>l.dataSource,e=>{if(e){let t=e;if(t.subscribe){let e=t.subscribe(()=>{S.value?.refresh()});p(()=>e())}}},{immediate:!0}),c({core:S}),(t,c)=>(m(),i(`div`,{ref_key:`containerRef`,ref:h,class:u([`gp-grid-container`,{"gp-grid-container--dark":s.darkMode}]),style:{width:`100%`,height:`100%`,overflow:`auto`,position:`relative`},tabindex:`0`,onScroll:se,onWheel:c[1]||=e=>x(G)(e,s.wheelDampening),onKeydown:c[2]||=(...e)=>x(W)&&x(W)(...e)},[r(` Content sizer `),a(`div`,{style:d({width:`${Math.max(x(D).contentWidth,z.value)}px`,height:`${Math.max(x(D).contentHeight,M.value)}px`,position:`relative`,minWidth:`100%`})},[r(` Headers `),a(`div`,{class:`gp-grid-header`,style:d({position:`sticky`,top:0,left:0,height:`${M.value}px`,width:`${Math.max(x(D).contentWidth,z.value)}px`,minWidth:`100%`})},[(m(!0),i(e,null,_(P.value,({column:e,originalIndex:t},r)=>(m(),i(`div`,{key:e.colId??e.field,class:`gp-grid-header-cell`,"data-col-index":t,style:d({position:`absolute`,left:`${I.value[r]}px`,top:0,width:`${L.value[r]}px`,height:`${M.value}px`,background:`transparent`}),onClick:e=>x(oe)(t,e)},[(m(),n(v(x(pe)({column:e,colIndex:t,sortDirection:x(D).headers.get(t)?.sortDirection,sortIndex:x(D).headers.get(t)?.sortIndex,sortable:x(D).headers.get(t)?.sortable??!0,filterable:x(D).headers.get(t)?.filterable??!0,hasFilter:x(D).headers.get(t)?.hasFilter??!1,core:S.value,container:h.value,headerRenderers:s.headerRenderers??{},globalHeaderRenderer:s.headerRenderer}))))],12,rt))),128))],4),r(` Row slots `),(m(!0),i(e,null,_(te.value.filter(e=>e.rowIndex>=0),t=>(m(),i(`div`,{key:t.slotId,class:u(fe(t)),style:d({position:`absolute`,top:0,left:0,transform:`translateY(${t.translateY}px)`,width:`${Math.max(x(D).contentWidth,z.value)}px`,height:`${s.rowHeight}px`})},[(m(!0),i(e,null,_(P.value,({column:a,originalIndex:o},c)=>(m(),i(`div`,{key:`${t.slotId}-${o}`,class:u(me(t.rowIndex,o,a,t.rowData,x(D).hoverPosition)),style:d({position:`absolute`,left:`${I.value[c]}px`,top:0,width:`${L.value[c]}px`,height:`${s.rowHeight}px`}),onMousedown:e=>x(re)(t.rowIndex,o,e),onDblclick:()=>x(ie)(t.rowIndex,o),onMouseenter:()=>Q(t.rowIndex,o),onMouseleave:ue},[r(` Edit mode `),x(V)(t.rowIndex,o,x(D).editingCell)&&x(D).editingCell?(m(),n(v(x(de)({column:a,rowData:t.rowData,rowIndex:t.rowIndex,colIndex:o,initialValue:x(D).editingCell.initialValue,core:S.value,editRenderers:s.editRenderers??{},globalEditRenderer:s.editRenderer})),{key:0})):(m(),i(e,{key:1},[r(` View mode `),(m(),n(v(x(le)({column:a,rowData:t.rowData,rowIndex:t.rowIndex,colIndex:o,isActive:x(B)(t.rowIndex,o,x(D).activeCell),isSelected:x(U)(t.rowIndex,o,x(D).selectionRange),isEditing:!1,cellRenderers:s.cellRenderers??{},globalCellRenderer:s.cellRenderer}))))],64))],46,it))),128))],6))),128)),r(` Fill handle `),x(J)&&!x(D).editingCell?(m(),i(`div`,{key:0,class:`gp-grid-fill-handle`,style:d({position:`absolute`,top:`${x(J).top}px`,left:`${x(J).left}px`,zIndex:200}),onMousedown:c[0]||=(...e)=>x(H)&&x(H)(...e)},null,36)):r(`v-if`,!0),r(` Loading indicator `),x(D).isLoading?(m(),i(`div`,at,[...c[3]||=[a(`div`,{class:`gp-grid-loading-spinner`},null,-1),o(` Loading... `,-1)]])):r(`v-if`,!0),r(` Error message `),x(D).error?(m(),i(`div`,ot,` Error: `+b(x(D).error),1)):r(`v-if`,!0),r(` Empty state `),!x(D).isLoading&&!x(D).error&&x(D).totalRows===0?(m(),i(`div`,st,` No data to display `)):r(`v-if`,!0)],4),r(` Filter Popup `),x(D).filterPopup?.isOpen&&x(D).filterPopup.column&&x(D).filterPopup.anchorRect?(m(),n(nt,{key:0,column:x(D).filterPopup.column,"col-index":x(D).filterPopup.colIndex,"anchor-rect":x(D).filterPopup.anchorRect,"distinct-values":x(D).filterPopup.distinctValues,"current-filter":x(D).filterPopup.currentFilter,onApply:ce,onClose:Z},null,8,[`column`,`col-index`,`anchor-rect`,`distinct-values`,`current-filter`])):r(`v-if`,!0)],34))}});function lt(e){ne();let n=g(null),r=g(null),{state:i,applyInstructions:a}=q(),o=t(()=>e.headerHeight??e.rowHeight),s=t(()=>e.columns.map((e,t)=>({column:e,originalIndex:t})).filter(({column:e})=>!e.hidden)),c=t(()=>k(s.value.map(e=>e.column),i.viewportWidth)),l=t(()=>c.value.positions),u=t(()=>c.value.widths),d=t(()=>R(l.value)),m=t(()=>Array.from(i.slots.values())),{handleCellMouseDown:h,handleCellDoubleClick:_,handleFillHandleMouseDown:v,handleHeaderClick:y,handleKeyDown:b,handleWheel:x,dragState:S}=Y(r,n,t(()=>e.columns),{activeCell:t(()=>i.activeCell),selectionRange:t(()=>i.selectionRange),editingCell:t(()=>i.editingCell),filterPopupOpen:t(()=>i.filterPopup?.isOpen??!1),rowHeight:e.rowHeight,headerHeight:o.value,columnPositions:l,visibleColumnsWithIndices:s,slots:t(()=>i.slots)}),w=()=>{let e=n.value,t=r.value;!e||!t||t.setViewport(e.scrollTop,e.scrollLeft,e.clientWidth,e.clientHeight)},T=(e,t)=>{let n=r.value;n&&n.setFilter(e,t)},D=()=>{let e=r.value;e&&e.closeFilterPopup()},O=(e,t)=>{r.value?.input.handleCellMouseEnter(e,t)},A=()=>{r.value?.input.handleCellMouseLeave()};f(()=>{let t=e.dataSource??(e.rowData?N(e.rowData):j([])),i=new E({columns:e.columns,dataSource:t,rowHeight:e.rowHeight,headerHeight:o.value,overscan:e.overscan??3,sortingEnabled:e.sortingEnabled??!0,highlighting:e.highlighting});r.value=i;let s=i.onBatchInstruction(e=>{a(e)});i.initialize();let c=n.value;if(c){i.setViewport(c.scrollTop,c.scrollLeft,c.clientWidth,c.clientHeight);let e=new ResizeObserver(()=>{i.setViewport(c.scrollTop,c.scrollLeft,c.clientWidth,c.clientHeight)});e.observe(c),p(()=>{e.disconnect(),s(),r.value=null})}}),C(()=>e.dataSource,e=>{if(e){let t=e;if(t.subscribe){let e=t.subscribe(()=>{r.value?.refresh()});p(()=>e())}}},{immediate:!0});let{fillHandlePosition:M}=X({activeCell:t(()=>i.activeCell),selectionRange:t(()=>i.selectionRange),slots:t(()=>i.slots),columns:t(()=>e.columns),visibleColumnsWithIndices:s,columnPositions:l,columnWidths:u,rowHeight:e.rowHeight});return{containerRef:n,coreRef:r,state:i,slotsArray:m,totalHeaderHeight:o,columnPositions:l,columnWidths:u,totalWidth:d,fillHandlePosition:M,handleScroll:w,handleCellMouseDown:h,handleCellDoubleClick:_,handleFillHandleMouseDown:v,handleHeaderClick:y,handleKeyDown:b,handleWheel:x,handleFilterApply:T,handleFilterPopupClose:D,handleCellMouseEnter:O,handleCellMouseLeave:A,dragState:S,isCellSelected:U,isCellActive:B,isCellEditing:V,isCellInFillPreview:ae,buildCellClasses:ee}}export{ct as GpGrid,ct as default,T as GridCore,D as buildCellClasses,O as calculateColumnPositions,A as createClientDataSource,M as createDataSourceFromArray,G as createInitialState,P as createMutableClientDataSource,F as createServerDataSource,I as findColumnAtX,Q as getCellValue,L as getTotalWidth,z as gridStyles,te as injectStyles,re as isCellActive,ie as isCellEditing,H as isCellInFillPreview,oe as isCellSelected,W as isRowVisible,le as renderCell,de as renderEditCell,pe as renderHeader,J as useAutoScroll,X as useFillHandle,$ as useFilterConditions,me as useFilterPopup,lt as useGpGrid,q as useGridState,Y as useInputHandler};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gp-grid-vue",
3
3
  "description": "A high-performance Vue 3 data grid component with virtual scrolling, cell selection, sorting, filtering, and Excel-like editing",
4
- "version": "0.5.3",
4
+ "version": "0.7.0",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
@@ -43,7 +43,7 @@
43
43
  "nuxt3"
44
44
  ],
45
45
  "dependencies": {
46
- "gp-grid-core": "0.5.3"
46
+ "gp-grid-core": "0.7.0"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "vue": "^3.4.0"