@alaarab/ogrid-vue 2.1.2 → 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 (44) hide show
  1. package/dist/esm/index.js +4336 -15
  2. package/package.json +4 -4
  3. package/dist/esm/components/MarchingAntsOverlay.js +0 -144
  4. package/dist/esm/components/SideBar.js +0 -1
  5. package/dist/esm/components/StatusBar.js +0 -49
  6. package/dist/esm/components/createDataGridTable.js +0 -514
  7. package/dist/esm/components/createInlineCellEditor.js +0 -194
  8. package/dist/esm/components/createOGrid.js +0 -383
  9. package/dist/esm/composables/index.js +0 -33
  10. package/dist/esm/composables/useActiveCell.js +0 -77
  11. package/dist/esm/composables/useCellEditing.js +0 -27
  12. package/dist/esm/composables/useCellSelection.js +0 -359
  13. package/dist/esm/composables/useClipboard.js +0 -87
  14. package/dist/esm/composables/useColumnChooserState.js +0 -74
  15. package/dist/esm/composables/useColumnHeaderFilterState.js +0 -189
  16. package/dist/esm/composables/useColumnHeaderMenuState.js +0 -113
  17. package/dist/esm/composables/useColumnPinning.js +0 -64
  18. package/dist/esm/composables/useColumnReorder.js +0 -110
  19. package/dist/esm/composables/useColumnResize.js +0 -73
  20. package/dist/esm/composables/useContextMenu.js +0 -23
  21. package/dist/esm/composables/useDataGridState.js +0 -425
  22. package/dist/esm/composables/useDataGridTableSetup.js +0 -66
  23. package/dist/esm/composables/useDateFilterState.js +0 -36
  24. package/dist/esm/composables/useDebounce.js +0 -60
  25. package/dist/esm/composables/useFillHandle.js +0 -205
  26. package/dist/esm/composables/useFilterOptions.js +0 -39
  27. package/dist/esm/composables/useInlineCellEditorState.js +0 -42
  28. package/dist/esm/composables/useKeyboardNavigation.js +0 -232
  29. package/dist/esm/composables/useLatestRef.js +0 -27
  30. package/dist/esm/composables/useMultiSelectFilterState.js +0 -59
  31. package/dist/esm/composables/useOGrid.js +0 -491
  32. package/dist/esm/composables/usePeopleFilterState.js +0 -66
  33. package/dist/esm/composables/useRichSelectState.js +0 -59
  34. package/dist/esm/composables/useRowSelection.js +0 -75
  35. package/dist/esm/composables/useSideBarState.js +0 -41
  36. package/dist/esm/composables/useTableLayout.js +0 -85
  37. package/dist/esm/composables/useTextFilterState.js +0 -26
  38. package/dist/esm/composables/useUndoRedo.js +0 -65
  39. package/dist/esm/composables/useVirtualScroll.js +0 -87
  40. package/dist/esm/types/columnTypes.js +0 -1
  41. package/dist/esm/types/dataGridTypes.js +0 -1
  42. package/dist/esm/types/index.js +0 -1
  43. package/dist/esm/utils/dataGridViewModel.js +0 -23
  44. package/dist/esm/utils/index.js +0 -1
@@ -1,189 +0,0 @@
1
- import { ref, computed, watch, onUnmounted } from 'vue';
2
- import { useTextFilterState } from './useTextFilterState';
3
- import { useMultiSelectFilterState } from './useMultiSelectFilterState';
4
- import { usePeopleFilterState } from './usePeopleFilterState';
5
- import { useDateFilterState } from './useDateFilterState';
6
- const EMPTY_OPTIONS = [];
7
- export function useColumnHeaderFilterState(params) {
8
- const { filterType, onSort, } = params;
9
- // Access params.selectedValues as a getter so hasActiveFilter tracks the reactive prop
10
- // (when params is Vue's reactive props object, this is reactive; plain objects are snapshots)
11
- const safeSelectedValues = () => params.selectedValues ?? EMPTY_OPTIONS;
12
- // Shared state
13
- const headerRef = ref(null);
14
- const popoverRef = ref(null);
15
- const isFilterOpen = ref(false);
16
- const popoverPosition = ref(null);
17
- const setFilterOpen = (open) => {
18
- isFilterOpen.value = open;
19
- };
20
- // Compose sub-hooks — pass the ref directly so Vue's reactivity system
21
- // can properly track dependencies (instead of a getter function wrapper)
22
- const textFilterState = useTextFilterState({
23
- textValue: params.textValue,
24
- onTextChange: params.onTextChange,
25
- isFilterOpen,
26
- });
27
- const multiSelectFilterState = useMultiSelectFilterState({
28
- selectedValues: params.selectedValues,
29
- onFilterChange: params.onFilterChange,
30
- options: params.options,
31
- isFilterOpen,
32
- });
33
- const peopleFilterState = usePeopleFilterState({
34
- selectedUser: params.selectedUser,
35
- onUserChange: params.onUserChange,
36
- peopleSearch: params.peopleSearch,
37
- isFilterOpen,
38
- filterType,
39
- });
40
- const dateFilterState = useDateFilterState({
41
- dateValue: params.dateValue,
42
- onDateChange: params.onDateChange,
43
- isFilterOpen,
44
- });
45
- // Close popover resets position
46
- watch(isFilterOpen, (open) => {
47
- if (!open) {
48
- popoverPosition.value = null;
49
- }
50
- });
51
- // Click outside and Escape to close
52
- let clickOutsideHandler = null;
53
- let keyDownHandler = null;
54
- let clickOutsideTimeout;
55
- const setupListeners = () => {
56
- cleanupListeners();
57
- clickOutsideHandler = (e) => {
58
- const target = e.target;
59
- if (popoverRef.value && !popoverRef.value.contains(target) &&
60
- headerRef.value && !headerRef.value.contains(target)) {
61
- isFilterOpen.value = false;
62
- }
63
- };
64
- keyDownHandler = (e) => {
65
- if (e.key === 'Escape' || e.key === 'Esc') {
66
- e.preventDefault();
67
- e.stopPropagation();
68
- isFilterOpen.value = false;
69
- }
70
- };
71
- clickOutsideTimeout = setTimeout(() => { if (clickOutsideHandler)
72
- document.addEventListener('mousedown', clickOutsideHandler); }, 0);
73
- document.addEventListener('keydown', keyDownHandler, true);
74
- };
75
- const cleanupListeners = () => {
76
- if (clickOutsideTimeout)
77
- clearTimeout(clickOutsideTimeout);
78
- if (clickOutsideHandler)
79
- document.removeEventListener('mousedown', clickOutsideHandler);
80
- if (keyDownHandler)
81
- document.removeEventListener('keydown', keyDownHandler, true);
82
- clickOutsideHandler = null;
83
- keyDownHandler = null;
84
- };
85
- watch(isFilterOpen, (open) => {
86
- if (open)
87
- setupListeners();
88
- else
89
- cleanupListeners();
90
- });
91
- onUnmounted(() => cleanupListeners());
92
- // Shared handlers
93
- const handleFilterIconClick = (e) => {
94
- e.stopPropagation();
95
- e.preventDefault();
96
- if (!isFilterOpen.value && headerRef.value) {
97
- const rect = headerRef.value.getBoundingClientRect();
98
- popoverPosition.value = { top: rect.bottom + 4, left: rect.left };
99
- }
100
- isFilterOpen.value = !isFilterOpen.value;
101
- };
102
- const handleSortClick = (e) => {
103
- e.stopPropagation();
104
- onSort?.();
105
- };
106
- const handleApplyMultiSelect = () => {
107
- multiSelectFilterState.handleApplyMultiSelect();
108
- isFilterOpen.value = false;
109
- };
110
- const handleTextApply = () => {
111
- textFilterState.handleTextApply();
112
- isFilterOpen.value = false;
113
- };
114
- const handleUserSelect = (user) => {
115
- peopleFilterState.handleUserSelect(user);
116
- isFilterOpen.value = false;
117
- };
118
- const handleClearUser = () => {
119
- peopleFilterState.handleClearUser();
120
- isFilterOpen.value = false;
121
- };
122
- const handleDateApply = () => {
123
- dateFilterState.handleDateApply();
124
- isFilterOpen.value = false;
125
- };
126
- const handlePopoverClick = (e) => e.stopPropagation();
127
- const handleInputFocus = (e) => e.stopPropagation();
128
- const handleInputMouseDown = (e) => e.stopPropagation();
129
- const handleInputClick = (e) => e.stopPropagation();
130
- const handleInputKeyDown = (e) => {
131
- if (e.key !== 'Escape' && e.key !== 'Esc')
132
- e.stopPropagation();
133
- };
134
- const hasActiveFilter = computed(() => {
135
- if (filterType === 'multiSelect')
136
- return safeSelectedValues().length > 0;
137
- if (filterType === 'text')
138
- return !!(params.textValue ?? '').trim();
139
- if (filterType === 'people')
140
- return !!params.selectedUser;
141
- if (filterType === 'date')
142
- return !!(params.dateValue?.from || params.dateValue?.to);
143
- return false;
144
- });
145
- return {
146
- headerRef,
147
- popoverRef,
148
- peopleInputRef: peopleFilterState.peopleInputRef,
149
- isFilterOpen,
150
- setFilterOpen,
151
- tempSelected: multiSelectFilterState.tempSelected,
152
- setTempSelected: multiSelectFilterState.setTempSelected,
153
- tempTextValue: textFilterState.tempTextValue,
154
- setTempTextValue: textFilterState.setTempTextValue,
155
- searchText: multiSelectFilterState.searchText,
156
- setSearchText: multiSelectFilterState.setSearchText,
157
- debouncedSearchText: multiSelectFilterState.debouncedSearchText,
158
- filteredOptions: multiSelectFilterState.filteredOptions,
159
- peopleSuggestions: peopleFilterState.peopleSuggestions,
160
- isPeopleLoading: peopleFilterState.isPeopleLoading,
161
- peopleSearchText: peopleFilterState.peopleSearchText,
162
- setPeopleSearchText: peopleFilterState.setPeopleSearchText,
163
- tempDateFrom: dateFilterState.tempDateFrom,
164
- setTempDateFrom: dateFilterState.setTempDateFrom,
165
- tempDateTo: dateFilterState.tempDateTo,
166
- setTempDateTo: dateFilterState.setTempDateTo,
167
- hasActiveFilter,
168
- popoverPosition,
169
- handlers: {
170
- handleFilterIconClick,
171
- handleApplyMultiSelect,
172
- handleTextApply,
173
- handleTextClear: textFilterState.handleTextClear,
174
- handleUserSelect,
175
- handleClearUser,
176
- handleCheckboxChange: multiSelectFilterState.handleCheckboxChange,
177
- handleSelectAll: multiSelectFilterState.handleSelectAll,
178
- handleClearSelection: multiSelectFilterState.handleClearSelection,
179
- handlePopoverClick,
180
- handleInputFocus,
181
- handleInputMouseDown,
182
- handleInputClick,
183
- handleInputKeyDown,
184
- handleDateApply,
185
- handleDateClear: dateFilterState.handleDateClear,
186
- handleSortClick,
187
- },
188
- };
189
- }
@@ -1,113 +0,0 @@
1
- import { ref, computed } from 'vue';
2
- import { measureColumnContentWidth } from '@alaarab/ogrid-core';
3
- /**
4
- * Manages state for the column header menu (pin/unpin, sort, autosize actions).
5
- * Tracks which column's menu is open, anchor element, and action handlers.
6
- */
7
- export function useColumnHeaderMenuState(params) {
8
- const { columns, pinnedColumns, onPinColumn, onUnpinColumn, onSort, onColumnResized, onAutosizeColumn, sortBy, sortDirection, } = params;
9
- const isOpen = ref(false);
10
- const openForColumn = ref(null);
11
- const anchorElement = ref(null);
12
- const open = (columnId, anchorEl) => {
13
- openForColumn.value = columnId;
14
- anchorElement.value = anchorEl;
15
- isOpen.value = true;
16
- };
17
- const close = () => {
18
- isOpen.value = false;
19
- openForColumn.value = null;
20
- anchorElement.value = null;
21
- };
22
- const currentColumn = computed(() => openForColumn.value ? columns.value.find((c) => c.columnId === openForColumn.value) : undefined);
23
- const currentPinState = computed(() => openForColumn.value ? pinnedColumns.value[openForColumn.value] : undefined);
24
- const canPinLeft = computed(() => currentPinState.value !== 'left');
25
- const canPinRight = computed(() => currentPinState.value !== 'right');
26
- const canUnpin = computed(() => !!currentPinState.value);
27
- const currentSort = computed(() => {
28
- if (!openForColumn.value || !sortBy?.value || sortBy.value !== openForColumn.value) {
29
- return null;
30
- }
31
- return sortDirection?.value ?? null;
32
- });
33
- const isSortable = computed(() => {
34
- const col = currentColumn.value;
35
- return col?.sortable !== false;
36
- });
37
- // All columns are resizable by default (no per-column resizable flag in core)
38
- const isResizable = ref(true);
39
- const handlePinLeft = () => {
40
- if (openForColumn.value && canPinLeft.value) {
41
- onPinColumn(openForColumn.value, 'left');
42
- close();
43
- }
44
- };
45
- const handlePinRight = () => {
46
- if (openForColumn.value && canPinRight.value) {
47
- onPinColumn(openForColumn.value, 'right');
48
- close();
49
- }
50
- };
51
- const handleUnpin = () => {
52
- if (openForColumn.value && canUnpin.value) {
53
- onUnpinColumn(openForColumn.value);
54
- close();
55
- }
56
- };
57
- const handleSortAsc = () => {
58
- if (openForColumn.value && onSort) {
59
- onSort(openForColumn.value, 'asc');
60
- close();
61
- }
62
- };
63
- const handleSortDesc = () => {
64
- if (openForColumn.value && onSort) {
65
- onSort(openForColumn.value, 'desc');
66
- close();
67
- }
68
- };
69
- const handleClearSort = () => {
70
- if (openForColumn.value && onSort) {
71
- onSort(openForColumn.value, null);
72
- close();
73
- }
74
- };
75
- const handleAutosizeThis = () => {
76
- const resizer = onAutosizeColumn ?? onColumnResized;
77
- if (!openForColumn.value || !resizer || !isResizable.value)
78
- return;
79
- const col = currentColumn.value;
80
- resizer(openForColumn.value, measureColumnContentWidth(openForColumn.value, col?.minWidth));
81
- close();
82
- };
83
- const handleAutosizeAll = () => {
84
- const resizer = onAutosizeColumn ?? onColumnResized;
85
- if (!resizer)
86
- return;
87
- columns.value.forEach((col) => {
88
- resizer(col.columnId, measureColumnContentWidth(col.columnId, col.minWidth));
89
- });
90
- close();
91
- };
92
- return {
93
- isOpen,
94
- openForColumn,
95
- anchorElement,
96
- open,
97
- close,
98
- handlePinLeft,
99
- handlePinRight,
100
- handleUnpin,
101
- handleSortAsc,
102
- handleSortDesc,
103
- handleClearSort,
104
- handleAutosizeThis,
105
- handleAutosizeAll,
106
- canPinLeft,
107
- canPinRight,
108
- canUnpin,
109
- currentSort,
110
- isSortable,
111
- isResizable,
112
- };
113
- }
@@ -1,64 +0,0 @@
1
- import { ref, computed } from 'vue';
2
- /**
3
- * Manages column pinning state (left/right sticky positioning).
4
- * Supports controlled and uncontrolled modes.
5
- * Initializes from column.pinned definitions and pinnedColumns prop.
6
- */
7
- export function useColumnPinning(params) {
8
- const { columns, pinnedColumns: controlledPinnedColumns, onColumnPinned } = params;
9
- // Initialize internal state from column.pinned definitions (only on mount)
10
- const initialPinnedColumns = {};
11
- for (const col of columns.value) {
12
- if (col.pinned) {
13
- initialPinnedColumns[col.columnId] = col.pinned;
14
- }
15
- }
16
- const internalPinnedColumns = ref(initialPinnedColumns);
17
- // Use controlled state if provided, otherwise internal
18
- const pinnedColumns = computed(() => controlledPinnedColumns?.value ?? internalPinnedColumns.value);
19
- const pinColumn = (columnId, side) => {
20
- const next = { ...pinnedColumns.value, [columnId]: side };
21
- internalPinnedColumns.value = next;
22
- onColumnPinned?.(columnId, side);
23
- };
24
- const unpinColumn = (columnId) => {
25
- const { [columnId]: _removed, ...next } = pinnedColumns.value;
26
- void _removed;
27
- internalPinnedColumns.value = next;
28
- onColumnPinned?.(columnId, null);
29
- };
30
- const isPinned = (columnId) => {
31
- return pinnedColumns.value[columnId];
32
- };
33
- const computeLeftOffsets = (visibleCols, columnWidths, defaultWidth, hasCheckboxColumn, checkboxColumnWidth) => {
34
- const offsets = {};
35
- let left = hasCheckboxColumn ? checkboxColumnWidth : 0;
36
- for (const col of visibleCols) {
37
- if (pinnedColumns.value[col.columnId] === 'left') {
38
- offsets[col.columnId] = left;
39
- left += columnWidths[col.columnId] ?? defaultWidth;
40
- }
41
- }
42
- return offsets;
43
- };
44
- const computeRightOffsets = (visibleCols, columnWidths, defaultWidth) => {
45
- const offsets = {};
46
- let right = 0;
47
- for (let i = visibleCols.length - 1; i >= 0; i--) {
48
- const col = visibleCols[i];
49
- if (pinnedColumns.value[col.columnId] === 'right') {
50
- offsets[col.columnId] = right;
51
- right += columnWidths[col.columnId] ?? defaultWidth;
52
- }
53
- }
54
- return offsets;
55
- };
56
- return {
57
- pinnedColumns,
58
- pinColumn,
59
- unpinColumn,
60
- isPinned,
61
- computeLeftOffsets,
62
- computeRightOffsets,
63
- };
64
- }
@@ -1,110 +0,0 @@
1
- import { ref, onUnmounted } from 'vue';
2
- import { calculateDropTarget, reorderColumnArray, getPinStateForColumn, } from '@alaarab/ogrid-core';
3
- /** Width of the resize handle zone on the right edge of each header cell. */
4
- const RESIZE_HANDLE_ZONE = 8;
5
- /** Minimum drag distance (px) before activating reorder to prevent accidental drags on click. */
6
- const MIN_DRAG_DISTANCE = 5;
7
- /**
8
- * Manages column reordering via drag-and-drop on header cells.
9
- * Uses RAF-throttled mouse tracking and core's calculateDropTarget/reorderColumnArray.
10
- */
11
- export function useColumnReorder(params) {
12
- const { columnOrder, onColumnOrderChange, tableRef, pinnedColumns } = params;
13
- const isDragging = ref(false);
14
- const dropIndicatorX = ref(null);
15
- let draggedColumnId = null;
16
- let draggedPinState = 'unpinned';
17
- let rafId = 0;
18
- let cleanupFn = null;
19
- onUnmounted(() => {
20
- cleanupFn?.();
21
- cleanupFn = null;
22
- });
23
- const handleHeaderMouseDown = (columnId, event) => {
24
- if (event.button !== 0)
25
- return;
26
- // Skip if in resize handle zone (right 8px of the header cell)
27
- const th = event.target.closest('th');
28
- if (th) {
29
- const rect = th.getBoundingClientRect();
30
- if (event.clientX > rect.right - RESIZE_HANDLE_ZONE)
31
- return;
32
- }
33
- event.preventDefault();
34
- const table = tableRef.value;
35
- if (!table)
36
- return;
37
- if (!onColumnOrderChange.value)
38
- return;
39
- draggedColumnId = columnId;
40
- draggedPinState = getPinStateForColumn(columnId, pinnedColumns?.value);
41
- dropIndicatorX.value = null;
42
- const startX = event.clientX;
43
- let hasMoved = false;
44
- let latestMouseX = event.clientX;
45
- let targetIndex = -1;
46
- const prevCursor = document.body.style.cursor;
47
- const prevUserSelect = document.body.style.userSelect;
48
- document.body.style.cursor = 'grabbing';
49
- document.body.style.userSelect = 'none';
50
- const onMove = (moveEvent) => {
51
- // Require minimum drag distance before activating
52
- if (!hasMoved && Math.abs(moveEvent.clientX - startX) < MIN_DRAG_DISTANCE)
53
- return;
54
- if (!hasMoved) {
55
- hasMoved = true;
56
- isDragging.value = true;
57
- }
58
- latestMouseX = moveEvent.clientX;
59
- if (!rafId) {
60
- rafId = requestAnimationFrame(() => {
61
- rafId = 0;
62
- const tableEl = tableRef.value;
63
- if (!tableEl || !draggedColumnId)
64
- return;
65
- const result = calculateDropTarget({
66
- mouseX: latestMouseX,
67
- columnOrder: columnOrder.value,
68
- draggedColumnId,
69
- draggedPinState,
70
- tableElement: tableEl,
71
- pinnedColumns: pinnedColumns?.value,
72
- });
73
- if (result) {
74
- targetIndex = result.targetIndex;
75
- dropIndicatorX.value = result.indicatorX;
76
- }
77
- else {
78
- dropIndicatorX.value = null;
79
- }
80
- });
81
- }
82
- };
83
- const cleanup = () => {
84
- window.removeEventListener('mousemove', onMove, true);
85
- window.removeEventListener('mouseup', onUp, true);
86
- cleanupFn = null;
87
- document.body.style.cursor = prevCursor;
88
- document.body.style.userSelect = prevUserSelect;
89
- if (rafId) {
90
- cancelAnimationFrame(rafId);
91
- rafId = 0;
92
- }
93
- };
94
- const onUp = () => {
95
- cleanup();
96
- if (hasMoved && draggedColumnId && targetIndex >= 0 && onColumnOrderChange.value) {
97
- const newOrder = reorderColumnArray(columnOrder.value, draggedColumnId, targetIndex);
98
- onColumnOrderChange.value(newOrder);
99
- }
100
- draggedColumnId = null;
101
- isDragging.value = false;
102
- dropIndicatorX.value = null;
103
- targetIndex = -1;
104
- };
105
- window.addEventListener('mousemove', onMove, true);
106
- window.addEventListener('mouseup', onUp, true);
107
- cleanupFn = cleanup;
108
- };
109
- return { isDragging, dropIndicatorX, handleHeaderMouseDown };
110
- }
@@ -1,73 +0,0 @@
1
- import { onUnmounted } from 'vue';
2
- /**
3
- * Manages column resize drag interactions with RAF-throttled state updates.
4
- */
5
- export function useColumnResize(params) {
6
- const { columnSizingOverrides, setColumnSizingOverrides, minWidth = 80, defaultWidth = 120, onColumnResized, } = params;
7
- let rafId = 0;
8
- let cleanupFn = null;
9
- onUnmounted(() => {
10
- cleanupFn?.();
11
- cleanupFn = null;
12
- });
13
- const handleResizeStart = (e, col) => {
14
- e.preventDefault();
15
- e.stopPropagation();
16
- const startX = e.clientX;
17
- const columnId = col.columnId;
18
- const thEl = e.currentTarget.parentElement;
19
- const startWidth = thEl
20
- ? thEl.getBoundingClientRect().width
21
- : columnSizingOverrides.value[columnId]?.widthPx
22
- ?? col.idealWidth
23
- ?? col.defaultWidth
24
- ?? defaultWidth;
25
- let latestWidth = startWidth;
26
- const prevCursor = document.body.style.cursor;
27
- const prevUserSelect = document.body.style.userSelect;
28
- document.body.style.cursor = 'col-resize';
29
- document.body.style.userSelect = 'none';
30
- const flushWidth = () => {
31
- setColumnSizingOverrides({
32
- ...columnSizingOverrides.value,
33
- [columnId]: { widthPx: latestWidth },
34
- });
35
- };
36
- const onMove = (moveEvent) => {
37
- const deltaX = moveEvent.clientX - startX;
38
- latestWidth = Math.max(minWidth, startWidth + deltaX);
39
- if (!rafId) {
40
- rafId = requestAnimationFrame(() => {
41
- rafId = 0;
42
- flushWidth();
43
- });
44
- }
45
- };
46
- const cleanup = () => {
47
- document.removeEventListener('mousemove', onMove);
48
- document.removeEventListener('mouseup', onUp);
49
- cleanupFn = null;
50
- document.body.style.cursor = prevCursor;
51
- document.body.style.userSelect = prevUserSelect;
52
- if (rafId) {
53
- cancelAnimationFrame(rafId);
54
- rafId = 0;
55
- }
56
- };
57
- const onUp = () => {
58
- cleanup();
59
- flushWidth();
60
- onColumnResized?.(columnId, latestWidth);
61
- };
62
- document.addEventListener('mousemove', onMove);
63
- document.addEventListener('mouseup', onUp);
64
- cleanupFn = cleanup;
65
- };
66
- const getColumnWidth = (col) => {
67
- return columnSizingOverrides.value[col.columnId]?.widthPx
68
- ?? col.idealWidth
69
- ?? col.defaultWidth
70
- ?? defaultWidth;
71
- };
72
- return { handleResizeStart, getColumnWidth };
73
- }
@@ -1,23 +0,0 @@
1
- import { shallowRef } from 'vue';
2
- /**
3
- * Manages context menu position state for right-click menus.
4
- */
5
- export function useContextMenu() {
6
- const contextMenuPosition = shallowRef(null);
7
- const setContextMenuPosition = (pos) => {
8
- contextMenuPosition.value = pos;
9
- };
10
- const handleCellContextMenu = (e) => {
11
- e.preventDefault?.();
12
- contextMenuPosition.value = { x: e.clientX, y: e.clientY };
13
- };
14
- const closeContextMenu = () => {
15
- contextMenuPosition.value = null;
16
- };
17
- return {
18
- contextMenuPosition,
19
- setContextMenuPosition,
20
- handleCellContextMenu,
21
- closeContextMenu,
22
- };
23
- }