@alaarab/ogrid-vue 2.1.3 → 2.1.5
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/esm/index.js +4336 -15
- package/package.json +4 -4
- package/dist/esm/components/MarchingAntsOverlay.js +0 -144
- package/dist/esm/components/SideBar.js +0 -1
- package/dist/esm/components/StatusBar.js +0 -49
- package/dist/esm/components/createDataGridTable.js +0 -514
- package/dist/esm/components/createInlineCellEditor.js +0 -194
- package/dist/esm/components/createOGrid.js +0 -383
- package/dist/esm/composables/index.js +0 -33
- package/dist/esm/composables/useActiveCell.js +0 -77
- package/dist/esm/composables/useCellEditing.js +0 -27
- package/dist/esm/composables/useCellSelection.js +0 -359
- package/dist/esm/composables/useClipboard.js +0 -87
- package/dist/esm/composables/useColumnChooserState.js +0 -74
- package/dist/esm/composables/useColumnHeaderFilterState.js +0 -189
- package/dist/esm/composables/useColumnHeaderMenuState.js +0 -113
- package/dist/esm/composables/useColumnPinning.js +0 -64
- package/dist/esm/composables/useColumnReorder.js +0 -110
- package/dist/esm/composables/useColumnResize.js +0 -73
- package/dist/esm/composables/useContextMenu.js +0 -23
- package/dist/esm/composables/useDataGridState.js +0 -425
- package/dist/esm/composables/useDataGridTableSetup.js +0 -66
- package/dist/esm/composables/useDateFilterState.js +0 -36
- package/dist/esm/composables/useDebounce.js +0 -60
- package/dist/esm/composables/useFillHandle.js +0 -205
- package/dist/esm/composables/useFilterOptions.js +0 -39
- package/dist/esm/composables/useInlineCellEditorState.js +0 -42
- package/dist/esm/composables/useKeyboardNavigation.js +0 -232
- package/dist/esm/composables/useLatestRef.js +0 -27
- package/dist/esm/composables/useMultiSelectFilterState.js +0 -59
- package/dist/esm/composables/useOGrid.js +0 -491
- package/dist/esm/composables/usePeopleFilterState.js +0 -66
- package/dist/esm/composables/useRichSelectState.js +0 -59
- package/dist/esm/composables/useRowSelection.js +0 -75
- package/dist/esm/composables/useSideBarState.js +0 -41
- package/dist/esm/composables/useTableLayout.js +0 -85
- package/dist/esm/composables/useTextFilterState.js +0 -26
- package/dist/esm/composables/useUndoRedo.js +0 -65
- package/dist/esm/composables/useVirtualScroll.js +0 -87
- package/dist/esm/types/columnTypes.js +0 -1
- package/dist/esm/types/dataGridTypes.js +0 -1
- package/dist/esm/types/index.js +0 -1
- package/dist/esm/utils/dataGridViewModel.js +0 -23
- package/dist/esm/utils/index.js +0 -1
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { ref, computed } from 'vue';
|
|
2
|
-
const DEFAULT_PANELS = ['columns', 'filters'];
|
|
3
|
-
/**
|
|
4
|
-
* Manages side bar panel state: enabled panels, active panel, position, and toggle/close handlers.
|
|
5
|
-
*/
|
|
6
|
-
export function useSideBarState(params) {
|
|
7
|
-
const { config } = params;
|
|
8
|
-
const isEnabled = config != null && config !== false;
|
|
9
|
-
const parsed = (() => {
|
|
10
|
-
if (!isEnabled || config === true) {
|
|
11
|
-
return { panels: DEFAULT_PANELS, position: 'right', defaultPanel: null };
|
|
12
|
-
}
|
|
13
|
-
const def = config;
|
|
14
|
-
return {
|
|
15
|
-
panels: def.panels ?? DEFAULT_PANELS,
|
|
16
|
-
position: def.position ?? 'right',
|
|
17
|
-
defaultPanel: def.defaultPanel ?? null,
|
|
18
|
-
};
|
|
19
|
-
})();
|
|
20
|
-
const activePanel = ref(parsed.defaultPanel);
|
|
21
|
-
const setActivePanel = (panel) => {
|
|
22
|
-
activePanel.value = panel;
|
|
23
|
-
};
|
|
24
|
-
const toggle = (panel) => {
|
|
25
|
-
activePanel.value = activePanel.value === panel ? null : panel;
|
|
26
|
-
};
|
|
27
|
-
const close = () => {
|
|
28
|
-
activePanel.value = null;
|
|
29
|
-
};
|
|
30
|
-
const isOpen = computed(() => activePanel.value !== null);
|
|
31
|
-
return {
|
|
32
|
-
isEnabled,
|
|
33
|
-
activePanel,
|
|
34
|
-
setActivePanel,
|
|
35
|
-
panels: parsed.panels,
|
|
36
|
-
position: parsed.position,
|
|
37
|
-
isOpen,
|
|
38
|
-
toggle,
|
|
39
|
-
close,
|
|
40
|
-
};
|
|
41
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { ref, computed, watch, onMounted, onUnmounted } from 'vue';
|
|
2
|
-
import { CHECKBOX_COLUMN_WIDTH, DEFAULT_MIN_COLUMN_WIDTH, CELL_PADDING } from '@alaarab/ogrid-core';
|
|
3
|
-
/**
|
|
4
|
-
* Manages table layout: container width measurement, column sizing overrides,
|
|
5
|
-
* min/desired table width calculations.
|
|
6
|
-
*/
|
|
7
|
-
export function useTableLayout(params) {
|
|
8
|
-
const { wrapperRef, visibleCols, flatColumns, hasCheckboxCol, initialColumnWidths, onColumnResized, } = params;
|
|
9
|
-
// Container width measurement via ResizeObserver
|
|
10
|
-
const containerWidth = ref(0);
|
|
11
|
-
let resizeObserver;
|
|
12
|
-
const measure = () => {
|
|
13
|
-
const el = wrapperRef.value;
|
|
14
|
-
if (!el)
|
|
15
|
-
return;
|
|
16
|
-
const rect = el.getBoundingClientRect();
|
|
17
|
-
const cs = window.getComputedStyle(el);
|
|
18
|
-
const borderX = (parseFloat(cs.borderLeftWidth || '0') || 0) +
|
|
19
|
-
(parseFloat(cs.borderRightWidth || '0') || 0);
|
|
20
|
-
containerWidth.value = Math.max(0, rect.width - borderX);
|
|
21
|
-
};
|
|
22
|
-
onMounted(() => {
|
|
23
|
-
const el = wrapperRef.value;
|
|
24
|
-
if (el) {
|
|
25
|
-
if (typeof ResizeObserver !== 'undefined') {
|
|
26
|
-
resizeObserver = new ResizeObserver(measure);
|
|
27
|
-
resizeObserver.observe(el);
|
|
28
|
-
}
|
|
29
|
-
measure();
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
onUnmounted(() => {
|
|
33
|
-
resizeObserver?.disconnect();
|
|
34
|
-
});
|
|
35
|
-
// Column sizing overrides state
|
|
36
|
-
const columnSizingOverrides = ref((() => {
|
|
37
|
-
if (!initialColumnWidths)
|
|
38
|
-
return {};
|
|
39
|
-
const result = {};
|
|
40
|
-
for (const [id, width] of Object.entries(initialColumnWidths)) {
|
|
41
|
-
result[id] = { widthPx: width };
|
|
42
|
-
}
|
|
43
|
-
return result;
|
|
44
|
-
})());
|
|
45
|
-
const setColumnSizingOverrides = (value) => {
|
|
46
|
-
columnSizingOverrides.value = value;
|
|
47
|
-
};
|
|
48
|
-
// Minimum table width calculation
|
|
49
|
-
const minTableWidth = computed(() => {
|
|
50
|
-
const checkboxW = hasCheckboxCol.value ? CHECKBOX_COLUMN_WIDTH : 0;
|
|
51
|
-
return visibleCols.value.reduce((sum, c) => sum + (c.minWidth ?? DEFAULT_MIN_COLUMN_WIDTH) + CELL_PADDING, checkboxW);
|
|
52
|
-
});
|
|
53
|
-
// Cleanup effect: remove overrides for columns that no longer exist
|
|
54
|
-
watch(flatColumns, (cols) => {
|
|
55
|
-
const colIds = new Set(cols.map((c) => c.columnId));
|
|
56
|
-
const prev = columnSizingOverrides.value;
|
|
57
|
-
const keys = Object.keys(prev);
|
|
58
|
-
const kept = keys.filter((id) => colIds.has(id));
|
|
59
|
-
if (kept.length < keys.length) {
|
|
60
|
-
const next = {};
|
|
61
|
-
for (const id of kept)
|
|
62
|
-
next[id] = prev[id];
|
|
63
|
-
columnSizingOverrides.value = next;
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
// Desired table width calculation
|
|
67
|
-
const desiredTableWidth = computed(() => {
|
|
68
|
-
const checkboxW = hasCheckboxCol.value ? CHECKBOX_COLUMN_WIDTH : 0;
|
|
69
|
-
return visibleCols.value.reduce((sum, c) => {
|
|
70
|
-
const override = columnSizingOverrides.value[c.columnId];
|
|
71
|
-
const w = override
|
|
72
|
-
? override.widthPx
|
|
73
|
-
: (c.idealWidth ?? c.defaultWidth ?? c.minWidth ?? DEFAULT_MIN_COLUMN_WIDTH);
|
|
74
|
-
return sum + Math.max(c.minWidth ?? DEFAULT_MIN_COLUMN_WIDTH, w) + CELL_PADDING;
|
|
75
|
-
}, checkboxW);
|
|
76
|
-
});
|
|
77
|
-
return {
|
|
78
|
-
containerWidth,
|
|
79
|
-
minTableWidth,
|
|
80
|
-
desiredTableWidth,
|
|
81
|
-
columnSizingOverrides,
|
|
82
|
-
setColumnSizingOverrides,
|
|
83
|
-
onColumnResized,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { ref, watch } from 'vue';
|
|
2
|
-
export function useTextFilterState(params) {
|
|
3
|
-
const { textValue = '', onTextChange } = params;
|
|
4
|
-
const tempTextValue = ref(textValue);
|
|
5
|
-
// Sync temp state when popover opens
|
|
6
|
-
watch(params.isFilterOpen, (open) => {
|
|
7
|
-
if (open) {
|
|
8
|
-
tempTextValue.value = params.textValue ?? '';
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
const setTempTextValue = (v) => {
|
|
12
|
-
tempTextValue.value = v;
|
|
13
|
-
};
|
|
14
|
-
const handleTextApply = () => {
|
|
15
|
-
onTextChange?.(tempTextValue.value.trim());
|
|
16
|
-
};
|
|
17
|
-
const handleTextClear = () => {
|
|
18
|
-
tempTextValue.value = '';
|
|
19
|
-
};
|
|
20
|
-
return {
|
|
21
|
-
tempTextValue,
|
|
22
|
-
setTempTextValue,
|
|
23
|
-
handleTextApply,
|
|
24
|
-
handleTextClear,
|
|
25
|
-
};
|
|
26
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { ref } from 'vue';
|
|
2
|
-
import { UndoRedoStack } from '@alaarab/ogrid-core';
|
|
3
|
-
/**
|
|
4
|
-
* Wraps onCellValueChanged with an undo/redo history stack.
|
|
5
|
-
* Supports batch operations: changes between beginBatch/endBatch are one undo step.
|
|
6
|
-
*/
|
|
7
|
-
export function useUndoRedo(params) {
|
|
8
|
-
const { onCellValueChanged, maxUndoDepth = 100 } = params;
|
|
9
|
-
const stack = new UndoRedoStack(maxUndoDepth);
|
|
10
|
-
const canUndo = ref(false);
|
|
11
|
-
const canRedo = ref(false);
|
|
12
|
-
const updateFlags = () => {
|
|
13
|
-
canUndo.value = stack.canUndo;
|
|
14
|
-
canRedo.value = stack.canRedo;
|
|
15
|
-
};
|
|
16
|
-
const wrapped = onCellValueChanged
|
|
17
|
-
? (event) => {
|
|
18
|
-
stack.record(event);
|
|
19
|
-
if (!stack.isBatching) {
|
|
20
|
-
updateFlags();
|
|
21
|
-
}
|
|
22
|
-
onCellValueChanged(event);
|
|
23
|
-
}
|
|
24
|
-
: undefined;
|
|
25
|
-
const beginBatch = () => {
|
|
26
|
-
stack.beginBatch();
|
|
27
|
-
};
|
|
28
|
-
const endBatch = () => {
|
|
29
|
-
stack.endBatch();
|
|
30
|
-
updateFlags();
|
|
31
|
-
};
|
|
32
|
-
const undo = () => {
|
|
33
|
-
if (!onCellValueChanged)
|
|
34
|
-
return;
|
|
35
|
-
const lastBatch = stack.undo();
|
|
36
|
-
if (!lastBatch)
|
|
37
|
-
return;
|
|
38
|
-
updateFlags();
|
|
39
|
-
for (let i = lastBatch.length - 1; i >= 0; i--) {
|
|
40
|
-
const ev = lastBatch[i];
|
|
41
|
-
onCellValueChanged({ ...ev, oldValue: ev.newValue, newValue: ev.oldValue });
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
const redo = () => {
|
|
45
|
-
if (!onCellValueChanged)
|
|
46
|
-
return;
|
|
47
|
-
const nextBatch = stack.redo();
|
|
48
|
-
if (!nextBatch)
|
|
49
|
-
return;
|
|
50
|
-
updateFlags();
|
|
51
|
-
for (const ev of nextBatch) {
|
|
52
|
-
onCellValueChanged(ev);
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
return {
|
|
56
|
-
onCellValueChanged: wrapped,
|
|
57
|
-
undo,
|
|
58
|
-
redo,
|
|
59
|
-
canUndo,
|
|
60
|
-
canRedo,
|
|
61
|
-
beginBatch,
|
|
62
|
-
endBatch,
|
|
63
|
-
maxUndoDepth,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { ref, computed, watch, onUnmounted } from 'vue';
|
|
2
|
-
import { computeVisibleRange, computeTotalHeight, getScrollTopForRow, } from '@alaarab/ogrid-core';
|
|
3
|
-
/**
|
|
4
|
-
* Manages virtual scrolling with RAF-throttled scroll handling and ResizeObserver
|
|
5
|
-
* for container height tracking. Uses core's computeVisibleRange for range calculation.
|
|
6
|
-
*/
|
|
7
|
-
export function useVirtualScroll(params) {
|
|
8
|
-
const { totalRows, rowHeight, enabled, overscan = 5 } = params;
|
|
9
|
-
const containerRef = ref(null);
|
|
10
|
-
const scrollTop = ref(0);
|
|
11
|
-
const containerHeight = ref(0);
|
|
12
|
-
let rafId = 0;
|
|
13
|
-
let resizeObserver;
|
|
14
|
-
let prevObservedEl = null;
|
|
15
|
-
const visibleRange = computed(() => {
|
|
16
|
-
if (!enabled.value) {
|
|
17
|
-
return { startIndex: 0, endIndex: totalRows.value - 1, offsetTop: 0, offsetBottom: 0 };
|
|
18
|
-
}
|
|
19
|
-
return computeVisibleRange(scrollTop.value, rowHeight, containerHeight.value, totalRows.value, overscan);
|
|
20
|
-
});
|
|
21
|
-
const totalHeight = computed(() => {
|
|
22
|
-
if (!enabled.value)
|
|
23
|
-
return 0;
|
|
24
|
-
return computeTotalHeight(totalRows.value, rowHeight);
|
|
25
|
-
});
|
|
26
|
-
const onScroll = () => {
|
|
27
|
-
if (!rafId) {
|
|
28
|
-
rafId = requestAnimationFrame(() => {
|
|
29
|
-
rafId = 0;
|
|
30
|
-
const el = containerRef.value;
|
|
31
|
-
if (el) {
|
|
32
|
-
scrollTop.value = el.scrollTop;
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
const measure = () => {
|
|
38
|
-
const el = containerRef.value;
|
|
39
|
-
if (!el)
|
|
40
|
-
return;
|
|
41
|
-
containerHeight.value = el.clientHeight;
|
|
42
|
-
};
|
|
43
|
-
// Watch containerRef to attach/detach scroll listener and ResizeObserver.
|
|
44
|
-
// Track prevObservedEl to avoid re-observing the same element and to
|
|
45
|
-
// properly disconnect old observers before creating new ones.
|
|
46
|
-
watch(containerRef, (el) => {
|
|
47
|
-
if (el === prevObservedEl)
|
|
48
|
-
return; // skip if same element
|
|
49
|
-
// Teardown previous element
|
|
50
|
-
if (prevObservedEl) {
|
|
51
|
-
prevObservedEl.removeEventListener('scroll', onScroll);
|
|
52
|
-
}
|
|
53
|
-
if (resizeObserver) {
|
|
54
|
-
resizeObserver.disconnect();
|
|
55
|
-
resizeObserver = undefined;
|
|
56
|
-
}
|
|
57
|
-
prevObservedEl = el;
|
|
58
|
-
// Setup new element
|
|
59
|
-
if (el) {
|
|
60
|
-
el.addEventListener('scroll', onScroll, { passive: true });
|
|
61
|
-
if (typeof ResizeObserver !== 'undefined') {
|
|
62
|
-
resizeObserver = new ResizeObserver(measure);
|
|
63
|
-
resizeObserver.observe(el);
|
|
64
|
-
}
|
|
65
|
-
measure();
|
|
66
|
-
scrollTop.value = el.scrollTop;
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
onUnmounted(() => {
|
|
70
|
-
const el = containerRef.value;
|
|
71
|
-
if (el) {
|
|
72
|
-
el.removeEventListener('scroll', onScroll);
|
|
73
|
-
}
|
|
74
|
-
resizeObserver?.disconnect();
|
|
75
|
-
if (rafId) {
|
|
76
|
-
cancelAnimationFrame(rafId);
|
|
77
|
-
rafId = 0;
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
const scrollToRow = (index, align = 'start') => {
|
|
81
|
-
const el = containerRef.value;
|
|
82
|
-
if (!el)
|
|
83
|
-
return;
|
|
84
|
-
el.scrollTop = getScrollTopForRow(index, rowHeight, containerHeight.value, align);
|
|
85
|
-
};
|
|
86
|
-
return { containerRef, visibleRange, totalHeight, scrollToRow };
|
|
87
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { toUserLike, isInSelectionRange, normalizeSelectionRange } from '@alaarab/ogrid-core';
|
package/dist/esm/types/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { toUserLike, isInSelectionRange, normalizeSelectionRange } from './dataGridTypes';
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* View model helpers for Vue DataGridTable.
|
|
3
|
-
* Pure functions live in @alaarab/ogrid-core. This file re-exports them
|
|
4
|
-
* and adds Vue-specific helpers (getCellInteractionProps uses Vue event naming).
|
|
5
|
-
*/
|
|
6
|
-
// Re-export everything from core's dataGridViewModel
|
|
7
|
-
export { getHeaderFilterConfig, getCellRenderDescriptor, resolveCellDisplayContent, resolveCellStyle, buildInlineEditorProps, buildPopoverEditorProps, } from '@alaarab/ogrid-core';
|
|
8
|
-
export function getCellInteractionProps(descriptor, columnId, handlers) {
|
|
9
|
-
const base = {
|
|
10
|
-
'data-row-index': descriptor.rowIndex,
|
|
11
|
-
'data-col-index': descriptor.globalColIndex,
|
|
12
|
-
...(descriptor.isInRange ? { 'data-in-range': 'true' } : {}),
|
|
13
|
-
tabindex: descriptor.isActive ? 0 : -1,
|
|
14
|
-
onMousedown: (e) => handlers.handleCellMouseDown(e, descriptor.rowIndex, descriptor.globalColIndex),
|
|
15
|
-
onClick: () => handlers.setActiveCell({ rowIndex: descriptor.rowIndex, columnIndex: descriptor.globalColIndex }),
|
|
16
|
-
onContextmenu: (e) => handlers.handleCellContextMenu(e),
|
|
17
|
-
};
|
|
18
|
-
if (descriptor.canEditAny) {
|
|
19
|
-
base.role = 'button';
|
|
20
|
-
base.onDblclick = () => handlers.setEditingCell({ rowId: descriptor.rowId, columnId });
|
|
21
|
-
}
|
|
22
|
-
return base;
|
|
23
|
-
}
|
package/dist/esm/utils/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { getHeaderFilterConfig, getCellRenderDescriptor, resolveCellDisplayContent, resolveCellStyle, buildInlineEditorProps, buildPopoverEditorProps, getCellInteractionProps, } from './dataGridViewModel';
|