gp-grid-react 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -28,6 +28,37 @@ interface CellRange {
28
28
  endRow: number;
29
29
  endCol: number;
30
30
  }
31
+ /** Selection state */
32
+ interface SelectionState {
33
+ /** Active cell position */
34
+ activeCell: CellPosition | null;
35
+ /** Selection range */
36
+ range: CellRange | null;
37
+ /** Anchor cell for shift-extend selection */
38
+ anchor: CellPosition | null;
39
+ /** Whether selection mode is active (ctrl held) */
40
+ selectionMode: boolean;
41
+ }
42
+ /** Edit state */
43
+ interface EditState {
44
+ /** Row index */
45
+ row: number;
46
+ /** Column index */
47
+ col: number;
48
+ /** Initial value */
49
+ initialValue: CellValue;
50
+ /** Current value */
51
+ currentValue: CellValue;
52
+ }
53
+ /** Fill handle state */
54
+ interface FillHandleState {
55
+ /** Source range */
56
+ sourceRange: CellRange;
57
+ /** Target row */
58
+ targetRow: number;
59
+ /** Target column */
60
+ targetCol: number;
61
+ }
31
62
  //#endregion
32
63
  //#region ../core/src/types/columns.d.ts
33
64
  /** Column definition */
@@ -124,6 +155,8 @@ interface DataSourceResponse<TData = Row> {
124
155
  /** Data source interface */
125
156
  interface DataSource<TData = Row> {
126
157
  fetch(request: DataSourceRequest): Promise<DataSourceResponse<TData>>;
158
+ /** Optional cleanup method to release resources */
159
+ destroy?: () => void;
127
160
  }
128
161
  //#endregion
129
162
  //#region ../core/src/types/instructions.d.ts
@@ -295,6 +328,10 @@ CreateSlotInstruction | DestroySlotInstruction | AssignSlotInstruction | MoveSlo
295
328
  /** Fill handle */ | StartFillInstruction | UpdateFillInstruction | CommitFillInstruction | CancelFillInstruction
296
329
  /** Data */ | DataLoadingInstruction | DataLoadedInstruction | DataErrorInstruction
297
330
  /** Transactions */ | RowsAddedInstruction | RowsRemovedInstruction | RowsUpdatedInstruction | TransactionProcessedInstruction;
331
+ /** Instruction listener: Single instruction Listener that receives a single instruction, used by frameworks to update their state */
332
+ type InstructionListener = (instruction: GridInstruction) => void;
333
+ /** Batch instruction listener: Batch instruction Listener that receives an array of instructions, used by frameworks to update their state */
334
+ type BatchInstructionListener = (instructions: GridInstruction[]) => void;
298
335
  //#endregion
299
336
  //#region ../core/src/types/renderers.d.ts
300
337
  /** Cell renderer params */
@@ -349,6 +386,474 @@ interface HeaderRendererParams {
349
386
  onFilterClick: () => void;
350
387
  }
351
388
  //#endregion
389
+ //#region ../core/src/types/options.d.ts
390
+ /** Grid core options */
391
+ interface GridCoreOptions<TData = Row> {
392
+ /** Column definitions */
393
+ columns: ColumnDefinition[];
394
+ /** Data source */
395
+ dataSource: DataSource<TData>;
396
+ /** Row height */
397
+ rowHeight: number;
398
+ /** Header height: Default to row height */
399
+ headerHeight?: number;
400
+ /** Overscan: How many rows to render outside the viewport */
401
+ overscan?: number;
402
+ /** Enable/disable sorting globally. Default: true */
403
+ sortingEnabled?: boolean;
404
+ /** Debounce time for transactions in ms. Default 50. Set to 0 for sync. */
405
+ transactionDebounceMs?: number;
406
+ /** Function to extract unique ID from row. Required for mutations. */
407
+ getRowId?: (row: TData) => RowId;
408
+ }
409
+ //#endregion
410
+ //#region ../core/src/types/input.d.ts
411
+ /** Framework-agnostic pointer/mouse event data */
412
+ interface PointerEventData {
413
+ /** X coordinate relative to viewport */
414
+ clientX: number;
415
+ /** Y coordinate relative to viewport */
416
+ clientY: number;
417
+ /** Mouse button (0 = left, 1 = middle, 2 = right) */
418
+ button: number;
419
+ /** Whether Shift key is pressed */
420
+ shiftKey: boolean;
421
+ /** Whether Ctrl key is pressed */
422
+ ctrlKey: boolean;
423
+ /** Whether Meta/Command key is pressed */
424
+ metaKey: boolean;
425
+ }
426
+ /** Framework-agnostic keyboard event data */
427
+ interface KeyEventData {
428
+ /** Key value (e.g., 'Enter', 'ArrowUp', 'a') */
429
+ key: string;
430
+ /** Whether Shift key is pressed */
431
+ shiftKey: boolean;
432
+ /** Whether Ctrl key is pressed */
433
+ ctrlKey: boolean;
434
+ /** Whether Meta/Command key is pressed */
435
+ metaKey: boolean;
436
+ }
437
+ /** Container bounds and scroll position */
438
+ interface ContainerBounds {
439
+ /** Top position relative to viewport */
440
+ top: number;
441
+ /** Left position relative to viewport */
442
+ left: number;
443
+ /** Container width */
444
+ width: number;
445
+ /** Container height */
446
+ height: number;
447
+ /** Current scroll top position */
448
+ scrollTop: number;
449
+ /** Current scroll left position */
450
+ scrollLeft: number;
451
+ }
452
+ /** Result from mouse/pointer input handlers */
453
+ interface InputResult {
454
+ /** Whether to call preventDefault() on the event */
455
+ preventDefault: boolean;
456
+ /** Whether to call stopPropagation() on the event */
457
+ stopPropagation: boolean;
458
+ /** Whether framework should focus the container element */
459
+ focusContainer?: boolean;
460
+ /** Type of drag operation to start (framework manages global listeners) */
461
+ startDrag?: "selection" | "fill";
462
+ }
463
+ /** Result from keyboard input handler */
464
+ interface KeyboardResult {
465
+ /** Whether to call preventDefault() on the event */
466
+ preventDefault: boolean;
467
+ /** Cell to scroll into view (if navigation occurred) */
468
+ scrollToCell?: CellPosition;
469
+ }
470
+ /** Result from drag move handler */
471
+ interface DragMoveResult {
472
+ /** Target row index */
473
+ targetRow: number;
474
+ /** Target column index */
475
+ targetCol: number;
476
+ /** Auto-scroll deltas (null if no auto-scroll needed) */
477
+ autoScroll: {
478
+ dx: number;
479
+ dy: number;
480
+ } | null;
481
+ }
482
+ /** Options for InputHandler constructor */
483
+ interface InputHandlerDeps {
484
+ /** Get header height */
485
+ getHeaderHeight: () => number;
486
+ /** Get row height */
487
+ getRowHeight: () => number;
488
+ /** Get column positions array */
489
+ getColumnPositions: () => number[];
490
+ /** Get column count */
491
+ getColumnCount: () => number;
492
+ }
493
+ /** Current drag state for UI rendering */
494
+ interface DragState {
495
+ /** Whether any drag operation is active */
496
+ isDragging: boolean;
497
+ /** Type of active drag operation */
498
+ dragType: "selection" | "fill" | null;
499
+ /** Source range for fill operations */
500
+ fillSourceRange: CellRange | null;
501
+ /** Current fill target position */
502
+ fillTarget: {
503
+ row: number;
504
+ col: number;
505
+ } | null;
506
+ }
507
+ //#endregion
508
+ //#region ../core/src/selection.d.ts
509
+ type Direction = "up" | "down" | "left" | "right";
510
+ interface SelectionManagerOptions {
511
+ getRowCount: () => number;
512
+ getColumnCount: () => number;
513
+ getCellValue: (row: number, col: number) => CellValue;
514
+ getRowData: (row: number) => Row | undefined;
515
+ getColumn: (col: number) => ColumnDefinition | undefined;
516
+ }
517
+ /**
518
+ * Manages Excel-style cell selection, keyboard navigation, and clipboard operations.
519
+ */
520
+ declare class SelectionManager {
521
+ private state;
522
+ private options;
523
+ private listeners;
524
+ constructor(options: SelectionManagerOptions);
525
+ onInstruction(listener: InstructionListener): () => void;
526
+ private emit;
527
+ getState(): SelectionState;
528
+ getActiveCell(): CellPosition | null;
529
+ getSelectionRange(): CellRange | null;
530
+ isSelected(row: number, col: number): boolean;
531
+ isActiveCell(row: number, col: number): boolean;
532
+ /**
533
+ * Start a selection at the given cell.
534
+ * @param cell - The cell to select
535
+ * @param opts.shift - Extend selection from anchor (range select)
536
+ * @param opts.ctrl - Toggle selection mode
537
+ */
538
+ startSelection(cell: CellPosition, opts?: {
539
+ shift?: boolean;
540
+ ctrl?: boolean;
541
+ }): void;
542
+ /**
543
+ * Move focus in a direction, optionally extending the selection.
544
+ */
545
+ moveFocus(direction: Direction, extend?: boolean): void;
546
+ /**
547
+ * Select all cells in the grid (Ctrl+A).
548
+ */
549
+ selectAll(): void;
550
+ /**
551
+ * Clear the current selection.
552
+ */
553
+ clearSelection(): void;
554
+ /**
555
+ * Set the active cell directly.
556
+ */
557
+ setActiveCell(row: number, col: number): void;
558
+ /**
559
+ * Set the selection range directly.
560
+ */
561
+ setSelectionRange(range: CellRange): void;
562
+ /**
563
+ * Get the data from the currently selected cells as a 2D array.
564
+ */
565
+ getSelectedData(): CellValue[][];
566
+ /**
567
+ * Copy the selected data to the clipboard (Ctrl+C).
568
+ */
569
+ copySelectionToClipboard(): Promise<void>;
570
+ /**
571
+ * Clean up resources for garbage collection.
572
+ */
573
+ destroy(): void;
574
+ private clampPosition;
575
+ }
576
+ //#endregion
577
+ //#region ../core/src/fill.d.ts
578
+ interface FillManagerOptions {
579
+ getRowCount: () => number;
580
+ getColumnCount: () => number;
581
+ getCellValue: (row: number, col: number) => CellValue;
582
+ getColumn: (col: number) => ColumnDefinition | undefined;
583
+ setCellValue: (row: number, col: number, value: CellValue) => void;
584
+ }
585
+ /**
586
+ * Manages fill handle operations including pattern detection and auto-fill.
587
+ */
588
+ declare class FillManager {
589
+ private state;
590
+ private options;
591
+ private listeners;
592
+ constructor(options: FillManagerOptions);
593
+ onInstruction(listener: InstructionListener): () => void;
594
+ private emit;
595
+ getState(): FillHandleState | null;
596
+ isActive(): boolean;
597
+ /**
598
+ * Start a fill drag operation from a source range.
599
+ */
600
+ startFillDrag(sourceRange: CellRange): void;
601
+ /**
602
+ * Update the fill drag target position.
603
+ */
604
+ updateFillDrag(targetRow: number, targetCol: number): void;
605
+ /**
606
+ * Commit the fill operation - apply pattern to target cells.
607
+ */
608
+ commitFillDrag(): void;
609
+ /**
610
+ * Cancel the fill operation.
611
+ */
612
+ cancelFillDrag(): void;
613
+ /**
614
+ * Clean up resources for garbage collection.
615
+ */
616
+ destroy(): void;
617
+ /**
618
+ * Calculate the values to fill based on source pattern.
619
+ */
620
+ private calculateFilledCells;
621
+ private getSourceColumnValues;
622
+ private detectPattern;
623
+ private applyPattern;
624
+ }
625
+ //#endregion
626
+ //#region ../core/src/input-handler.d.ts
627
+ declare class InputHandler<TData extends Row = Row> {
628
+ private core;
629
+ private deps;
630
+ private isDraggingSelection;
631
+ private isDraggingFill;
632
+ private fillSourceRange;
633
+ private fillTarget;
634
+ constructor(core: GridCore<TData>, deps: InputHandlerDeps);
635
+ /**
636
+ * Update dependencies (called when options change)
637
+ */
638
+ updateDeps(deps: Partial<InputHandlerDeps>): void;
639
+ /**
640
+ * Get current drag state for UI rendering
641
+ */
642
+ getDragState(): DragState;
643
+ /**
644
+ * Handle cell mouse down event
645
+ */
646
+ handleCellMouseDown(rowIndex: number, colIndex: number, event: PointerEventData): InputResult;
647
+ /**
648
+ * Handle cell double click event (start editing)
649
+ */
650
+ handleCellDoubleClick(rowIndex: number, colIndex: number): void;
651
+ /**
652
+ * Handle fill handle mouse down event
653
+ */
654
+ handleFillHandleMouseDown(activeCell: CellPosition | null, selectionRange: CellRange | null, _event: PointerEventData): InputResult;
655
+ /**
656
+ * Handle header click event (cycle sort direction)
657
+ */
658
+ handleHeaderClick(colId: string, addToExisting: boolean): void;
659
+ /**
660
+ * Start selection drag (called by framework after handleCellMouseDown returns startDrag: 'selection')
661
+ */
662
+ startSelectionDrag(): void;
663
+ /**
664
+ * Handle drag move event (selection or fill)
665
+ */
666
+ handleDragMove(event: PointerEventData, bounds: ContainerBounds): DragMoveResult | null;
667
+ /**
668
+ * Handle drag end event
669
+ */
670
+ handleDragEnd(): void;
671
+ /**
672
+ * Handle wheel event with dampening for large datasets
673
+ * Returns scroll deltas or null if no dampening needed
674
+ */
675
+ handleWheel(deltaY: number, deltaX: number, dampening: number): {
676
+ dy: number;
677
+ dx: number;
678
+ } | null;
679
+ /**
680
+ * Handle keyboard event
681
+ */
682
+ handleKeyDown(event: KeyEventData, activeCell: CellPosition | null, editingCell: {
683
+ row: number;
684
+ col: number;
685
+ } | null, filterPopupOpen: boolean): KeyboardResult;
686
+ /**
687
+ * Find column index at a given X coordinate
688
+ */
689
+ private findColumnAtX;
690
+ /**
691
+ * Calculate auto-scroll deltas based on mouse position
692
+ */
693
+ private calculateAutoScroll;
694
+ }
695
+ //#endregion
696
+ //#region ../core/src/grid-core.d.ts
697
+ declare class GridCore<TData extends Row = Row> {
698
+ private columns;
699
+ private dataSource;
700
+ private rowHeight;
701
+ private headerHeight;
702
+ private overscan;
703
+ private sortingEnabled;
704
+ private scrollTop;
705
+ private scrollLeft;
706
+ private viewportWidth;
707
+ private viewportHeight;
708
+ private cachedRows;
709
+ private totalRows;
710
+ private currentPageIndex;
711
+ private pageSize;
712
+ private sortModel;
713
+ private filterModel;
714
+ private openFilterColIndex;
715
+ readonly selection: SelectionManager;
716
+ readonly fill: FillManager;
717
+ readonly input: InputHandler<TData>;
718
+ private readonly slotPool;
719
+ private readonly editManager;
720
+ private columnPositions;
721
+ private listeners;
722
+ private batchListeners;
723
+ private naturalContentHeight;
724
+ private virtualContentHeight;
725
+ private scrollRatio;
726
+ constructor(options: GridCoreOptions<TData>);
727
+ onInstruction(listener: InstructionListener): () => void;
728
+ /**
729
+ * Subscribe to batched instructions for efficient React state updates.
730
+ * Batch listeners receive arrays of instructions instead of individual ones.
731
+ */
732
+ onBatchInstruction(listener: BatchInstructionListener): () => void;
733
+ private emit;
734
+ private emitBatch;
735
+ /**
736
+ * Initialize the grid and load initial data.
737
+ */
738
+ initialize(): Promise<void>;
739
+ /**
740
+ * Update viewport measurements and sync slots.
741
+ * When scroll virtualization is active, maps the DOM scroll position to the actual row position.
742
+ */
743
+ setViewport(scrollTop: number, scrollLeft: number, width: number, height: number): void;
744
+ private fetchData;
745
+ private fetchAllData;
746
+ setSort(colId: string, direction: SortDirection | null, addToExisting?: boolean): Promise<void>;
747
+ setFilter(colId: string, filter: ColumnFilterModel | string | null): Promise<void>;
748
+ /**
749
+ * Check if a column has an active filter
750
+ */
751
+ hasActiveFilter(colId: string): boolean;
752
+ /**
753
+ * Check if a column is sortable
754
+ */
755
+ isColumnSortable(colIndex: number): boolean;
756
+ /**
757
+ * Check if a column is filterable
758
+ */
759
+ isColumnFilterable(colIndex: number): boolean;
760
+ /**
761
+ * Get distinct values for a column (for filter dropdowns)
762
+ * For array-type columns (like tags), each unique array combination is returned.
763
+ * Arrays are sorted internally for consistent comparison.
764
+ * Limited to MAX_DISTINCT_VALUES to avoid performance issues with large datasets.
765
+ */
766
+ getDistinctValuesForColumn(colId: string, maxValues?: number): CellValue[];
767
+ /**
768
+ * Open filter popup for a column (toggles if already open for same column)
769
+ */
770
+ openFilterPopup(colIndex: number, anchorRect: {
771
+ top: number;
772
+ left: number;
773
+ width: number;
774
+ height: number;
775
+ }): void;
776
+ /**
777
+ * Close filter popup
778
+ */
779
+ closeFilterPopup(): void;
780
+ getSortModel(): SortModel[];
781
+ getFilterModel(): FilterModel;
782
+ startEdit(row: number, col: number): void;
783
+ updateEditValue(value: CellValue): void;
784
+ commitEdit(): void;
785
+ cancelEdit(): void;
786
+ getEditState(): EditState | null;
787
+ getCellValue(row: number, col: number): CellValue;
788
+ setCellValue(row: number, col: number, value: CellValue): void;
789
+ private getFieldValue;
790
+ private setFieldValue;
791
+ private computeColumnPositions;
792
+ private emitContentSize;
793
+ private emitHeaders;
794
+ getColumns(): ColumnDefinition[];
795
+ getColumnPositions(): number[];
796
+ getRowCount(): number;
797
+ getRowHeight(): number;
798
+ getHeaderHeight(): number;
799
+ getTotalWidth(): number;
800
+ getTotalHeight(): number;
801
+ /**
802
+ * Check if scroll scaling is active (large datasets exceeding browser scroll limits).
803
+ * When scaling is active, scrollRatio < 1 and scroll positions are compressed.
804
+ */
805
+ isScalingActive(): boolean;
806
+ /**
807
+ * Get the natural (uncapped) content height.
808
+ * Useful for debugging or displaying actual content size.
809
+ */
810
+ getNaturalHeight(): number;
811
+ /**
812
+ * Get the scroll ratio used for scroll virtualization.
813
+ * Returns 1 when no virtualization is needed, < 1 when content exceeds browser limits.
814
+ */
815
+ getScrollRatio(): number;
816
+ /**
817
+ * Get the visible row range (excluding overscan).
818
+ * Returns the first and last row indices that are actually visible in the viewport.
819
+ * Includes partially visible rows to avoid false positives when clicking on edge rows.
820
+ */
821
+ getVisibleRowRange(): {
822
+ start: number;
823
+ end: number;
824
+ };
825
+ /**
826
+ * Get the scroll position needed to bring a row into view.
827
+ * Accounts for scroll scaling when active.
828
+ */
829
+ getScrollTopForRow(rowIndex: number): number;
830
+ /**
831
+ * Get the row index at a given viewport Y position.
832
+ * Accounts for scroll scaling when active.
833
+ * @param viewportY Y position in viewport (physical pixels below header, NOT including scroll)
834
+ * @param virtualScrollTop Current scroll position from container.scrollTop (virtual/scaled)
835
+ */
836
+ getRowIndexAtDisplayY(viewportY: number, virtualScrollTop: number): number;
837
+ getRowData(rowIndex: number): TData | undefined;
838
+ /**
839
+ * Refresh data from the data source.
840
+ */
841
+ refresh(): Promise<void>;
842
+ /**
843
+ * Refresh slot display without refetching data.
844
+ * Useful after in-place data modifications like fill operations.
845
+ */
846
+ refreshSlotData(): void;
847
+ /**
848
+ * Update the data source and refresh.
849
+ */
850
+ setDataSource(dataSource: DataSource<TData>): Promise<void>;
851
+ /**
852
+ * Update columns and recompute layout.
853
+ */
854
+ setColumns(columns: ColumnDefinition[]): void;
855
+ }
856
+ //#endregion
352
857
  //#region ../core/src/data-source/client-data-source.d.ts
353
858
  interface ClientDataSourceOptions<TData> {
354
859
  /** Custom field accessor for nested properties */
@@ -411,6 +916,8 @@ interface MutableDataSource<TData = Row> extends DataSource<TData> {
411
916
  getTotalRowCount(): number;
412
917
  /** Subscribe to data change notifications. Returns unsubscribe function. */
413
918
  subscribe(listener: DataChangeListener): () => void;
919
+ /** Clear all data from the data source. */
920
+ clear(): void;
414
921
  }
415
922
  interface MutableClientDataSourceOptions<TData> {
416
923
  /** Function to extract unique ID from row. Required. */
@@ -429,6 +936,11 @@ interface MutableClientDataSourceOptions<TData> {
429
936
  declare function createMutableClientDataSource<TData extends Row = Row>(data: TData[], options: MutableClientDataSourceOptions<TData>): MutableDataSource<TData>;
430
937
  //#endregion
431
938
  //#region src/types.d.ts
939
+ /** Ref handle exposed by the Grid component */
940
+ interface GridRef<TData extends Row = Row> {
941
+ /** Access to the underlying GridCore instance */
942
+ core: GridCore<TData> | null;
943
+ }
432
944
  /** React cell renderer: A function that renders a cell */
433
945
  type ReactCellRenderer = (params: CellRendererParams) => React.ReactNode;
434
946
  /** React edit renderer: A function that renders the cell while in edit mode */
@@ -471,6 +983,8 @@ interface GridProps<TData extends Row = Row> {
471
983
  initialWidth?: number;
472
984
  /** Initial viewport height for SSR (pixels). ResizeObserver takes over on client. */
473
985
  initialHeight?: number;
986
+ /** Optional ref to access GridCore API */
987
+ gridRef?: React.MutableRefObject<GridRef<TData> | null>;
474
988
  }
475
989
  //#endregion
476
990
  //#region src/Grid.d.ts
@@ -481,4 +995,4 @@ interface GridProps<TData extends Row = Row> {
481
995
  */
482
996
  declare function Grid<TData extends Row = Row>(props: GridProps<TData>): React$1.ReactNode;
483
997
  //#endregion
484
- export { type CellDataType, type CellPosition, type CellRange, type CellRendererParams, type CellValue, type ColumnDefinition, type DataSource, type DataSourceRequest, type DataSourceResponse, type EditRendererParams, type FilterModel, Grid, type GridInstruction, type GridProps, type HeaderRendererParams, type MutableDataSource, type ReactCellRenderer, type ReactEditRenderer, type ReactHeaderRenderer, type Row, type SortDirection, type SortModel, createClientDataSource, createDataSourceFromArray, createMutableClientDataSource, createServerDataSource };
998
+ export { type CellDataType, type CellPosition, type CellRange, type CellRendererParams, type CellValue, type ColumnDefinition, type ColumnFilterModel, type DataSource, type DataSourceRequest, type DataSourceResponse, type EditRendererParams, type FilterCondition, type FilterModel, Grid, GridCore, type GridInstruction, type GridProps, type GridRef, type HeaderRendererParams, type MutableDataSource, type ReactCellRenderer, type ReactEditRenderer, type ReactHeaderRenderer, type Row, type SortDirection, type SortModel, createClientDataSource, createDataSourceFromArray, createMutableClientDataSource, createServerDataSource };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import e,{useCallback as t,useEffect as n,useMemo as r,useReducer as i,useRef as a,useState as o}from"react";import{GridCore as s,buildCellClasses as c,calculateScaledColumnPositions as l,createClientDataSource as u,createClientDataSource as d,createDataSourceFromArray as f,createDataSourceFromArray as p,createMutableClientDataSource as m,createServerDataSource as h,getTotalWidth as g,injectStyles as _,isCellActive as v,isCellEditing as y,isCellInFillPreview as b,isCellSelected as x}from"gp-grid-core";import{Fragment as S,jsx as C,jsxs as w}from"react/jsx-runtime";const T=[{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`}];function E({distinctValues:e,currentFilter:n,onApply:i,onClose:a}){let s=t(e=>Array.isArray(e)?e.join(`, `):String(e??``),[]),c=r(()=>{let t=e.filter(e=>e!=null&&e!==``&&!(Array.isArray(e)&&e.length===0)).map(e=>s(e));return Array.from(new Set(t)).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`})})},[e,s]),l=c.length>100,[u,d]=o(r(()=>{if(!n?.conditions[0])return l?`condition`:`values`;let e=n.conditions[0];return e.selectedValues&&e.selectedValues.size>0?`values`:`condition`},[n,l])),f=r(()=>n?.conditions[0]?n.conditions[0].selectedValues??new Set:new Set,[n]),p=r(()=>n?.conditions[0]?n.conditions[0].includeBlank??!0:!0,[n]),[m,h]=o(``),[g,_]=o(f),[v,y]=o(p),[b,x]=o(r(()=>{if(!n?.conditions.length)return[{operator:`contains`,value:``,nextOperator:`and`}];let e=n.conditions[0];if(e.selectedValues&&e.selectedValues.size>0)return[{operator:`contains`,value:``,nextOperator:`and`}];let t=n.combination??`and`;return n.conditions.map(e=>{let n=e;return{operator:n.operator,value:n.value??``,nextOperator:n.nextOperator??t}})},[n])),E=r(()=>{if(!m)return c;let e=m.toLowerCase();return c.filter(t=>t.toLowerCase().includes(e))},[c,m]),D=r(()=>e.some(e=>e==null||e===``),[e]),O=r(()=>E.every(e=>g.has(e))&&(!D||v),[E,g,D,v]),k=t(()=>{_(new Set(E)),D&&y(!0)},[E,D]),A=t(()=>{_(new Set),y(!1)},[]),j=t(e=>{_(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},[]),M=t((e,t)=>{x(n=>{let r=[...n];return r[e]={...r[e],...t},r})},[]),N=t(()=>{x(e=>[...e,{operator:`contains`,value:``,nextOperator:`and`}])},[]),P=t(e=>{x(t=>t.filter((t,n)=>n!==e))},[]),F=t(()=>{if(u===`values`){if(c.every(e=>g.has(e))&&(!D||v)){i(null);return}i({conditions:[{type:`text`,operator:`equals`,selectedValues:g,includeBlank:v}],combination:`and`})}else{let e=b.filter(e=>e.operator===`blank`||e.operator===`notBlank`?!0:e.value.trim()!==``);if(e.length===0){i(null);return}i({conditions:e.map(e=>({type:`text`,operator:e.operator,value:e.value,nextOperator:e.nextOperator})),combination:`and`})}},[u,c,g,v,D,b,i]),I=t(()=>{i(null)},[i]);return w(`div`,{className:`gp-grid-filter-content gp-grid-filter-text`,children:[!l&&w(`div`,{className:`gp-grid-filter-mode-toggle`,children:[C(`button`,{type:`button`,className:u===`values`?`active`:``,onClick:()=>d(`values`),children:`Values`}),C(`button`,{type:`button`,className:u===`condition`?`active`:``,onClick:()=>d(`condition`),children:`Condition`})]}),l&&u===`condition`&&w(`div`,{className:`gp-grid-filter-info`,children:[`Too many unique values (`,c.length,`). Use conditions to filter.`]}),u===`values`&&w(S,{children:[C(`input`,{className:`gp-grid-filter-search`,type:`text`,placeholder:`Search...`,value:m,onChange:e=>h(e.target.value),autoFocus:!0}),w(`div`,{className:`gp-grid-filter-actions`,children:[C(`button`,{type:`button`,onClick:k,disabled:O,children:`Select All`}),C(`button`,{type:`button`,onClick:A,children:`Deselect All`})]}),w(`div`,{className:`gp-grid-filter-list`,children:[D&&w(`label`,{className:`gp-grid-filter-option`,children:[C(`input`,{type:`checkbox`,checked:v,onChange:()=>y(!v)}),C(`span`,{className:`gp-grid-filter-blank`,children:`(Blanks)`})]}),E.map(e=>w(`label`,{className:`gp-grid-filter-option`,children:[C(`input`,{type:`checkbox`,checked:g.has(e),onChange:()=>j(e)}),C(`span`,{children:e})]},e))]})]}),u===`condition`&&w(S,{children:[b.map((e,t)=>w(`div`,{className:`gp-grid-filter-condition`,children:[t>0&&w(`div`,{className:`gp-grid-filter-combination`,children:[C(`button`,{type:`button`,className:b[t-1]?.nextOperator===`and`?`active`:``,onClick:()=>M(t-1,{nextOperator:`and`}),children:`AND`}),C(`button`,{type:`button`,className:b[t-1]?.nextOperator===`or`?`active`:``,onClick:()=>M(t-1,{nextOperator:`or`}),children:`OR`})]}),w(`div`,{className:`gp-grid-filter-row`,children:[C(`select`,{value:e.operator,onChange:e=>M(t,{operator:e.target.value}),autoFocus:t===0,children:T.map(e=>C(`option`,{value:e.value,children:e.label},e.value))}),e.operator!==`blank`&&e.operator!==`notBlank`&&C(`input`,{type:`text`,value:e.value,onChange:e=>M(t,{value:e.target.value}),placeholder:`Value`,className:`gp-grid-filter-text-input`}),b.length>1&&C(`button`,{type:`button`,className:`gp-grid-filter-remove`,onClick:()=>P(t),children:`×`})]})]},t)),C(`button`,{type:`button`,className:`gp-grid-filter-add`,onClick:N,children:`+ Add condition`})]}),w(`div`,{className:`gp-grid-filter-buttons`,children:[C(`button`,{type:`button`,className:`gp-grid-filter-btn-clear`,onClick:I,children:`Clear`}),C(`button`,{type:`button`,className:`gp-grid-filter-btn-apply`,onClick:F,children:`Apply`})]})]})}const D=[{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`}];function O({currentFilter:e,onApply:n,onClose:i}){let[a,s]=o(r(()=>{if(!e?.conditions.length)return[{operator:`=`,value:``,valueTo:``,nextOperator:`and`}];let t=e.combination??`and`;return e.conditions.map(e=>{let n=e;return{operator:n.operator,value:n.value==null?``:String(n.value),valueTo:n.valueTo==null?``:String(n.valueTo),nextOperator:n.nextOperator??t}})},[e])),c=t((e,t)=>{s(n=>{let r=[...n];return r[e]={...r[e],...t},r})},[]),l=t(()=>{s(e=>[...e,{operator:`=`,value:``,valueTo:``,nextOperator:`and`}])},[]),u=t(e=>{s(t=>t.filter((t,n)=>n!==e))},[]),d=t(()=>{let e=a.filter(e=>e.operator===`blank`||e.operator===`notBlank`?!0:e.operator===`between`?e.value!==``&&e.valueTo!==``:e.value!==``);if(e.length===0){n(null);return}n({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`})},[a,n]),f=t(()=>{n(null)},[n]);return w(`div`,{className:`gp-grid-filter-content gp-grid-filter-number`,children:[a.map((e,t)=>w(`div`,{className:`gp-grid-filter-condition`,children:[t>0&&w(`div`,{className:`gp-grid-filter-combination`,children:[C(`button`,{type:`button`,className:a[t-1]?.nextOperator===`and`?`active`:``,onClick:()=>c(t-1,{nextOperator:`and`}),children:`AND`}),C(`button`,{type:`button`,className:a[t-1]?.nextOperator===`or`?`active`:``,onClick:()=>c(t-1,{nextOperator:`or`}),children:`OR`})]}),w(`div`,{className:`gp-grid-filter-row`,children:[C(`select`,{value:e.operator,onChange:e=>c(t,{operator:e.target.value}),children:D.map(e=>C(`option`,{value:e.value,children:e.label},e.value))}),e.operator!==`blank`&&e.operator!==`notBlank`&&C(`input`,{type:`number`,value:e.value,onChange:e=>c(t,{value:e.target.value}),placeholder:`Value`}),e.operator===`between`&&w(S,{children:[C(`span`,{className:`gp-grid-filter-to`,children:`to`}),C(`input`,{type:`number`,value:e.valueTo,onChange:e=>c(t,{valueTo:e.target.value}),placeholder:`Value`})]}),a.length>1&&C(`button`,{type:`button`,className:`gp-grid-filter-remove`,onClick:()=>u(t),children:`×`})]})]},t)),C(`button`,{type:`button`,className:`gp-grid-filter-add`,onClick:l,children:`+ Add condition`}),w(`div`,{className:`gp-grid-filter-buttons`,children:[C(`button`,{type:`button`,className:`gp-grid-filter-btn-clear`,onClick:f,children:`Clear`}),C(`button`,{type:`button`,className:`gp-grid-filter-btn-apply`,onClick:d,children:`Apply`})]})]})}const k=[{value:`=`,label:`=`},{value:`!=`,label:`≠`},{value:`>`,label:`>`},{value:`<`,label:`<`},{value:`between`,label:`↔`},{value:`blank`,label:`Is blank`},{value:`notBlank`,label:`Not blank`}];function A(e){if(!e)return``;let t=typeof e==`string`?new Date(e):e;return isNaN(t.getTime())?``:t.toISOString().split(`T`)[0]}function j({currentFilter:e,onApply:n,onClose:i}){let[a,s]=o(r(()=>{if(!e?.conditions.length)return[{operator:`=`,value:``,valueTo:``,nextOperator:`and`}];let t=e.combination??`and`;return e.conditions.map(e=>{let n=e;return{operator:n.operator,value:A(n.value),valueTo:A(n.valueTo),nextOperator:n.nextOperator??t}})},[e])),c=t((e,t)=>{s(n=>{let r=[...n];return r[e]={...r[e],...t},r})},[]),l=t(()=>{s(e=>[...e,{operator:`=`,value:``,valueTo:``,nextOperator:`and`}])},[]),u=t(e=>{s(t=>t.filter((t,n)=>n!==e))},[]),d=t(()=>{let e=a.filter(e=>e.operator===`blank`||e.operator===`notBlank`?!0:e.operator===`between`?e.value!==``&&e.valueTo!==``:e.value!==``);if(e.length===0){n(null);return}n({conditions:e.map(e=>({type:`date`,operator:e.operator,value:e.value||void 0,valueTo:e.valueTo||void 0,nextOperator:e.nextOperator})),combination:`and`})},[a,n]),f=t(()=>{n(null)},[n]);return w(`div`,{className:`gp-grid-filter-content gp-grid-filter-date`,children:[a.map((e,t)=>w(`div`,{className:`gp-grid-filter-condition`,children:[t>0&&w(`div`,{className:`gp-grid-filter-combination`,children:[C(`button`,{type:`button`,className:a[t-1]?.nextOperator===`and`?`active`:``,onClick:()=>c(t-1,{nextOperator:`and`}),children:`AND`}),C(`button`,{type:`button`,className:a[t-1]?.nextOperator===`or`?`active`:``,onClick:()=>c(t-1,{nextOperator:`or`}),children:`OR`})]}),w(`div`,{className:`gp-grid-filter-row`,children:[C(`select`,{value:e.operator,onChange:e=>c(t,{operator:e.target.value}),children:k.map(e=>C(`option`,{value:e.value,children:e.label},e.value))}),e.operator!==`blank`&&e.operator!==`notBlank`&&C(`input`,{type:`date`,value:e.value,onChange:e=>c(t,{value:e.target.value})}),e.operator===`between`&&w(S,{children:[C(`span`,{className:`gp-grid-filter-to`,children:`to`}),C(`input`,{type:`date`,value:e.valueTo,onChange:e=>c(t,{valueTo:e.target.value})})]}),a.length>1&&C(`button`,{type:`button`,className:`gp-grid-filter-remove`,onClick:()=>u(t),children:`×`})]})]},t)),C(`button`,{type:`button`,className:`gp-grid-filter-add`,onClick:l,children:`+ Add condition`}),w(`div`,{className:`gp-grid-filter-buttons`,children:[C(`button`,{type:`button`,className:`gp-grid-filter-btn-clear`,onClick:f,children:`Clear`}),C(`button`,{type:`button`,className:`gp-grid-filter-btn-apply`,onClick:d,children:`Apply`})]})]})}function M({column:e,colIndex:r,anchorRect:i,distinctValues:o,currentFilter:s,onApply:c,onClose:l}){let u=a(null);n(()=>{let e=e=>{let t=e.target;t.closest(`.gp-grid-filter-icon`)||u.current&&!u.current.contains(t)&&l()},t=e=>{e.key===`Escape`&&l()};return requestAnimationFrame(()=>{document.addEventListener(`mousedown`,e),document.addEventListener(`keydown`,t)}),()=>{document.removeEventListener(`mousedown`,e),document.removeEventListener(`keydown`,t)}},[l]);let d=t(t=>{c(e.colId??e.field,t),l()},[e,c,l]),f={position:`fixed`,top:i.top+i.height+4,left:i.left,minWidth:Math.max(200,i.width),zIndex:1e4},p=e.cellDataType,m=p===`text`||p===`object`,h=p===`number`,g=p===`date`||p===`dateString`||p===`dateTime`||p===`dateTimeString`;return w(`div`,{ref:u,className:`gp-grid-filter-popup`,style:f,children:[w(`div`,{className:`gp-grid-filter-header`,children:[`Filter: `,e.headerName??e.field]}),m&&C(E,{distinctValues:o,currentFilter:s,onApply:d,onClose:l}),h&&C(O,{currentFilter:s,onApply:d,onClose:l}),g&&C(j,{currentFilter:s,onApply:d,onClose:l}),!m&&!h&&!g&&C(E,{distinctValues:o,currentFilter:s,onApply:d,onClose:l})]})}function N(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 P(e,t,n){switch(e.type){case`CREATE_SLOT`:return t.set(e.slotId,{slotId:e.slotId,rowIndex:-1,rowData:{},translateY:0}),null;case`DESTROY_SLOT`:return t.delete(e.slotId),null;case`ASSIGN_SLOT`:{let n=t.get(e.slotId);return n&&t.set(e.slotId,{...n,rowIndex:e.rowIndex,rowData:e.rowData}),null}case`MOVE_SLOT`:{let n=t.get(e.slotId);return n&&t.set(e.slotId,{...n,translateY:e.translateY}),null}case`SET_ACTIVE_CELL`:return{activeCell:e.position};case`SET_SELECTION_RANGE`:return{selectionRange:e.range};case`UPDATE_VISIBLE_RANGE`:return{visibleRowRange:{start:e.start,end:e.end}};case`START_EDIT`:return{editingCell:{row:e.row,col:e.col,initialValue:e.initialValue}};case`STOP_EDIT`:return{editingCell:null};case`SET_CONTENT_SIZE`:return{contentWidth:e.width,contentHeight:e.height,viewportWidth:e.viewportWidth};case`UPDATE_HEADER`:return n.set(e.colIndex,{column:e.column,sortDirection:e.sortDirection,sortIndex:e.sortIndex,sortable:e.sortable,filterable:e.filterable,hasFilter:e.hasFilter}),null;case`OPEN_FILTER_POPUP`:return{filterPopup:{isOpen:!0,colIndex:e.colIndex,column:e.column,anchorRect:e.anchorRect,distinctValues:e.distinctValues,currentFilter:e.currentFilter}};case`CLOSE_FILTER_POPUP`:return{filterPopup:null};case`DATA_LOADING`:return{isLoading:!0,error:null};case`DATA_LOADED`:return{isLoading:!1,totalRows:e.totalRows};case`DATA_ERROR`:return{isLoading:!1,error:e.error};case`ROWS_ADDED`:case`ROWS_REMOVED`:return{totalRows:e.totalRows};case`ROWS_UPDATED`:case`TRANSACTION_PROCESSED`:return null;default:return null}}function F(e,t){if(t.type===`RESET`)return N();let{instructions:n}=t;if(n.length===0)return e;let r=new Map(e.slots),i=new Map(e.headers),a={};for(let e of n){let t=P(e,r,i);t&&(a={...a,...t})}return{...e,...a,slots:r,headers:i}}function I(e,t){for(let n of e.values())if(n.rowIndex===t)return n;return null}function L(e,t,n,r,i,a){let o=I(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 R(e,r,i,s){let{activeCell:c,selectionRange:l,editingCell:u,filterPopupOpen:d,rowHeight:f,headerHeight:p,columnPositions:m,slots:h}=s,g=a(null),[_,v]=o({isDragging:!1,dragType:null,fillSourceRange:null,fillTarget:null});n(()=>{let t=e.current;t?.input&&t.input.updateDeps({getHeaderHeight:()=>p,getRowHeight:()=>f,getColumnPositions:()=>m,getColumnCount:()=>i.length})},[e,p,f,m,i.length]);let y=t((e,t)=>{g.current&&clearInterval(g.current),g.current=setInterval(()=>{let n=r.current;n&&(n.scrollTop+=t,n.scrollLeft+=e)},16)},[r]),b=t(()=>{g.current&&=(clearInterval(g.current),null)},[]),x=t(()=>{let e=r.current;if(!e)return null;let t=e.getBoundingClientRect();return{top:t.top,left:t.left,width:t.width,height:t.height,scrollTop:e.scrollTop,scrollLeft:e.scrollLeft}},[r]),S=e=>({clientX:e.clientX,clientY:e.clientY,button:e.button,shiftKey:e.shiftKey,ctrlKey:e.ctrlKey,metaKey:e.metaKey}),C=t(()=>{let t=t=>{let n=e.current,r=x();if(!n?.input||!r)return;let i=n.input.handleDragMove(S(t),r);i&&(i.autoScroll?y(i.autoScroll.dx,i.autoScroll.dy):b(),v(n.input.getDragState()))},n=()=>{let r=e.current;r?.input&&(r.input.handleDragEnd(),v(r.input.getDragState())),b(),document.removeEventListener(`mousemove`,t),document.removeEventListener(`mouseup`,n)};document.addEventListener(`mousemove`,t),document.addEventListener(`mouseup`,n)},[e,x,y,b]),w=t((t,n,i)=>{let a=e.current;if(!a?.input)return;let o=a.input.handleCellMouseDown(t,n,S(i));o.focusContainer&&r.current?.focus(),o.startDrag===`selection`&&(a.input.startSelectionDrag(),v(a.input.getDragState()),C())},[e,r,C]),T=t((t,n)=>{let r=e.current;r?.input&&r.input.handleCellDoubleClick(t,n)},[e]),E=t(t=>{let n=e.current;if(!n?.input)return;let r=n.input.handleFillHandleMouseDown(c,l,S(t));r.preventDefault&&t.preventDefault(),r.stopPropagation&&t.stopPropagation(),r.startDrag===`fill`&&(v(n.input.getDragState()),C())},[e,c,l,C]),D=t((t,n)=>{let r=e.current;if(!r?.input)return;let a=i[t];if(!a)return;let o=a.colId??a.field;r.input.handleHeaderClick(o,n.shiftKey)},[e,i]),O=t(t=>{let n=e.current,i=r.current;if(!n?.input)return;let a=n.input.handleKeyDown({key:t.key,shiftKey:t.shiftKey,ctrlKey:t.ctrlKey,metaKey:t.metaKey},c,u,d);a.preventDefault&&t.preventDefault(),a.scrollToCell&&i&&L(n,i,a.scrollToCell.row,f,p,h)},[e,r,c,u,d,f,p,h]),k=t((t,n)=>{let i=e.current,a=r.current;if(!i?.input||!a)return;let o=i.input.handleWheel(t.deltaY,t.deltaX,n);o&&(t.preventDefault(),a.scrollTop+=o.dy,a.scrollLeft+=o.dx)},[e,r]);return n(()=>()=>{b()},[b]),{handleCellMouseDown:w,handleCellDoubleClick:T,handleFillHandleMouseDown:E,handleHeaderClick:D,handleKeyDown:O,handleWheel:k,dragState:_}}function z(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 ee(e){let{column:t,rowData:n,rowIndex:r,colIndex:i,isActive:a,isSelected:o,isEditing:s,cellRenderers:c,globalCellRenderer:l}=e,u=z(n,t.field),d={value:u,rowData:n,column:t,rowIndex:r,colIndex:i,isActive:a,isSelected:o,isEditing:s};if(t.cellRenderer&&typeof t.cellRenderer==`string`){let e=c[t.cellRenderer];if(e)return e(d)}return l?l(d):u==null?``:String(u)}function B(e){let{column:t,rowData:n,rowIndex:r,colIndex:i,initialValue:a,coreRef:o,editRenderers:s,globalEditRenderer:c}=e,l=o.current;if(!l)return null;let u={value:z(n,t.field),rowData:n,column:t,rowIndex:r,colIndex:i,isActive:!0,isSelected:!0,isEditing:!0,initialValue:a,onValueChange:e=>l.updateEditValue(e),onCommit:()=>l.commitEdit(),onCancel:()=>l.cancelEdit()};if(t.editRenderer&&typeof t.editRenderer==`string`){let e=s[t.editRenderer];if(e)return e(u)}return c?c(u):C(`input`,{className:`gp-grid-edit-input`,type:`text`,defaultValue:a==null?``:String(a),autoFocus:!0,onFocus:e=>e.target.select(),onChange:e=>l.updateEditValue(e.target.value),onKeyDown:e=>{e.stopPropagation(),e.key===`Enter`?l.commitEdit():e.key===`Escape`?l.cancelEdit():e.key===`Tab`&&(e.preventDefault(),l.commitEdit(),l.selection.moveFocus(e.shiftKey?`left`:`right`,!1))},onBlur:()=>l.commitEdit()})}function V(e){let{column:t,colIndex:n,sortDirection:r,sortIndex:i,sortable:a,filterable:o,hasFilter:s,coreRef:c,containerRef:l,headerRenderers:u,globalHeaderRenderer:d}=e,f=c.current,p={column:t,colIndex:n,sortDirection:r,sortIndex:i,sortable:a,filterable:o,hasFilter:s,onSort:(e,n)=>{f&&a&&f.setSort(t.colId??t.field,e,n)},onFilterClick:()=>{if(f&&o){let e=l.current?.querySelector(`[data-col-index="${n}"]`);if(e){let t=e.getBoundingClientRect();f.openFilterPopup(n,{top:t.top,left:t.left,width:t.width,height:t.height})}}}};if(t.headerRenderer&&typeof t.headerRenderer==`string`){let e=u[t.headerRenderer];if(e)return e(p)}return d?d(p):w(S,{children:[C(`span`,{className:`gp-grid-header-text`,children:t.headerName??t.field}),w(`span`,{className:`gp-grid-header-icons`,children:[a&&w(`span`,{className:`gp-grid-sort-arrows`,children:[w(`span`,{className:`gp-grid-sort-arrows-stack`,children:[C(`svg`,{className:`gp-grid-sort-arrow-up${r===`asc`?` active`:``}`,width:`8`,height:`6`,viewBox:`0 0 8 6`,children:C(`path`,{d:`M4 0L8 6H0L4 0Z`,fill:`currentColor`})}),C(`svg`,{className:`gp-grid-sort-arrow-down${r===`desc`?` active`:``}`,width:`8`,height:`6`,viewBox:`0 0 8 6`,children:C(`path`,{d:`M4 6L0 0H8L4 6Z`,fill:`currentColor`})})]}),i!==void 0&&i>0&&C(`span`,{className:`gp-grid-sort-index`,children:i})]}),o&&C(`span`,{className:`gp-grid-filter-icon${s?` active`:``}`,onMouseDown:e=>{e.stopPropagation(),e.preventDefault(),p.onFilterClick()},onClick:e=>{e.stopPropagation()},children:C(`svg`,{width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`currentColor`,children:C(`path`,{d:`M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z`})})})]})]})}function H(e){_();let{columns:o,dataSource:u,rowData:f,rowHeight:m,headerHeight:h=m,overscan:S=3,sortingEnabled:T=!0,darkMode:E=!1,wheelDampening:D=.1,cellRenderers:O={},editRenderers:k={},headerRenderers:A={},cellRenderer:j,editRenderer:P,headerRenderer:I,initialWidth:L,initialHeight:z}=e,H=a(null),U=a(null),[W,G]=i(F,{initialWidth:L,initialHeight:z},N),K=h,q=r(()=>u||(f?p(f):d([])),[u,f]),{positions:J,widths:Y}=r(()=>l(o,W.viewportWidth),[o,W.viewportWidth]),X=g(J),{handleCellMouseDown:te,handleCellDoubleClick:ne,handleFillHandleMouseDown:re,handleHeaderClick:ie,handleKeyDown:ae,handleWheel:oe,dragState:Z}=R(U,H,o,{activeCell:W.activeCell,selectionRange:W.selectionRange,editingCell:W.editingCell,filterPopupOpen:W.filterPopup?.isOpen??!1,rowHeight:m,headerHeight:K,columnPositions:J,slots:W.slots});n(()=>{let e=new s({columns:o,dataSource:q,rowHeight:m,headerHeight:K,overscan:S,sortingEnabled:T});U.current=e;let t=e.onBatchInstruction(e=>{G({type:`BATCH_INSTRUCTIONS`,instructions:e})});return e.initialize(),()=>{t(),U.current=null}},[o,q,m,K,S,T]),n(()=>{let e=q;if(e.subscribe)return e.subscribe(()=>{U.current?.refresh()})},[q]);let Q=t(()=>{let e=H.current,t=U.current;!e||!t||t.setViewport(e.scrollTop,e.scrollLeft,e.clientWidth,e.clientHeight)},[]);n(()=>{let e=H.current,t=U.current;if(!e||!t)return;if(typeof ResizeObserver>`u`){Q();return}let n=new ResizeObserver(()=>{t.setViewport(e.scrollTop,e.scrollLeft,e.clientWidth,e.clientHeight)});return n.observe(e),Q(),()=>n.disconnect()},[Q]);let se=t((e,t)=>{let n=U.current;n&&n.setFilter(e,t)},[]),ce=t(()=>{let e=U.current;e&&e.closeFilterPopup()},[]),le=r(()=>Array.from(W.slots.values()),[W.slots]),$=r(()=>{let{activeCell:e,selectionRange:t,slots:n}=W;if(!e&&!t)return null;let r,i,a,s;if(t)r=Math.max(t.startRow,t.endRow),i=Math.max(t.startCol,t.endCol),a=Math.min(t.startCol,t.endCol),s=Math.max(t.startCol,t.endCol);else if(e)r=e.row,i=e.col,a=i,s=i;else return null;for(let e=a;e<=s;e++){let t=o[e];if(!t||t.editable!==!0)return null}let c=null;for(let e of n.values())if(e.rowIndex===r){c=e.translateY;break}if(c===null)return null;let l=J[i]??0,u=Y[i]??0;return{top:c+m-5,left:l+u-20}},[W.activeCell,W.selectionRange,W.slots,m,J,Y,o]);return w(`div`,{ref:H,className:`gp-grid-container${E?` gp-grid-container--dark`:``}`,style:{width:`100%`,height:`100%`,overflow:`auto`,position:`relative`},onScroll:Q,onWheel:e=>oe(e,D),onKeyDown:ae,tabIndex:0,children:[w(`div`,{style:{width:Math.max(W.contentWidth,X),height:Math.max(W.contentHeight,K),position:`relative`,minWidth:`100%`},children:[C(`div`,{className:`gp-grid-header`,style:{position:`sticky`,top:0,left:0,height:h,width:Math.max(W.contentWidth,X),minWidth:`100%`},children:o.map((e,t)=>{let n=W.headers.get(t);return C(`div`,{className:`gp-grid-header-cell`,"data-col-index":t,style:{position:`absolute`,left:`${J[t]}px`,top:0,width:`${Y[t]}px`,height:`${h}px`,background:`transparent`},onClick:e=>ie(t,e),children:V({column:e,colIndex:t,sortDirection:n?.sortDirection,sortIndex:n?.sortIndex,sortable:n?.sortable??!0,filterable:n?.filterable??!0,hasFilter:n?.hasFilter??!1,coreRef:U,containerRef:H,headerRenderers:A,globalHeaderRenderer:I})},e.colId??e.field)})}),le.map(e=>e.rowIndex<0?null:C(`div`,{className:`gp-grid-row ${e.rowIndex%2==0?`gp-grid-row--even`:``}`,style:{position:`absolute`,top:0,left:0,transform:`translateY(${e.translateY}px)`,width:`${Math.max(W.contentWidth,X)}px`,height:`${m}px`},children:o.map((t,n)=>{let r=y(e.rowIndex,n,W.editingCell),i=v(e.rowIndex,n,W.activeCell),a=x(e.rowIndex,n,W.selectionRange);return C(`div`,{className:c(i,a,r,b(e.rowIndex,n,Z.dragType===`fill`,Z.fillSourceRange,Z.fillTarget)),style:{position:`absolute`,left:`${J[n]}px`,top:0,width:`${Y[n]}px`,height:`${m}px`},onMouseDown:t=>te(e.rowIndex,n,t),onDoubleClick:()=>ne(e.rowIndex,n),children:r&&W.editingCell?B({column:t,rowData:e.rowData,rowIndex:e.rowIndex,colIndex:n,initialValue:W.editingCell.initialValue,coreRef:U,editRenderers:k,globalEditRenderer:P}):ee({column:t,rowData:e.rowData,rowIndex:e.rowIndex,colIndex:n,isActive:i,isSelected:a,isEditing:r,cellRenderers:O,globalCellRenderer:j})},`${e.slotId}-${n}`)})},e.slotId)),$&&!W.editingCell&&C(`div`,{className:`gp-grid-fill-handle`,style:{position:`absolute`,top:$.top,left:$.left,zIndex:200},onMouseDown:re}),W.isLoading&&w(`div`,{className:`gp-grid-loading`,children:[C(`div`,{className:`gp-grid-loading-spinner`}),`Loading...`]}),W.error&&w(`div`,{className:`gp-grid-error`,children:[`Error: `,W.error]}),!W.isLoading&&!W.error&&W.totalRows===0&&C(`div`,{className:`gp-grid-empty`,children:`No data to display`})]}),W.filterPopup?.isOpen&&W.filterPopup.column&&W.filterPopup.anchorRect&&C(M,{column:W.filterPopup.column,colIndex:W.filterPopup.colIndex,anchorRect:W.filterPopup.anchorRect,distinctValues:W.filterPopup.distinctValues,currentFilter:W.filterPopup.currentFilter,onApply:se,onClose:ce})]})}export{H as Grid,u as createClientDataSource,f as createDataSourceFromArray,m as createMutableClientDataSource,h as createServerDataSource};
1
+ import e,{useCallback as t,useEffect as n,useMemo as r,useReducer as i,useRef as a,useState as o}from"react";import{GridCore as s,GridCore as c,buildCellClasses as l,calculateScaledColumnPositions as u,createClientDataSource as d,createClientDataSource as f,createDataSourceFromArray as p,createDataSourceFromArray as m,createMutableClientDataSource as h,createServerDataSource as g,getTotalWidth as _,injectStyles as v,isCellActive as y,isCellEditing as b,isCellInFillPreview as x,isCellSelected as S}from"gp-grid-core";import{Fragment as C,jsx as w,jsxs as T}from"react/jsx-runtime";const E=[{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`}];function D({distinctValues:e,currentFilter:n,onApply:i,onClose:a}){let s=t(e=>Array.isArray(e)?e.join(`, `):String(e??``),[]),c=r(()=>{let t=e.filter(e=>e!=null&&e!==``&&!(Array.isArray(e)&&e.length===0)).map(e=>s(e));return Array.from(new Set(t)).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`})})},[e,s]),l=c.length>100,[u,d]=o(r(()=>{if(!n?.conditions[0])return l?`condition`:`values`;let e=n.conditions[0];return e.selectedValues&&e.selectedValues.size>0?`values`:`condition`},[n,l])),f=r(()=>n?.conditions[0]?n.conditions[0].selectedValues??new Set:new Set,[n]),p=r(()=>n?.conditions[0]?n.conditions[0].includeBlank??!0:!0,[n]),[m,h]=o(``),[g,_]=o(f),[v,y]=o(p),[b,x]=o(r(()=>{if(!n?.conditions.length)return[{operator:`contains`,value:``,nextOperator:`and`}];let e=n.conditions[0];if(e.selectedValues&&e.selectedValues.size>0)return[{operator:`contains`,value:``,nextOperator:`and`}];let t=n.combination??`and`;return n.conditions.map(e=>{let n=e;return{operator:n.operator,value:n.value??``,nextOperator:n.nextOperator??t}})},[n])),S=r(()=>{if(!m)return c;let e=m.toLowerCase();return c.filter(t=>t.toLowerCase().includes(e))},[c,m]),D=r(()=>e.some(e=>e==null||e===``),[e]),O=r(()=>S.every(e=>g.has(e))&&(!D||v),[S,g,D,v]),k=t(()=>{_(new Set(S)),D&&y(!0)},[S,D]),A=t(()=>{_(new Set),y(!1)},[]),j=t(e=>{_(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},[]),M=t((e,t)=>{x(n=>{let r=[...n];return r[e]={...r[e],...t},r})},[]),N=t(()=>{x(e=>[...e,{operator:`contains`,value:``,nextOperator:`and`}])},[]),P=t(e=>{x(t=>t.filter((t,n)=>n!==e))},[]),F=t(()=>{if(u===`values`){if(c.every(e=>g.has(e))&&(!D||v)){i(null);return}i({conditions:[{type:`text`,operator:`equals`,selectedValues:g,includeBlank:v}],combination:`and`})}else{let e=b.filter(e=>e.operator===`blank`||e.operator===`notBlank`?!0:e.value.trim()!==``);if(e.length===0){i(null);return}i({conditions:e.map(e=>({type:`text`,operator:e.operator,value:e.value,nextOperator:e.nextOperator})),combination:`and`})}},[u,c,g,v,D,b,i]),I=t(()=>{i(null)},[i]);return T(`div`,{className:`gp-grid-filter-content gp-grid-filter-text`,children:[!l&&T(`div`,{className:`gp-grid-filter-mode-toggle`,children:[w(`button`,{type:`button`,className:u===`values`?`active`:``,onClick:()=>d(`values`),children:`Values`}),w(`button`,{type:`button`,className:u===`condition`?`active`:``,onClick:()=>d(`condition`),children:`Condition`})]}),l&&u===`condition`&&T(`div`,{className:`gp-grid-filter-info`,children:[`Too many unique values (`,c.length,`). Use conditions to filter.`]}),u===`values`&&T(C,{children:[w(`input`,{className:`gp-grid-filter-search`,type:`text`,placeholder:`Search...`,value:m,onChange:e=>h(e.target.value),autoFocus:!0}),T(`div`,{className:`gp-grid-filter-actions`,children:[w(`button`,{type:`button`,onClick:k,disabled:O,children:`Select All`}),w(`button`,{type:`button`,onClick:A,children:`Deselect All`})]}),T(`div`,{className:`gp-grid-filter-list`,children:[D&&T(`label`,{className:`gp-grid-filter-option`,children:[w(`input`,{type:`checkbox`,checked:v,onChange:()=>y(!v)}),w(`span`,{className:`gp-grid-filter-blank`,children:`(Blanks)`})]}),S.map(e=>T(`label`,{className:`gp-grid-filter-option`,children:[w(`input`,{type:`checkbox`,checked:g.has(e),onChange:()=>j(e)}),w(`span`,{children:e})]},e))]})]}),u===`condition`&&T(C,{children:[b.map((e,t)=>T(`div`,{className:`gp-grid-filter-condition`,children:[t>0&&T(`div`,{className:`gp-grid-filter-combination`,children:[w(`button`,{type:`button`,className:b[t-1]?.nextOperator===`and`?`active`:``,onClick:()=>M(t-1,{nextOperator:`and`}),children:`AND`}),w(`button`,{type:`button`,className:b[t-1]?.nextOperator===`or`?`active`:``,onClick:()=>M(t-1,{nextOperator:`or`}),children:`OR`})]}),T(`div`,{className:`gp-grid-filter-row`,children:[w(`select`,{value:e.operator,onChange:e=>M(t,{operator:e.target.value}),autoFocus:t===0,children:E.map(e=>w(`option`,{value:e.value,children:e.label},e.value))}),e.operator!==`blank`&&e.operator!==`notBlank`&&w(`input`,{type:`text`,value:e.value,onChange:e=>M(t,{value:e.target.value}),placeholder:`Value`,className:`gp-grid-filter-text-input`}),b.length>1&&w(`button`,{type:`button`,className:`gp-grid-filter-remove`,onClick:()=>P(t),children:`×`})]})]},t)),w(`button`,{type:`button`,className:`gp-grid-filter-add`,onClick:N,children:`+ Add condition`})]}),T(`div`,{className:`gp-grid-filter-buttons`,children:[w(`button`,{type:`button`,className:`gp-grid-filter-btn-clear`,onClick:I,children:`Clear`}),w(`button`,{type:`button`,className:`gp-grid-filter-btn-apply`,onClick:F,children:`Apply`})]})]})}const O=[{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`}];function k({currentFilter:e,onApply:n,onClose:i}){let[a,s]=o(r(()=>{if(!e?.conditions.length)return[{operator:`=`,value:``,valueTo:``,nextOperator:`and`}];let t=e.combination??`and`;return e.conditions.map(e=>{let n=e;return{operator:n.operator,value:n.value==null?``:String(n.value),valueTo:n.valueTo==null?``:String(n.valueTo),nextOperator:n.nextOperator??t}})},[e])),c=t((e,t)=>{s(n=>{let r=[...n];return r[e]={...r[e],...t},r})},[]),l=t(()=>{s(e=>[...e,{operator:`=`,value:``,valueTo:``,nextOperator:`and`}])},[]),u=t(e=>{s(t=>t.filter((t,n)=>n!==e))},[]),d=t(()=>{let e=a.filter(e=>e.operator===`blank`||e.operator===`notBlank`?!0:e.operator===`between`?e.value!==``&&e.valueTo!==``:e.value!==``);if(e.length===0){n(null);return}n({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`})},[a,n]),f=t(()=>{n(null)},[n]);return T(`div`,{className:`gp-grid-filter-content gp-grid-filter-number`,children:[a.map((e,t)=>T(`div`,{className:`gp-grid-filter-condition`,children:[t>0&&T(`div`,{className:`gp-grid-filter-combination`,children:[w(`button`,{type:`button`,className:a[t-1]?.nextOperator===`and`?`active`:``,onClick:()=>c(t-1,{nextOperator:`and`}),children:`AND`}),w(`button`,{type:`button`,className:a[t-1]?.nextOperator===`or`?`active`:``,onClick:()=>c(t-1,{nextOperator:`or`}),children:`OR`})]}),T(`div`,{className:`gp-grid-filter-row`,children:[w(`select`,{value:e.operator,onChange:e=>c(t,{operator:e.target.value}),children:O.map(e=>w(`option`,{value:e.value,children:e.label},e.value))}),e.operator!==`blank`&&e.operator!==`notBlank`&&w(`input`,{type:`number`,value:e.value,onChange:e=>c(t,{value:e.target.value}),placeholder:`Value`}),e.operator===`between`&&T(C,{children:[w(`span`,{className:`gp-grid-filter-to`,children:`to`}),w(`input`,{type:`number`,value:e.valueTo,onChange:e=>c(t,{valueTo:e.target.value}),placeholder:`Value`})]}),a.length>1&&w(`button`,{type:`button`,className:`gp-grid-filter-remove`,onClick:()=>u(t),children:`×`})]})]},t)),w(`button`,{type:`button`,className:`gp-grid-filter-add`,onClick:l,children:`+ Add condition`}),T(`div`,{className:`gp-grid-filter-buttons`,children:[w(`button`,{type:`button`,className:`gp-grid-filter-btn-clear`,onClick:f,children:`Clear`}),w(`button`,{type:`button`,className:`gp-grid-filter-btn-apply`,onClick:d,children:`Apply`})]})]})}const A=[{value:`=`,label:`=`},{value:`!=`,label:`≠`},{value:`>`,label:`>`},{value:`<`,label:`<`},{value:`between`,label:`↔`},{value:`blank`,label:`Is blank`},{value:`notBlank`,label:`Not blank`}];function j(e){if(!e)return``;let t=typeof e==`string`?new Date(e):e;return isNaN(t.getTime())?``:t.toISOString().split(`T`)[0]}function M({currentFilter:e,onApply:n,onClose:i}){let[a,s]=o(r(()=>{if(!e?.conditions.length)return[{operator:`=`,value:``,valueTo:``,nextOperator:`and`}];let t=e.combination??`and`;return e.conditions.map(e=>{let n=e;return{operator:n.operator,value:j(n.value),valueTo:j(n.valueTo),nextOperator:n.nextOperator??t}})},[e])),c=t((e,t)=>{s(n=>{let r=[...n];return r[e]={...r[e],...t},r})},[]),l=t(()=>{s(e=>[...e,{operator:`=`,value:``,valueTo:``,nextOperator:`and`}])},[]),u=t(e=>{s(t=>t.filter((t,n)=>n!==e))},[]),d=t(()=>{let e=a.filter(e=>e.operator===`blank`||e.operator===`notBlank`?!0:e.operator===`between`?e.value!==``&&e.valueTo!==``:e.value!==``);if(e.length===0){n(null);return}n({conditions:e.map(e=>({type:`date`,operator:e.operator,value:e.value||void 0,valueTo:e.valueTo||void 0,nextOperator:e.nextOperator})),combination:`and`})},[a,n]),f=t(()=>{n(null)},[n]);return T(`div`,{className:`gp-grid-filter-content gp-grid-filter-date`,children:[a.map((e,t)=>T(`div`,{className:`gp-grid-filter-condition`,children:[t>0&&T(`div`,{className:`gp-grid-filter-combination`,children:[w(`button`,{type:`button`,className:a[t-1]?.nextOperator===`and`?`active`:``,onClick:()=>c(t-1,{nextOperator:`and`}),children:`AND`}),w(`button`,{type:`button`,className:a[t-1]?.nextOperator===`or`?`active`:``,onClick:()=>c(t-1,{nextOperator:`or`}),children:`OR`})]}),T(`div`,{className:`gp-grid-filter-row`,children:[w(`select`,{value:e.operator,onChange:e=>c(t,{operator:e.target.value}),children:A.map(e=>w(`option`,{value:e.value,children:e.label},e.value))}),e.operator!==`blank`&&e.operator!==`notBlank`&&w(`input`,{type:`date`,value:e.value,onChange:e=>c(t,{value:e.target.value})}),e.operator===`between`&&T(C,{children:[w(`span`,{className:`gp-grid-filter-to`,children:`to`}),w(`input`,{type:`date`,value:e.valueTo,onChange:e=>c(t,{valueTo:e.target.value})})]}),a.length>1&&w(`button`,{type:`button`,className:`gp-grid-filter-remove`,onClick:()=>u(t),children:`×`})]})]},t)),w(`button`,{type:`button`,className:`gp-grid-filter-add`,onClick:l,children:`+ Add condition`}),T(`div`,{className:`gp-grid-filter-buttons`,children:[w(`button`,{type:`button`,className:`gp-grid-filter-btn-clear`,onClick:f,children:`Clear`}),w(`button`,{type:`button`,className:`gp-grid-filter-btn-apply`,onClick:d,children:`Apply`})]})]})}function N({column:e,colIndex:r,anchorRect:i,distinctValues:o,currentFilter:s,onApply:c,onClose:l}){let u=a(null);n(()=>{let e=e=>{let t=e.target;t.closest(`.gp-grid-filter-icon`)||u.current&&!u.current.contains(t)&&l()},t=e=>{e.key===`Escape`&&l()};return requestAnimationFrame(()=>{document.addEventListener(`mousedown`,e),document.addEventListener(`keydown`,t)}),()=>{document.removeEventListener(`mousedown`,e),document.removeEventListener(`keydown`,t)}},[l]);let d=t(t=>{c(e.colId??e.field,t),l()},[e,c,l]),f={position:`fixed`,top:i.top+i.height+4,left:i.left,minWidth:Math.max(200,i.width),zIndex:1e4},p=e.cellDataType,m=p===`text`||p===`object`,h=p===`number`,g=p===`date`||p===`dateString`||p===`dateTime`||p===`dateTimeString`;return T(`div`,{ref:u,className:`gp-grid-filter-popup`,style:f,children:[T(`div`,{className:`gp-grid-filter-header`,children:[`Filter: `,e.headerName??e.field]}),m&&w(D,{distinctValues:o,currentFilter:s,onApply:d,onClose:l}),h&&w(k,{currentFilter:s,onApply:d,onClose:l}),g&&w(M,{currentFilter:s,onApply:d,onClose:l}),!m&&!h&&!g&&w(D,{distinctValues:o,currentFilter:s,onApply:d,onClose:l})]})}function P(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 F(e,t,n){switch(e.type){case`CREATE_SLOT`:return t.set(e.slotId,{slotId:e.slotId,rowIndex:-1,rowData:{},translateY:0}),null;case`DESTROY_SLOT`:return t.delete(e.slotId),null;case`ASSIGN_SLOT`:{let n=t.get(e.slotId);return n&&t.set(e.slotId,{...n,rowIndex:e.rowIndex,rowData:e.rowData}),null}case`MOVE_SLOT`:{let n=t.get(e.slotId);return n&&t.set(e.slotId,{...n,translateY:e.translateY}),null}case`SET_ACTIVE_CELL`:return{activeCell:e.position};case`SET_SELECTION_RANGE`:return{selectionRange:e.range};case`UPDATE_VISIBLE_RANGE`:return{visibleRowRange:{start:e.start,end:e.end}};case`START_EDIT`:return{editingCell:{row:e.row,col:e.col,initialValue:e.initialValue}};case`STOP_EDIT`:return{editingCell:null};case`SET_CONTENT_SIZE`:return{contentWidth:e.width,contentHeight:e.height,viewportWidth:e.viewportWidth};case`UPDATE_HEADER`:return n.set(e.colIndex,{column:e.column,sortDirection:e.sortDirection,sortIndex:e.sortIndex,sortable:e.sortable,filterable:e.filterable,hasFilter:e.hasFilter}),null;case`OPEN_FILTER_POPUP`:return{filterPopup:{isOpen:!0,colIndex:e.colIndex,column:e.column,anchorRect:e.anchorRect,distinctValues:e.distinctValues,currentFilter:e.currentFilter}};case`CLOSE_FILTER_POPUP`:return{filterPopup:null};case`DATA_LOADING`:return{isLoading:!0,error:null};case`DATA_LOADED`:return{isLoading:!1,totalRows:e.totalRows};case`DATA_ERROR`:return{isLoading:!1,error:e.error};case`ROWS_ADDED`:case`ROWS_REMOVED`:return{totalRows:e.totalRows};case`ROWS_UPDATED`:case`TRANSACTION_PROCESSED`:return null;default:return null}}function I(e,t){if(t.type===`RESET`)return P();let{instructions:n}=t;if(n.length===0)return e;let r=new Map(e.slots),i=new Map(e.headers),a={};for(let e of n){let t=F(e,r,i);t&&(a={...a,...t})}return{...e,...a,slots:r,headers:i}}function L(e,t){for(let n of e.values())if(n.rowIndex===t)return n;return null}function R(e,t,n,r,i,a){let o=L(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 z(e,r,i,s){let{activeCell:c,selectionRange:l,editingCell:u,filterPopupOpen:d,rowHeight:f,headerHeight:p,columnPositions:m,slots:h}=s,g=a(null),[_,v]=o({isDragging:!1,dragType:null,fillSourceRange:null,fillTarget:null});n(()=>{let t=e.current;t?.input&&t.input.updateDeps({getHeaderHeight:()=>p,getRowHeight:()=>f,getColumnPositions:()=>m,getColumnCount:()=>i.length})},[e,p,f,m,i.length]);let y=t((e,t)=>{g.current&&clearInterval(g.current),g.current=setInterval(()=>{let n=r.current;n&&(n.scrollTop+=t,n.scrollLeft+=e)},16)},[r]),b=t(()=>{g.current&&=(clearInterval(g.current),null)},[]),x=t(()=>{let e=r.current;if(!e)return null;let t=e.getBoundingClientRect();return{top:t.top,left:t.left,width:t.width,height:t.height,scrollTop:e.scrollTop,scrollLeft:e.scrollLeft}},[r]),S=e=>({clientX:e.clientX,clientY:e.clientY,button:e.button,shiftKey:e.shiftKey,ctrlKey:e.ctrlKey,metaKey:e.metaKey}),C=t(()=>{let t=t=>{let n=e.current,r=x();if(!n?.input||!r)return;let i=n.input.handleDragMove(S(t),r);i&&(i.autoScroll?y(i.autoScroll.dx,i.autoScroll.dy):b(),v(n.input.getDragState()))},n=()=>{let r=e.current;r?.input&&(r.input.handleDragEnd(),v(r.input.getDragState())),b(),document.removeEventListener(`mousemove`,t),document.removeEventListener(`mouseup`,n)};document.addEventListener(`mousemove`,t),document.addEventListener(`mouseup`,n)},[e,x,y,b]),w=t((t,n,i)=>{let a=e.current;if(!a?.input)return;let o=a.input.handleCellMouseDown(t,n,S(i));o.focusContainer&&r.current?.focus(),o.startDrag===`selection`&&(a.input.startSelectionDrag(),v(a.input.getDragState()),C())},[e,r,C]),T=t((t,n)=>{let r=e.current;r?.input&&r.input.handleCellDoubleClick(t,n)},[e]),E=t(t=>{let n=e.current;if(!n?.input)return;let r=n.input.handleFillHandleMouseDown(c,l,S(t));r.preventDefault&&t.preventDefault(),r.stopPropagation&&t.stopPropagation(),r.startDrag===`fill`&&(v(n.input.getDragState()),C())},[e,c,l,C]),D=t((t,n)=>{let r=e.current;if(!r?.input)return;let a=i[t];if(!a)return;let o=a.colId??a.field;r.input.handleHeaderClick(o,n.shiftKey)},[e,i]),O=t(t=>{let n=e.current,i=r.current;if(!n?.input)return;let a=n.input.handleKeyDown({key:t.key,shiftKey:t.shiftKey,ctrlKey:t.ctrlKey,metaKey:t.metaKey},c,u,d);a.preventDefault&&t.preventDefault(),a.scrollToCell&&i&&R(n,i,a.scrollToCell.row,f,p,h)},[e,r,c,u,d,f,p,h]),k=t((t,n)=>{let i=e.current,a=r.current;if(!i?.input||!a)return;let o=i.input.handleWheel(t.deltaY,t.deltaX,n);o&&(t.preventDefault(),a.scrollTop+=o.dy,a.scrollLeft+=o.dx)},[e,r]);return n(()=>()=>{b()},[b]),{handleCellMouseDown:w,handleCellDoubleClick:T,handleFillHandleMouseDown:E,handleHeaderClick:D,handleKeyDown:O,handleWheel:k,dragState:_}}function B(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 V(e){let{column:t,rowData:n,rowIndex:r,colIndex:i,isActive:a,isSelected:o,isEditing:s,cellRenderers:c,globalCellRenderer:l}=e,u=B(n,t.field),d={value:u,rowData:n,column:t,rowIndex:r,colIndex:i,isActive:a,isSelected:o,isEditing:s};if(t.cellRenderer&&typeof t.cellRenderer==`string`){let e=c[t.cellRenderer];if(e)return e(d)}return l?l(d):u==null?``:String(u)}function H(e){let{column:t,rowData:n,rowIndex:r,colIndex:i,initialValue:a,coreRef:o,editRenderers:s,globalEditRenderer:c}=e,l=o.current;if(!l)return null;let u={value:B(n,t.field),rowData:n,column:t,rowIndex:r,colIndex:i,isActive:!0,isSelected:!0,isEditing:!0,initialValue:a,onValueChange:e=>l.updateEditValue(e),onCommit:()=>l.commitEdit(),onCancel:()=>l.cancelEdit()};if(t.editRenderer&&typeof t.editRenderer==`string`){let e=s[t.editRenderer];if(e)return e(u)}return c?c(u):w(`input`,{className:`gp-grid-edit-input`,type:`text`,defaultValue:a==null?``:String(a),autoFocus:!0,onFocus:e=>e.target.select(),onChange:e=>l.updateEditValue(e.target.value),onKeyDown:e=>{e.stopPropagation(),e.key===`Enter`?l.commitEdit():e.key===`Escape`?l.cancelEdit():e.key===`Tab`&&(e.preventDefault(),l.commitEdit(),l.selection.moveFocus(e.shiftKey?`left`:`right`,!1))},onBlur:()=>l.commitEdit()})}function U(e){let{column:t,colIndex:n,sortDirection:r,sortIndex:i,sortable:a,filterable:o,hasFilter:s,coreRef:c,containerRef:l,headerRenderers:u,globalHeaderRenderer:d}=e,f=c.current,p={column:t,colIndex:n,sortDirection:r,sortIndex:i,sortable:a,filterable:o,hasFilter:s,onSort:(e,n)=>{f&&a&&f.setSort(t.colId??t.field,e,n)},onFilterClick:()=>{if(f&&o){let e=l.current?.querySelector(`[data-col-index="${n}"]`);if(e){let t=e.getBoundingClientRect();f.openFilterPopup(n,{top:t.top,left:t.left,width:t.width,height:t.height})}}}};if(t.headerRenderer&&typeof t.headerRenderer==`string`){let e=u[t.headerRenderer];if(e)return e(p)}return d?d(p):T(C,{children:[w(`span`,{className:`gp-grid-header-text`,children:t.headerName??t.field}),T(`span`,{className:`gp-grid-header-icons`,children:[a&&T(`span`,{className:`gp-grid-sort-arrows`,children:[T(`span`,{className:`gp-grid-sort-arrows-stack`,children:[w(`svg`,{className:`gp-grid-sort-arrow-up${r===`asc`?` active`:``}`,width:`8`,height:`6`,viewBox:`0 0 8 6`,children:w(`path`,{d:`M4 0L8 6H0L4 0Z`,fill:`currentColor`})}),w(`svg`,{className:`gp-grid-sort-arrow-down${r===`desc`?` active`:``}`,width:`8`,height:`6`,viewBox:`0 0 8 6`,children:w(`path`,{d:`M4 6L0 0H8L4 6Z`,fill:`currentColor`})})]}),i!==void 0&&i>0&&w(`span`,{className:`gp-grid-sort-index`,children:i})]}),o&&w(`span`,{className:`gp-grid-filter-icon${s?` active`:``}`,onMouseDown:e=>{e.stopPropagation(),e.preventDefault(),p.onFilterClick()},onClick:e=>{e.stopPropagation()},children:w(`svg`,{width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`currentColor`,children:w(`path`,{d:`M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z`})})})]})]})}function W(e){v();let{columns:o,dataSource:s,rowData:d,rowHeight:p,headerHeight:h=p,overscan:g=3,sortingEnabled:C=!0,darkMode:E=!1,wheelDampening:D=.1,cellRenderers:O={},editRenderers:k={},headerRenderers:A={},cellRenderer:j,editRenderer:M,headerRenderer:F,initialWidth:L,initialHeight:R}=e,B=a(null),W=a(null),[G,ee]=i(I,{initialWidth:L,initialHeight:R},P),K=h,q=r(()=>s||(d?m(d):f([])),[s,d]),{positions:J,widths:Y}=r(()=>u(o,G.viewportWidth),[o,G.viewportWidth]),X=_(J),{handleCellMouseDown:te,handleCellDoubleClick:ne,handleFillHandleMouseDown:re,handleHeaderClick:ie,handleKeyDown:ae,handleWheel:oe,dragState:Z}=z(W,B,o,{activeCell:G.activeCell,selectionRange:G.selectionRange,editingCell:G.editingCell,filterPopupOpen:G.filterPopup?.isOpen??!1,rowHeight:p,headerHeight:K,columnPositions:J,slots:G.slots});n(()=>{let e=new c({columns:o,dataSource:q,rowHeight:p,headerHeight:K,overscan:g,sortingEnabled:C});W.current=e;let t=e.onBatchInstruction(e=>{ee({type:`BATCH_INSTRUCTIONS`,instructions:e})});return e.initialize(),()=>{t(),W.current=null}},[o,q,p,K,g,C]),n(()=>{let e=q;if(e.subscribe)return e.subscribe(()=>{W.current?.refresh()})},[q]);let Q=t(()=>{let e=B.current,t=W.current;!e||!t||t.setViewport(e.scrollTop,e.scrollLeft,e.clientWidth,e.clientHeight)},[]);n(()=>{let e=B.current,t=W.current;if(!e||!t)return;if(typeof ResizeObserver>`u`){Q();return}let n=new ResizeObserver(()=>{t.setViewport(e.scrollTop,e.scrollLeft,e.clientWidth,e.clientHeight)});return n.observe(e),Q(),()=>n.disconnect()},[Q]);let se=t((e,t)=>{let n=W.current;n&&n.setFilter(e,t)},[]),ce=t(()=>{let e=W.current;e&&e.closeFilterPopup()},[]),le=r(()=>Array.from(G.slots.values()),[G.slots]),$=r(()=>{let{activeCell:e,selectionRange:t,slots:n}=G;if(!e&&!t)return null;let r,i,a,s;if(t)r=Math.max(t.startRow,t.endRow),i=Math.max(t.startCol,t.endCol),a=Math.min(t.startCol,t.endCol),s=Math.max(t.startCol,t.endCol);else if(e)r=e.row,i=e.col,a=i,s=i;else return null;for(let e=a;e<=s;e++){let t=o[e];if(!t||t.editable!==!0)return null}let c=null;for(let e of n.values())if(e.rowIndex===r){c=e.translateY;break}if(c===null)return null;let l=J[i]??0,u=Y[i]??0;return{top:c+p-5,left:l+u-20}},[G.activeCell,G.selectionRange,G.slots,p,J,Y,o]);return T(`div`,{ref:B,className:`gp-grid-container${E?` gp-grid-container--dark`:``}`,style:{width:`100%`,height:`100%`,overflow:`auto`,position:`relative`},onScroll:Q,onWheel:e=>oe(e,D),onKeyDown:ae,tabIndex:0,children:[T(`div`,{style:{width:Math.max(G.contentWidth,X),height:Math.max(G.contentHeight,K),position:`relative`,minWidth:`100%`},children:[w(`div`,{className:`gp-grid-header`,style:{position:`sticky`,top:0,left:0,height:h,width:Math.max(G.contentWidth,X),minWidth:`100%`},children:o.map((e,t)=>{let n=G.headers.get(t);return w(`div`,{className:`gp-grid-header-cell`,"data-col-index":t,style:{position:`absolute`,left:`${J[t]}px`,top:0,width:`${Y[t]}px`,height:`${h}px`,background:`transparent`},onClick:e=>ie(t,e),children:U({column:e,colIndex:t,sortDirection:n?.sortDirection,sortIndex:n?.sortIndex,sortable:n?.sortable??!0,filterable:n?.filterable??!0,hasFilter:n?.hasFilter??!1,coreRef:W,containerRef:B,headerRenderers:A,globalHeaderRenderer:F})},e.colId??e.field)})}),le.map(e=>e.rowIndex<0?null:w(`div`,{className:`gp-grid-row ${e.rowIndex%2==0?`gp-grid-row--even`:``}`,style:{position:`absolute`,top:0,left:0,transform:`translateY(${e.translateY}px)`,width:`${Math.max(G.contentWidth,X)}px`,height:`${p}px`},children:o.map((t,n)=>{let r=b(e.rowIndex,n,G.editingCell),i=y(e.rowIndex,n,G.activeCell),a=S(e.rowIndex,n,G.selectionRange);return w(`div`,{className:l(i,a,r,x(e.rowIndex,n,Z.dragType===`fill`,Z.fillSourceRange,Z.fillTarget)),style:{position:`absolute`,left:`${J[n]}px`,top:0,width:`${Y[n]}px`,height:`${p}px`},onMouseDown:t=>te(e.rowIndex,n,t),onDoubleClick:()=>ne(e.rowIndex,n),children:r&&G.editingCell?H({column:t,rowData:e.rowData,rowIndex:e.rowIndex,colIndex:n,initialValue:G.editingCell.initialValue,coreRef:W,editRenderers:k,globalEditRenderer:M}):V({column:t,rowData:e.rowData,rowIndex:e.rowIndex,colIndex:n,isActive:i,isSelected:a,isEditing:r,cellRenderers:O,globalCellRenderer:j})},`${e.slotId}-${n}`)})},e.slotId)),$&&!G.editingCell&&w(`div`,{className:`gp-grid-fill-handle`,style:{position:`absolute`,top:$.top,left:$.left,zIndex:200},onMouseDown:re}),G.isLoading&&T(`div`,{className:`gp-grid-loading`,children:[w(`div`,{className:`gp-grid-loading-spinner`}),`Loading...`]}),G.error&&T(`div`,{className:`gp-grid-error`,children:[`Error: `,G.error]}),!G.isLoading&&!G.error&&G.totalRows===0&&w(`div`,{className:`gp-grid-empty`,children:`No data to display`})]}),G.filterPopup?.isOpen&&G.filterPopup.column&&G.filterPopup.anchorRect&&w(N,{column:G.filterPopup.column,colIndex:G.filterPopup.colIndex,anchorRect:G.filterPopup.anchorRect,distinctValues:G.filterPopup.distinctValues,currentFilter:G.filterPopup.currentFilter,onApply:se,onClose:ce})]})}export{W as Grid,s as GridCore,d as createClientDataSource,p as createDataSourceFromArray,h as createMutableClientDataSource,g as createServerDataSource};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gp-grid-react",
3
3
  "description": "A high-performance React data grid component with virtual scrolling, cell selection, sorting, filtering, and Excel-like editing",
4
- "version": "0.4.0",
4
+ "version": "0.5.1",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
@@ -45,7 +45,7 @@
45
45
  "link-workspace-packages": false
46
46
  },
47
47
  "dependencies": {
48
- "gp-grid-core": "0.4.0"
48
+ "gp-grid-core": "0.5.1"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "react": "^19.0.0",
@@ -56,10 +56,10 @@
56
56
  "@testing-library/user-event": "^14.6.1",
57
57
  "@types/react": "^19.2.2",
58
58
  "@types/react-dom": "^19.1.9",
59
- "@vitejs/plugin-react": "^4.5.2",
59
+ "@vitejs/plugin-react": "^5.1.2",
60
60
  "react": "^19.2.0",
61
61
  "react-dom": "^19.2.0",
62
- "tsdown": "^0.15.9",
62
+ "tsdown": "0.19.0-beta.5",
63
63
  "typescript": "^5.9.3"
64
64
  },
65
65
  "scripts": {