mirror of
https://github.com/dream-num/univer.git
synced 2026-08-28 23:01:30 +08:00
fix(sheets-ui): qualify cross-sheet editor labels (#7423)
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { Nullable } from '@univerjs/core';
|
||||
import type { Nullable, Workbook } from '@univerjs/core';
|
||||
import type { KeyCode } from '@univerjs/ui';
|
||||
import type { ICellEditorState } from '../../services/editor-bridge.service';
|
||||
import {
|
||||
@@ -31,6 +31,7 @@ import {
|
||||
UniverInstanceType,
|
||||
} from '@univerjs/core';
|
||||
import { DocSelectionRenderService, IEditorService } from '@univerjs/docs-ui';
|
||||
import { quoteSheetName } from '@univerjs/engine-formula';
|
||||
import { DeviceInputEventType, IRenderManagerService } from '@univerjs/engine-render';
|
||||
import {
|
||||
ComponentManager,
|
||||
@@ -62,6 +63,7 @@ import {
|
||||
SHEET_EMBED_INTERACTION_BOUNDARY_OWNER_ATTRIBUTE,
|
||||
SHEET_EMBED_RUNTIME_FOCUS_ROLE_ATTRIBUTE,
|
||||
} from '../../services/sheet-embed-integration.service';
|
||||
import { useActiveWorksheet } from '../hook';
|
||||
import { focusSheetCellEditorElement, registerSheetCellEditorRuntimePortal } from './focus-editor';
|
||||
import { useKeyEventConfig } from './hooks';
|
||||
|
||||
@@ -229,9 +231,18 @@ export function EditorContainer() {
|
||||
);
|
||||
const FormulaEditor = componentManager.get(EMBEDDING_FORMULA_EDITOR_COMPONENT_KEY);
|
||||
const editState = useObservable(editorBridgeService.currentEditCellState$);
|
||||
const workbook = editState
|
||||
? instanceService.getUnit<Workbook>(editState.unitId, UniverInstanceType.UNIVER_SHEET) ?? null
|
||||
: null;
|
||||
const activeSheet = useActiveWorksheet(workbook);
|
||||
const darkMode = useObservable(themeService.darkMode$, themeService.darkMode);
|
||||
const [showEditCellAddress, setShowEditCellAddress] = useState(false);
|
||||
const editCellAddress = editState ? `${numberToABC(editState.column)}${editState.row + 1}` : null;
|
||||
const editSheetName = editState ? workbook?.getSheetBySheetId(editState.sheetId)?.getName() : null;
|
||||
const editCellAddress = editState
|
||||
? `${activeSheet && editSheetName && activeSheet.getSheetId() !== editState.sheetId
|
||||
? `'${quoteSheetName(editSheetName)}'!`
|
||||
: ''}${numberToABC(editState.column)}${editState.row + 1}`
|
||||
: null;
|
||||
// The editor border uses the normal selection stroke, so the address label stays visually in sync with it.
|
||||
const editorBorderColor = genNormalSelectionStyle(themeService).stroke;
|
||||
const focusCoordinator = injector.has(ISheetEmbedRuntimeFocusCoordinator)
|
||||
|
||||
@@ -99,7 +99,7 @@ class TestEditorBridgeService {
|
||||
readonly visible$ = this._visible$.asObservable();
|
||||
readonly currentEditCellState$ = new BehaviorSubject<Nullable<ICellEditorState>>({
|
||||
unitId: 'sheet-1',
|
||||
sheetId: 'sheet-1',
|
||||
sheetId: 'worksheet-1',
|
||||
row: 0,
|
||||
column: 0,
|
||||
editorUnitId: DOCS_NORMAL_EDITOR_UNIT_ID_KEY,
|
||||
@@ -142,6 +142,19 @@ function createTestBed(options: { docSelectionIsFocusing?: boolean; focusedUnitI
|
||||
const focusCoordinator = new EmbedRuntimeFocusCoordinator();
|
||||
const interactionBoundaryService = new EmbedInteractionBoundaryService();
|
||||
const editorBridgeService = new TestEditorBridgeService();
|
||||
const editSheet = { getSheetId: () => 'worksheet-1', getName: () => 'Sheet1' };
|
||||
const otherSheet = { getSheetId: () => 'worksheet-2', getName: () => 'Sheet2' };
|
||||
const activeSheet$ = new BehaviorSubject(editSheet);
|
||||
const workbook = {
|
||||
activeSheet$,
|
||||
getUnitId: () => 'sheet-1',
|
||||
getActiveSheet: () => activeSheet$.getValue(),
|
||||
getSheetBySheetId: (sheetId: string) => {
|
||||
if (sheetId === editSheet.getSheetId()) return editSheet;
|
||||
if (sheetId === otherSheet.getSheetId()) return otherSheet;
|
||||
return null;
|
||||
},
|
||||
};
|
||||
const cellEditorResizeService = {
|
||||
resizeCellEditor: vi.fn(),
|
||||
fitTextSize: vi.fn(),
|
||||
@@ -178,12 +191,16 @@ function createTestBed(options: { docSelectionIsFocusing?: boolean; focusedUnitI
|
||||
getFocusedUnit: () => options.focusedUnitId == null
|
||||
? null
|
||||
: { getUnitId: () => options.focusedUnitId },
|
||||
getUnit: (unitId: string, type?: UniverInstanceType) => (
|
||||
(type == null || type === UniverInstanceType.UNIVER_SHEET) &&
|
||||
(options.sheetUnitIds ?? ['child-sheet', 'scoped-child-sheet', 'sheet-1']).includes(unitId)
|
||||
? { getUnitId: () => unitId }
|
||||
: null
|
||||
),
|
||||
getUnit: (unitId: string, type?: UniverInstanceType) => {
|
||||
if (
|
||||
(type != null && type !== UniverInstanceType.UNIVER_SHEET) ||
|
||||
!(options.sheetUnitIds ?? ['child-sheet', 'scoped-child-sheet', 'sheet-1']).includes(unitId)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return unitId === workbook.getUnitId() ? workbook : { getUnitId: () => unitId };
|
||||
},
|
||||
} as never,
|
||||
}]);
|
||||
injector.add([IContextService, {
|
||||
@@ -215,7 +232,7 @@ function createTestBed(options: { docSelectionIsFocusing?: boolean; focusedUnitI
|
||||
injector.add([ISheetEmbedRuntimeFocusCoordinator, { useValue: focusCoordinator }]);
|
||||
injector.add([ISheetEmbedInteractionBoundaryService, { useValue: interactionBoundaryService }]);
|
||||
|
||||
return { injector, editorBridgeService, focusCoordinator, interactionBoundaryService, docSelectionRenderService, cellEditorResizeService, validViewportScrollInfo$ };
|
||||
return { injector, editorBridgeService, focusCoordinator, interactionBoundaryService, docSelectionRenderService, cellEditorResizeService, validViewportScrollInfo$, activeSheet$, otherSheet };
|
||||
}
|
||||
|
||||
function renderEditorContainer(root: Root, injector: Injector): void {
|
||||
@@ -618,6 +635,34 @@ describe('EditorContainer embed focus lease', () => {
|
||||
expect(container.querySelector('[data-u-comp="sheet-cell-editor-address"]')).toBeNull();
|
||||
});
|
||||
|
||||
it('qualifies the edited cell address after switching worksheets', async () => {
|
||||
const { injector, validViewportScrollInfo$, activeSheet$, otherSheet } = createTestBed();
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
root = createRoot(container);
|
||||
|
||||
await act(async () => {
|
||||
renderEditorContainer(root!, injector);
|
||||
await Promise.resolve();
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
validViewportScrollInfo$.next({});
|
||||
await Promise.resolve();
|
||||
});
|
||||
|
||||
const getAddress = () => container?.querySelector('[data-u-comp="sheet-cell-editor-address"]')?.textContent;
|
||||
|
||||
expect(getAddress()).toBe('A1');
|
||||
|
||||
await act(async () => {
|
||||
activeSheet$.next(otherSheet);
|
||||
await Promise.resolve();
|
||||
});
|
||||
|
||||
expect(getAddress()).toBe("'Sheet1'!A1");
|
||||
});
|
||||
|
||||
it('keeps the cell editor visible while formula range selection moves focus to the sheet canvas', async () => {
|
||||
const { injector, editorBridgeService } = createTestBed();
|
||||
container = document.createElement('div');
|
||||
|
||||
Reference in New Issue
Block a user