feat(grid): auto compact toolbar on overflow

This commit is contained in:
二丫讲梵 authored and GitHub committed 2026-08-31 22:30:57 +08:00
1 parent b60f04ea61
commit a84cb637ba
2 files changed
+101 -2

No files matched your search

+75 -2
View File
@@ -701,6 +701,8 @@ const columnCommentMap = computed(() => {
});
const dataGridTopbarWidth = ref(0);
const dataGridViewportWidth = ref(0);
const dataGridTopbarOverflowCompact = ref(false);
const dataGridTopbarExpandedRequiredWidth = ref(0);
const showColumnCommentsInHeader = computed(() => settingsStore.editorSettings.showColumnCommentsInHeader);
const showColumnTypesInHeader = computed(() => settingsStore.editorSettings.showColumnTypesInHeader);
const showTransposeFieldMetadata = computed(() => settingsStore.editorSettings.dataGridShowTransposeFieldMetadata);
@@ -720,7 +722,7 @@ const columnIndexMap = computed(() => buildColumnIndexMap(indexes.value, primary
const compactColumnHeaderActions = computed(() => settingsStore.editorSettings.compactColumnHeaderActions);
const dataGridRenderMode = computed(() => settingsStore.editorSettings.dataGridRenderMode);
const dataGridSearchMode = computed(() => settingsStore.editorSettings.dataGridSearchMode);
const compactDataGridToolbar = computed(() => isDataGridToolbarCompact(dataGridTopbarWidth.value, dataGridViewportWidth.value, DATA_GRID_CONDITION_TOOLBAR_MIN_WIDTH));
const compactDataGridToolbar = computed(() => dataGridTopbarOverflowCompact.value || isDataGridToolbarCompact(dataGridTopbarWidth.value, dataGridViewportWidth.value, DATA_GRID_CONDITION_TOOLBAR_MIN_WIDTH));
const infiniteScrollEnabled = computed(() => props.paginationEnabled && settingsStore.editorSettings.infiniteScroll);
const queryResultMaxRows = computed(() => effectiveQueryResultMaxRows(settingsStore.editorSettings.queryResultMaxRowsEnabled, settingsStore.editorSettings.queryResultMaxRows));
const paginationMaxRows = computed(() => (isResultsContext.value ? queryResultMaxRows.value : undefined));
@@ -2535,6 +2537,8 @@ let gridVerticalScrollbarThumbTopPercent = 0;
let gridVerticalScrollbarThumbHeightPercent = 100;
let gridScrollbarsRuntime: DataGridScrollbarsRuntime;
let dataGridTopbarResizeObserver: ResizeObserver | null = null;
let dataGridTopbarMutationObserver: MutationObserver | null = null;
let dataGridTopbarRecheckTimer: ReturnType<typeof setTimeout> | null = null;
let cellEditResizeObserver: ResizeObserver | null = null;
// vue-virtual-scroller's @resize only fires in pageMode (it observes window),
// so in container-scroll mode (transpose uses RecycleScroller without pageMode)
@@ -3183,19 +3187,68 @@ function observeGridHorizontalScrollbarScroller() {
}
function updateDataGridTopbarWidth() {
dataGridTopbarWidth.value = dataGridTopbarRef.value?.clientWidth ?? 0;
const topbar = dataGridTopbarRef.value;
dataGridTopbarWidth.value = topbar?.clientWidth ?? 0;
dataGridViewportWidth.value = typeof window === "undefined" ? 0 : window.innerWidth;
if (!topbar) return;
const fixedBreakpointCompact = isDataGridToolbarCompact(dataGridTopbarWidth.value, dataGridViewportWidth.value, DATA_GRID_CONDITION_TOOLBAR_MIN_WIDTH);
if (fixedBreakpointCompact) return;
if (dataGridTopbarOverflowCompact.value) {
if (dataGridTopbarWidth.value >= dataGridTopbarExpandedRequiredWidth.value) {
dataGridTopbarOverflowCompact.value = false;
dataGridTopbarExpandedRequiredWidth.value = 0;
}
return;
}
// The action list gains preview/save/rollback controls in editable grids. The
// fixed breakpoint cannot see that extra width, so capture the full layout
// width before the overflow-clip wrapper can hide the trailing action.
if (topbar.scrollWidth > topbar.clientWidth + 1) {
dataGridTopbarExpandedRequiredWidth.value = topbar.scrollWidth;
dataGridTopbarOverflowCompact.value = true;
}
}
function resetDataGridTopbarOverflowCompact() {
if (!dataGridTopbarOverflowCompact.value) return;
dataGridTopbarOverflowCompact.value = false;
dataGridTopbarExpandedRequiredWidth.value = 0;
if (dataGridTopbarRecheckTimer) clearTimeout(dataGridTopbarRecheckTimer);
// Wait for the label-width transition to finish before measuring the newly
// shortened action list. If it still overflows, updateDataGridTopbarWidth
// captures its new, smaller expanded width.
dataGridTopbarRecheckTimer = setTimeout(() => {
dataGridTopbarRecheckTimer = null;
updateDataGridTopbarWidth();
}, 360);
}
function clearDataGridTopbarRecheckTimer() {
if (!dataGridTopbarRecheckTimer) return;
clearTimeout(dataGridTopbarRecheckTimer);
dataGridTopbarRecheckTimer = null;
}
function observeDataGridTopbarWidth() {
dataGridTopbarResizeObserver?.disconnect();
dataGridTopbarResizeObserver = null;
dataGridTopbarMutationObserver?.disconnect();
dataGridTopbarMutationObserver = null;
clearDataGridTopbarRecheckTimer();
const topbar = dataGridTopbarRef.value;
updateDataGridTopbarWidth();
if (topbar && typeof ResizeObserver !== "undefined") {
dataGridTopbarResizeObserver = new ResizeObserver(updateDataGridTopbarWidth);
dataGridTopbarResizeObserver.observe(topbar);
}
if (topbar && typeof MutationObserver !== "undefined") {
dataGridTopbarMutationObserver = new MutationObserver(updateDataGridTopbarWidth);
dataGridTopbarMutationObserver.observe(topbar, { childList: true, characterData: true, subtree: true });
}
}
function applyPendingGridHorizontalScrollbarDrag(clientX: number) {
@@ -4843,6 +4896,21 @@ const previewToolbarCapability = computed<DataGridToolbarActionCapability>(() =>
loading: isPreviewLoading.value,
onTrigger: openSqlPreview,
}));
watch(
() => previewToolbarCapability.value.visible,
(visible, previousVisible) => {
if (previousVisible && !visible) resetDataGridTopbarOverflowCompact();
},
);
// Save/rollback disappear with saveToolbarState.showActions (committing or
// discarding all pending edits), which shortens the action list while compact
// just like the preview action disappearing does.
watch(
() => saveToolbarState.value.showActions,
(showActions, previousShowActions) => {
if (previousShowActions && !showActions) resetDataGridTopbarOverflowCompact();
},
);
const layerPreviewToolbarCapability = computed<DataGridToolbarActionCapability>(() => {
const action = previewActions.value.find((candidate) => candidate.id === "geometry-map-preview");
return {
@@ -7946,6 +8014,9 @@ function pauseCanvasGridWork() {
disconnectCellEditResizeObserver();
dataGridTopbarResizeObserver?.disconnect();
dataGridTopbarResizeObserver = null;
dataGridTopbarMutationObserver?.disconnect();
dataGridTopbarMutationObserver = null;
clearDataGridTopbarRecheckTimer();
disconnectTransposeViewportObserver();
canvasPixelRatioMediaQueryCleanup?.();
canvasPixelRatioMediaQueryCleanup = null;
@@ -8016,6 +8087,8 @@ onUnmounted(() => {
canvasRuntime.dispose();
gridScrollbarsRuntime.dispose();
dataGridTopbarResizeObserver?.disconnect();
dataGridTopbarMutationObserver?.disconnect();
clearDataGridTopbarRecheckTimer();
disconnectCellEditResizeObserver();
disconnectTransposeViewportObserver();
stopGridHorizontalScrollbarDrag();