@alaarab/ogrid-js 2.1.3 → 2.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/esm/index.js +6343 -32
  2. package/package.json +4 -4
  3. package/dist/esm/OGrid.js +0 -578
  4. package/dist/esm/OGridEventWiring.js +0 -178
  5. package/dist/esm/OGridRendering.js +0 -269
  6. package/dist/esm/components/ColumnChooser.js +0 -91
  7. package/dist/esm/components/ContextMenu.js +0 -125
  8. package/dist/esm/components/HeaderFilter.js +0 -281
  9. package/dist/esm/components/InlineCellEditor.js +0 -434
  10. package/dist/esm/components/MarchingAntsOverlay.js +0 -156
  11. package/dist/esm/components/PaginationControls.js +0 -85
  12. package/dist/esm/components/SideBar.js +0 -353
  13. package/dist/esm/components/StatusBar.js +0 -34
  14. package/dist/esm/renderer/TableRenderer.js +0 -846
  15. package/dist/esm/state/ClipboardState.js +0 -111
  16. package/dist/esm/state/ColumnPinningState.js +0 -82
  17. package/dist/esm/state/ColumnReorderState.js +0 -135
  18. package/dist/esm/state/ColumnResizeState.js +0 -55
  19. package/dist/esm/state/EventEmitter.js +0 -28
  20. package/dist/esm/state/FillHandleState.js +0 -206
  21. package/dist/esm/state/GridState.js +0 -324
  22. package/dist/esm/state/HeaderFilterState.js +0 -213
  23. package/dist/esm/state/KeyboardNavState.js +0 -216
  24. package/dist/esm/state/RowSelectionState.js +0 -72
  25. package/dist/esm/state/SelectionState.js +0 -109
  26. package/dist/esm/state/SideBarState.js +0 -41
  27. package/dist/esm/state/TableLayoutState.js +0 -97
  28. package/dist/esm/state/UndoRedoState.js +0 -71
  29. package/dist/esm/state/VirtualScrollState.js +0 -128
  30. package/dist/esm/types/columnTypes.js +0 -1
  31. package/dist/esm/types/gridTypes.js +0 -1
  32. package/dist/esm/types/index.js +0 -2
  33. package/dist/esm/utils/debounce.js +0 -2
  34. package/dist/esm/utils/getCellCoordinates.js +0 -15
  35. package/dist/esm/utils/index.js +0 -2
@@ -1,111 +0,0 @@
1
- import { normalizeSelectionRange, formatSelectionAsTsv, parseTsvClipboard, applyPastedValues, applyCutClear } from '@alaarab/ogrid-core';
2
- import { EventEmitter } from './EventEmitter';
3
- export class ClipboardState {
4
- constructor(params, getActiveCell, getSelectionRange) {
5
- this.emitter = new EventEmitter();
6
- this._cutRange = null;
7
- this._copyRange = null;
8
- this.internalClipboard = null;
9
- this.params = params;
10
- this.getActiveCell = getActiveCell;
11
- this.getSelectionRange = getSelectionRange;
12
- }
13
- updateParams(params) {
14
- this.params = params;
15
- }
16
- get cutRange() {
17
- return this._cutRange;
18
- }
19
- get copyRange() {
20
- return this._copyRange;
21
- }
22
- getEffectiveRange() {
23
- const sel = this.getSelectionRange();
24
- const ac = this.getActiveCell();
25
- return sel ?? (ac != null
26
- ? { startRow: ac.rowIndex, startCol: ac.columnIndex - this.params.colOffset, endRow: ac.rowIndex, endCol: ac.columnIndex - this.params.colOffset }
27
- : null);
28
- }
29
- handleCopy() {
30
- const range = this.getEffectiveRange();
31
- if (range == null)
32
- return;
33
- const norm = normalizeSelectionRange(range);
34
- const { items, visibleCols } = this.params;
35
- const tsv = formatSelectionAsTsv(items, visibleCols, norm);
36
- this.internalClipboard = tsv;
37
- this._copyRange = norm;
38
- this._cutRange = null;
39
- this.emitter.emit('rangesChange', { copyRange: this._copyRange, cutRange: null });
40
- if (typeof navigator !== 'undefined' && navigator.clipboard) {
41
- void navigator.clipboard.writeText(tsv).catch(() => { });
42
- }
43
- }
44
- handleCut() {
45
- if (this.params.editable === false)
46
- return;
47
- const range = this.getEffectiveRange();
48
- if (range == null)
49
- return;
50
- const norm = normalizeSelectionRange(range);
51
- this._cutRange = norm;
52
- this._copyRange = null;
53
- this.handleCopy();
54
- // handleCopy sets copyRange — override it back since this is a cut
55
- this._copyRange = null;
56
- this._cutRange = norm;
57
- this.emitter.emit('rangesChange', { copyRange: null, cutRange: this._cutRange });
58
- }
59
- async handlePaste() {
60
- if (this.params.editable === false)
61
- return;
62
- const { onCellValueChanged } = this.params;
63
- let text;
64
- try {
65
- if (typeof navigator !== 'undefined' && navigator.clipboard) {
66
- text = await navigator.clipboard.readText();
67
- }
68
- else {
69
- text = '';
70
- }
71
- }
72
- catch {
73
- text = '';
74
- }
75
- if (!text.trim() && this.internalClipboard != null) {
76
- text = this.internalClipboard;
77
- }
78
- if (!text.trim())
79
- return;
80
- if (onCellValueChanged == null)
81
- return;
82
- const norm = this.getEffectiveRange();
83
- const anchorRow = norm ? norm.startRow : 0;
84
- const anchorCol = norm ? norm.startCol : 0;
85
- const { items, visibleCols } = this.params;
86
- const parsedRows = parseTsvClipboard(text);
87
- const pasteEvents = applyPastedValues(parsedRows, anchorRow, anchorCol, items, visibleCols);
88
- for (const evt of pasteEvents)
89
- onCellValueChanged(evt);
90
- if (this._cutRange) {
91
- const cutEvents = applyCutClear(this._cutRange, items, visibleCols);
92
- for (const evt of cutEvents)
93
- onCellValueChanged(evt);
94
- this._cutRange = null;
95
- }
96
- this._copyRange = null;
97
- this.emitter.emit('rangesChange', { copyRange: null, cutRange: null });
98
- }
99
- clearClipboardRanges() {
100
- this._copyRange = null;
101
- this._cutRange = null;
102
- this.emitter.emit('rangesChange', { copyRange: null, cutRange: null });
103
- }
104
- onRangesChange(handler) {
105
- this.emitter.on('rangesChange', handler);
106
- return () => this.emitter.off('rangesChange', handler);
107
- }
108
- destroy() {
109
- this.emitter.removeAllListeners();
110
- }
111
- }
@@ -1,82 +0,0 @@
1
- import { ROW_NUMBER_COLUMN_WIDTH } from '@alaarab/ogrid-core';
2
- import { EventEmitter } from './EventEmitter';
3
- /**
4
- * Manages column pinning state — tracks which columns are pinned left/right.
5
- * Computes sticky offsets for the renderer.
6
- */
7
- export class ColumnPinningState {
8
- constructor(pinnedColumns, columns) {
9
- this.emitter = new EventEmitter();
10
- this._pinnedColumns = {};
11
- // Initialize from explicit pinnedColumns prop
12
- if (pinnedColumns) {
13
- this._pinnedColumns = { ...pinnedColumns };
14
- }
15
- // Also pick up pinned from column definitions
16
- if (columns) {
17
- for (const col of columns) {
18
- if (col.pinned && !(col.columnId in this._pinnedColumns)) {
19
- this._pinnedColumns[col.columnId] = col.pinned;
20
- }
21
- }
22
- }
23
- }
24
- get pinnedColumns() {
25
- return this._pinnedColumns;
26
- }
27
- pinColumn(columnId, side) {
28
- this._pinnedColumns = { ...this._pinnedColumns, [columnId]: side };
29
- this.emitter.emit('pinningChange', { pinnedColumns: this._pinnedColumns });
30
- }
31
- unpinColumn(columnId) {
32
- const { [columnId]: _, ...next } = this._pinnedColumns;
33
- this._pinnedColumns = next;
34
- this.emitter.emit('pinningChange', { pinnedColumns: this._pinnedColumns });
35
- }
36
- isPinned(columnId) {
37
- return this._pinnedColumns[columnId];
38
- }
39
- /**
40
- * Compute sticky left offsets for left-pinned columns.
41
- * Returns a map of columnId -> left offset in pixels.
42
- */
43
- computeLeftOffsets(visibleCols, columnWidths, defaultWidth, hasCheckboxColumn, checkboxColumnWidth, hasRowNumbersColumn) {
44
- const offsets = {};
45
- let left = 0;
46
- if (hasCheckboxColumn)
47
- left += checkboxColumnWidth;
48
- if (hasRowNumbersColumn)
49
- left += ROW_NUMBER_COLUMN_WIDTH;
50
- for (const col of visibleCols) {
51
- if (this._pinnedColumns[col.columnId] === 'left') {
52
- offsets[col.columnId] = left;
53
- left += columnWidths[col.columnId] ?? defaultWidth;
54
- }
55
- }
56
- return offsets;
57
- }
58
- /**
59
- * Compute sticky right offsets for right-pinned columns.
60
- * Returns a map of columnId -> right offset in pixels.
61
- */
62
- computeRightOffsets(visibleCols, columnWidths, defaultWidth) {
63
- const offsets = {};
64
- let right = 0;
65
- // Walk right-pinned columns from the end
66
- for (let i = visibleCols.length - 1; i >= 0; i--) {
67
- const col = visibleCols[i];
68
- if (this._pinnedColumns[col.columnId] === 'right') {
69
- offsets[col.columnId] = right;
70
- right += columnWidths[col.columnId] ?? defaultWidth;
71
- }
72
- }
73
- return offsets;
74
- }
75
- onPinningChange(handler) {
76
- this.emitter.on('pinningChange', handler);
77
- return () => this.emitter.off('pinningChange', handler);
78
- }
79
- destroy() {
80
- this.emitter.removeAllListeners();
81
- }
82
- }
@@ -1,135 +0,0 @@
1
- import { calculateDropTarget, reorderColumnArray, getPinStateForColumn } from '@alaarab/ogrid-core';
2
- import { EventEmitter } from './EventEmitter';
3
- /**
4
- * Manages column drag-to-reorder for the vanilla JS grid.
5
- * Follows the EventEmitter + RAF pattern from FillHandleState/SelectionState.
6
- */
7
- export class ColumnReorderState {
8
- constructor() {
9
- this.emitter = new EventEmitter();
10
- this._isDragging = false;
11
- this._draggedColumnId = null;
12
- this._dropIndicatorX = null;
13
- this._dropTargetIndex = null;
14
- this.rafId = 0;
15
- this.columnOrder = [];
16
- this.draggedPinState = 'unpinned';
17
- this.tableElement = null;
18
- this.onMoveBound = this.handleMouseMove.bind(this);
19
- this.onUpBound = this.handleMouseUp.bind(this);
20
- }
21
- get isDragging() {
22
- return this._isDragging;
23
- }
24
- get dropIndicatorX() {
25
- return this._dropIndicatorX;
26
- }
27
- /**
28
- * Begin a column drag operation.
29
- * Called from mousedown on a header cell.
30
- */
31
- startDrag(columnId, event, columns, columnOrder, pinnedColumns, tableElement) {
32
- event.preventDefault();
33
- this._isDragging = true;
34
- this._draggedColumnId = columnId;
35
- this._dropIndicatorX = null;
36
- this._dropTargetIndex = null;
37
- this.tableElement = tableElement;
38
- // Use provided column order, or derive from columns array
39
- this.columnOrder = columnOrder.length > 0
40
- ? [...columnOrder]
41
- : columns.map(c => c.columnId);
42
- // Convert Record<string, 'left' | 'right'> to { left?: string[]; right?: string[] }
43
- if (pinnedColumns) {
44
- const left = [];
45
- const right = [];
46
- for (const [id, side] of Object.entries(pinnedColumns)) {
47
- if (side === 'left')
48
- left.push(id);
49
- else if (side === 'right')
50
- right.push(id);
51
- }
52
- this.pinnedColumns = { left, right };
53
- }
54
- else {
55
- this.pinnedColumns = undefined;
56
- }
57
- this.draggedPinState = getPinStateForColumn(columnId, this.pinnedColumns);
58
- window.addEventListener('mousemove', this.onMoveBound, { capture: true, passive: true });
59
- window.addEventListener('mouseup', this.onUpBound, { capture: true, passive: true });
60
- this.emitter.emit('stateChange', { isDragging: true, dropIndicatorX: null });
61
- }
62
- handleMouseMove(event) {
63
- if (!this._isDragging || !this._draggedColumnId || !this.tableElement)
64
- return;
65
- if (this.rafId)
66
- cancelAnimationFrame(this.rafId);
67
- const mouseX = event.clientX;
68
- this.rafId = requestAnimationFrame(() => {
69
- this.rafId = 0;
70
- if (!this._draggedColumnId || !this.tableElement)
71
- return;
72
- const result = calculateDropTarget({
73
- mouseX,
74
- columnOrder: this.columnOrder,
75
- draggedColumnId: this._draggedColumnId,
76
- draggedPinState: this.draggedPinState,
77
- tableElement: this.tableElement,
78
- pinnedColumns: this.pinnedColumns,
79
- });
80
- if (!result)
81
- return;
82
- const prevX = this._dropIndicatorX;
83
- const prevIdx = this._dropTargetIndex;
84
- this._dropTargetIndex = result.targetIndex;
85
- this._dropIndicatorX = result.indicatorX;
86
- // Only emit if something changed
87
- if (prevX !== result.indicatorX || prevIdx !== result.targetIndex) {
88
- this.emitter.emit('stateChange', {
89
- isDragging: true,
90
- dropIndicatorX: result.indicatorX,
91
- });
92
- }
93
- });
94
- }
95
- handleMouseUp() {
96
- window.removeEventListener('mousemove', this.onMoveBound, true);
97
- window.removeEventListener('mouseup', this.onUpBound, true);
98
- if (this.rafId) {
99
- cancelAnimationFrame(this.rafId);
100
- this.rafId = 0;
101
- }
102
- // Commit reorder if we have a valid drop target that isn't a no-op
103
- if (this._isDragging &&
104
- this._draggedColumnId &&
105
- this._dropTargetIndex !== null &&
106
- this._dropIndicatorX !== null // null indicatorX means no-op (same position)
107
- ) {
108
- const newOrder = reorderColumnArray(this.columnOrder, this._draggedColumnId, this._dropTargetIndex);
109
- this.emitter.emit('reorder', { columnOrder: newOrder });
110
- }
111
- this._isDragging = false;
112
- this._draggedColumnId = null;
113
- this._dropIndicatorX = null;
114
- this._dropTargetIndex = null;
115
- this.tableElement = null;
116
- this.emitter.emit('stateChange', { isDragging: false, dropIndicatorX: null });
117
- }
118
- onStateChange(handler) {
119
- this.emitter.on('stateChange', handler);
120
- return () => this.emitter.off('stateChange', handler);
121
- }
122
- onReorder(handler) {
123
- this.emitter.on('reorder', handler);
124
- return () => this.emitter.off('reorder', handler);
125
- }
126
- destroy() {
127
- if (this._isDragging) {
128
- window.removeEventListener('mousemove', this.onMoveBound, true);
129
- window.removeEventListener('mouseup', this.onUpBound, true);
130
- }
131
- if (this.rafId)
132
- cancelAnimationFrame(this.rafId);
133
- this.emitter.removeAllListeners();
134
- }
135
- }
@@ -1,55 +0,0 @@
1
- import { DEFAULT_MIN_COLUMN_WIDTH } from '@alaarab/ogrid-core';
2
- import { EventEmitter } from './EventEmitter';
3
- export class ColumnResizeState {
4
- constructor() {
5
- this.emitter = new EventEmitter();
6
- this.columnWidths = new Map();
7
- this.isResizing = false;
8
- this.resizeColumnId = null;
9
- this.resizeStartX = 0;
10
- this.resizeStartWidth = 0;
11
- }
12
- get resizingColumnId() {
13
- return this.resizeColumnId;
14
- }
15
- getColumnWidth(columnId) {
16
- return this.columnWidths.get(columnId);
17
- }
18
- getAllColumnWidths() {
19
- const result = {};
20
- this.columnWidths.forEach((width, id) => {
21
- result[id] = width;
22
- });
23
- return result;
24
- }
25
- startResize(columnId, clientX, currentWidth) {
26
- this.isResizing = true;
27
- this.resizeColumnId = columnId;
28
- this.resizeStartX = clientX;
29
- this.resizeStartWidth = currentWidth;
30
- }
31
- updateResize(clientX) {
32
- if (!this.isResizing || !this.resizeColumnId)
33
- return null;
34
- const delta = clientX - this.resizeStartX;
35
- const newWidth = Math.max(DEFAULT_MIN_COLUMN_WIDTH, this.resizeStartWidth + delta);
36
- return newWidth;
37
- }
38
- endResize(clientX) {
39
- if (!this.isResizing || !this.resizeColumnId)
40
- return;
41
- const delta = clientX - this.resizeStartX;
42
- const newWidth = Math.max(DEFAULT_MIN_COLUMN_WIDTH, this.resizeStartWidth + delta);
43
- this.columnWidths.set(this.resizeColumnId, newWidth);
44
- this.emitter.emit('columnWidthChange', { columnId: this.resizeColumnId, widthPx: newWidth });
45
- this.isResizing = false;
46
- this.resizeColumnId = null;
47
- }
48
- onColumnWidthChange(handler) {
49
- this.emitter.on('columnWidthChange', handler);
50
- return () => this.emitter.off('columnWidthChange', handler);
51
- }
52
- destroy() {
53
- this.emitter.removeAllListeners();
54
- }
55
- }
@@ -1,28 +0,0 @@
1
- export class EventEmitter {
2
- constructor() {
3
- this.handlers = new Map();
4
- }
5
- on(event, handler) {
6
- if (!this.handlers.has(event)) {
7
- this.handlers.set(event, new Set());
8
- }
9
- this.handlers.get(event)?.add(handler);
10
- }
11
- off(event, handler) {
12
- this.handlers.get(event)?.delete(handler);
13
- }
14
- emit(event, ...args) {
15
- const data = args[0];
16
- this.handlers.get(event)?.forEach(handler => {
17
- handler(data);
18
- });
19
- }
20
- removeAllListeners(event) {
21
- if (event) {
22
- this.handlers.delete(event);
23
- }
24
- else {
25
- this.handlers.clear();
26
- }
27
- }
28
- }
@@ -1,206 +0,0 @@
1
- import { normalizeSelectionRange, applyFillValues } from '@alaarab/ogrid-core';
2
- import { EventEmitter } from './EventEmitter';
3
- import { getCellCoordinates } from '../utils/getCellCoordinates';
4
- /**
5
- * Manages Excel-style fill handle drag-to-fill for cell ranges (vanilla JS).
6
- * Mirrors the React `useFillHandle` hook as a class-based state.
7
- */
8
- export class FillHandleState {
9
- constructor(params, getSelectionRange, setSelectionRange, setActiveCell) {
10
- this.emitter = new EventEmitter();
11
- this.wrapperRef = null;
12
- this._isFillDragging = false;
13
- this.fillDragStart = null;
14
- this.fillDragEnd = { endRow: 0, endCol: 0 };
15
- this.rafHandle = 0;
16
- this.liveFillRange = null;
17
- this.lastMousePos = null;
18
- this.cachedCells = null;
19
- this.params = params;
20
- this.getSelectionRange = getSelectionRange;
21
- this.setSelectionRange = setSelectionRange;
22
- this.setActiveCell = setActiveCell;
23
- this.onMoveBound = this.onMouseMove.bind(this);
24
- this.onUpBound = this.onMouseUp.bind(this);
25
- }
26
- get isFillDragging() {
27
- return this._isFillDragging;
28
- }
29
- get fillRange() {
30
- return this.liveFillRange;
31
- }
32
- setWrapperRef(ref) {
33
- this.wrapperRef = ref;
34
- }
35
- updateParams(params) {
36
- this.params = params;
37
- }
38
- /** Called when the fill handle square is mousedown'd. */
39
- startFillDrag(e) {
40
- e.preventDefault();
41
- e.stopPropagation();
42
- const range = this.getSelectionRange();
43
- if (!range)
44
- return;
45
- if (this.params.editable === false || !this.params.onCellValueChanged)
46
- return;
47
- this._isFillDragging = true;
48
- this.fillDragStart = { startRow: range.startRow, startCol: range.startCol };
49
- this.fillDragEnd = { endRow: range.startRow, endCol: range.startCol };
50
- this.liveFillRange = null;
51
- // Cache querySelectorAll result once on drag start
52
- this.cachedCells = this.wrapperRef ? this.wrapperRef.querySelectorAll('[data-row-index][data-col-index]') : null;
53
- window.addEventListener('mousemove', this.onMoveBound, { capture: true, passive: true });
54
- window.addEventListener('mouseup', this.onUpBound, { capture: true, passive: true });
55
- }
56
- onMouseMove(e) {
57
- if (!this._isFillDragging || !this.fillDragStart)
58
- return;
59
- this.lastMousePos = { cx: e.clientX, cy: e.clientY };
60
- if (this.rafHandle)
61
- cancelAnimationFrame(this.rafHandle);
62
- this.rafHandle = requestAnimationFrame(() => {
63
- this.rafHandle = 0;
64
- if (!this.lastMousePos)
65
- return;
66
- const newRange = this.resolveRange(this.lastMousePos.cx, this.lastMousePos.cy);
67
- if (!newRange)
68
- return;
69
- // Skip if unchanged
70
- const prev = this.liveFillRange;
71
- if (prev &&
72
- prev.startRow === newRange.startRow &&
73
- prev.startCol === newRange.startCol &&
74
- prev.endRow === newRange.endRow &&
75
- prev.endCol === newRange.endCol) {
76
- return;
77
- }
78
- this.liveFillRange = newRange;
79
- this.fillDragEnd = { endRow: newRange.endRow, endCol: newRange.endCol };
80
- this.applyDragAttrs(newRange);
81
- });
82
- }
83
- onMouseUp() {
84
- if (!this._isFillDragging || !this.fillDragStart)
85
- return;
86
- window.removeEventListener('mousemove', this.onMoveBound, true);
87
- window.removeEventListener('mouseup', this.onUpBound, true);
88
- if (this.rafHandle) {
89
- cancelAnimationFrame(this.rafHandle);
90
- this.rafHandle = 0;
91
- }
92
- // Flush: resolve final position
93
- if (this.lastMousePos) {
94
- const flushed = this.resolveRange(this.lastMousePos.cx, this.lastMousePos.cy);
95
- if (flushed) {
96
- this.liveFillRange = flushed;
97
- this.fillDragEnd = { endRow: flushed.endRow, endCol: flushed.endCol };
98
- }
99
- }
100
- this.clearDragAttrs();
101
- const start = this.fillDragStart;
102
- const end = this.fillDragEnd;
103
- const norm = normalizeSelectionRange({
104
- startRow: start.startRow,
105
- startCol: start.startCol,
106
- endRow: end.endRow,
107
- endCol: end.endCol,
108
- });
109
- // Commit range
110
- this.setSelectionRange(norm);
111
- this.setActiveCell({ rowIndex: end.endRow, columnIndex: end.endCol + this.params.colOffset });
112
- // Apply fill values
113
- this.applyFillValuesFromCore(norm, start);
114
- this._isFillDragging = false;
115
- this.fillDragStart = null;
116
- this.liveFillRange = null;
117
- this.lastMousePos = null;
118
- this.emitter.emit('fillRangeChange', { fillRange: null });
119
- }
120
- applyFillValuesFromCore(norm, start) {
121
- const { items, visibleCols, onCellValueChanged, beginBatch, endBatch } = this.params;
122
- if (!onCellValueChanged)
123
- return;
124
- const fillEvents = applyFillValues(norm, start.startRow, start.startCol, items, visibleCols);
125
- if (fillEvents.length > 0) {
126
- beginBatch?.();
127
- for (const evt of fillEvents)
128
- onCellValueChanged(evt);
129
- endBatch?.();
130
- }
131
- }
132
- resolveRange(cx, cy) {
133
- if (!this.fillDragStart || !this.wrapperRef)
134
- return null;
135
- const target = document.elementFromPoint(cx, cy);
136
- const cell = target?.closest?.('[data-row-index][data-col-index]');
137
- if (!cell || !this.wrapperRef.contains(cell))
138
- return null;
139
- const coords = getCellCoordinates(cell);
140
- if (!coords || coords.colIndex < this.params.colOffset)
141
- return null;
142
- const r = coords.rowIndex;
143
- const dataCol = coords.colIndex - this.params.colOffset;
144
- return normalizeSelectionRange({
145
- startRow: this.fillDragStart.startRow,
146
- startCol: this.fillDragStart.startCol,
147
- endRow: r,
148
- endCol: dataCol,
149
- });
150
- }
151
- applyDragAttrs(range) {
152
- const cells = this.cachedCells;
153
- if (!cells)
154
- return;
155
- const colOff = this.params.colOffset;
156
- const minR = Math.min(range.startRow, range.endRow);
157
- const maxR = Math.max(range.startRow, range.endRow);
158
- const minC = Math.min(range.startCol, range.endCol);
159
- const maxC = Math.max(range.startCol, range.endCol);
160
- for (let i = 0; i < cells.length; i++) {
161
- const el = cells[i];
162
- const coords = getCellCoordinates(el);
163
- if (!coords)
164
- continue;
165
- const r = coords.rowIndex;
166
- const c = coords.colIndex - colOff;
167
- const inRange = r >= minR && r <= maxR && c >= minC && c <= maxC;
168
- if (inRange) {
169
- if (!el.hasAttribute('data-drag-range'))
170
- el.setAttribute('data-drag-range', '');
171
- }
172
- else {
173
- if (el.hasAttribute('data-drag-range'))
174
- el.removeAttribute('data-drag-range');
175
- }
176
- }
177
- }
178
- clearDragAttrs() {
179
- const cells = this.cachedCells;
180
- if (cells) {
181
- for (let i = 0; i < cells.length; i++)
182
- cells[i].removeAttribute('data-drag-range');
183
- }
184
- this.cachedCells = null;
185
- }
186
- onFillRangeChange(handler) {
187
- this.emitter.on('fillRangeChange', handler);
188
- return () => this.emitter.off('fillRangeChange', handler);
189
- }
190
- destroy() {
191
- if (this._isFillDragging) {
192
- window.removeEventListener('mousemove', this.onMoveBound, true);
193
- window.removeEventListener('mouseup', this.onUpBound, true);
194
- this.clearDragAttrs();
195
- this._isFillDragging = false;
196
- this.fillDragStart = null;
197
- this.liveFillRange = null;
198
- this.lastMousePos = null;
199
- }
200
- if (this.rafHandle) {
201
- cancelAnimationFrame(this.rafHandle);
202
- this.rafHandle = 0;
203
- }
204
- this.emitter.removeAllListeners();
205
- }
206
- }