FIX: Select range in worksheet when the name is selected if possible

This commit is contained in:
Nicolás Hatcher
2025-11-13 22:13:02 +01:00
committed by Nicolás Hatcher Andrés
parent 50941cb6ef
commit 3db094c956
3 changed files with 111 additions and 94 deletions

View File

@@ -30,24 +30,22 @@ interface NamedRangesProps {
newScope: number | null, newScope: number | null,
newFormula: string, newFormula: string,
) => void; ) => void;
newDefinedName: ( newDefinedName: (name: string, scope: number | null, formula: string) => void;
name: string,
scope: number | null,
formula: string,
) => void;
deleteDefinedName: (name: string, scope: number | null) => void; deleteDefinedName: (name: string, scope: number | null) => void;
selectedArea: () => string; getSelectedArea: () => string;
onNameSelected: (name: string) => void;
} }
function NamedRanges({ function NamedRanges({
title, title,
onClose, onClose,
definedNameList = [], definedNameList,
worksheets = [], worksheets,
updateDefinedName, updateDefinedName,
newDefinedName, newDefinedName,
deleteDefinedName, deleteDefinedName,
selectedArea, getSelectedArea,
onNameSelected,
}: NamedRangesProps) { }: NamedRangesProps) {
const [editingDefinedName, setEditingDefinedName] = const [editingDefinedName, setEditingDefinedName] =
useState<DefinedName | null>(null); useState<DefinedName | null>(null);
@@ -87,7 +85,7 @@ function NamedRanges({
return { formulaError: `${e}` }; return { formulaError: `${e}` };
} }
} else { } else {
if (!editingDefinedName || !updateDefinedName) return {}; if (!editingDefinedName) return {};
const scope_index = worksheets.findIndex((s) => s.name === scope); const scope_index = worksheets.findIndex((s) => s.name === scope);
const newScope = scope_index >= 0 ? scope_index : null; const newScope = scope_index >= 0 ? scope_index : null;
@@ -121,8 +119,8 @@ function NamedRanges({
? worksheets[editingDefinedName.scope]?.name || "[unknown]" ? worksheets[editingDefinedName.scope]?.name || "[unknown]"
: "[Global]"; : "[Global]";
formula = editingDefinedName.formula; formula = editingDefinedName.formula;
} else if (isCreatingNew && selectedArea) { } else if (isCreatingNew && getSelectedArea) {
formula = selectedArea(); formula = getSelectedArea();
} }
const headerTitle = isCreatingNew const headerTitle = isCreatingNew
@@ -147,60 +145,7 @@ function NamedRanges({
</IconButtonWrapper> </IconButtonWrapper>
</Tooltip> </Tooltip>
<EditHeaderTitle>{headerTitle}</EditHeaderTitle> <EditHeaderTitle>{headerTitle}</EditHeaderTitle>
{onClose && (
<Tooltip
title={t("right_drawer.close")}
slotProps={{
popper: {
modifiers: [
{
name: "offset",
options: {
offset: [0, -8],
},
},
],
},
}}
>
<IconButtonWrapper
onClick={onClose}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
onClose();
}
}}
aria-label={t("right_drawer.close")}
tabIndex={0}
>
<X />
</IconButtonWrapper>
</Tooltip>
)}
</EditHeader>
<Content>
<EditNamedRange
worksheets={worksheets}
name={name}
scope={scopeName}
formula={formula}
onSave={handleSave}
onCancel={handleCancel}
definedNameList={definedNameList}
editingDefinedName={editingDefinedName}
/>
</Content>
</Container>
);
}
const currentSelectedArea = selectedArea ? selectedArea() : null;
return (
<Container>
{onClose && (
<Header>
<HeaderTitle>{title}</HeaderTitle>
<Tooltip <Tooltip
title={t("right_drawer.close")} title={t("right_drawer.close")}
slotProps={{ slotProps={{
@@ -229,8 +174,58 @@ function NamedRanges({
<X /> <X />
</IconButtonWrapper> </IconButtonWrapper>
</Tooltip> </Tooltip>
</Header> </EditHeader>
)} <Content>
<EditNamedRange
worksheets={worksheets}
name={name}
scope={scopeName}
formula={formula}
onSave={handleSave}
onCancel={handleCancel}
definedNameList={definedNameList}
editingDefinedName={editingDefinedName}
/>
</Content>
</Container>
);
}
const currentSelectedArea = getSelectedArea();
return (
<Container>
<Header>
<HeaderTitle>{title}</HeaderTitle>
<Tooltip
title={t("right_drawer.close")}
slotProps={{
popper: {
modifiers: [
{
name: "offset",
options: {
offset: [0, -8],
},
},
],
},
}}
>
<IconButtonWrapper
onClick={onClose}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
onClose();
}
}}
aria-label={t("right_drawer.close")}
tabIndex={0}
>
<X />
</IconButtonWrapper>
</Tooltip>
</Header>
<Content> <Content>
{definedNameList.length === 0 ? ( {definedNameList.length === 0 ? (
<EmptyStateMessage> <EmptyStateMessage>
@@ -257,11 +252,11 @@ function NamedRanges({
key={`${definedName.name}-${definedName.scope}`} key={`${definedName.name}-${definedName.scope}`}
tabIndex={0} tabIndex={0}
$isSelected={isSelected} $isSelected={isSelected}
onClick={() => handleListItemClick(definedName)} onClick={() => onNameSelected(definedName.formula)}
onKeyDown={(e) => { onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") { if (e.key === "Enter" || e.key === " ") {
e.preventDefault(); e.preventDefault();
handleListItemClick(definedName); onNameSelected(definedName.formula);
} }
}} }}
> >
@@ -508,22 +503,22 @@ const EditHeaderTitle = styled("div")({
}); });
const IconButtonWrapper = styled("div")` const IconButtonWrapper = styled("div")`
&:hover { &:hover {
background-color: ${theme.palette.grey["50"]}; background-color: ${theme.palette.grey["50"]};
} }
display: flex; display: flex;
border-radius: 4px; border-radius: 4px;
height: 24px; height: 24px;
width: 24px; width: 24px;
cursor: pointer; cursor: pointer;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
svg { svg {
width: 16px; width: 16px;
height: 16px; height: 16px;
stroke-width: 1.5; stroke-width: 1.5;
} }
`; `;
const EmptyStateMessage = styled("div")` const EmptyStateMessage = styled("div")`
display: flex; display: flex;

View File

@@ -28,7 +28,8 @@ interface RightDrawerProps {
) => void; ) => void;
newDefinedName: (name: string, scope: number | null, formula: string) => void; newDefinedName: (name: string, scope: number | null, formula: string) => void;
deleteDefinedName: (name: string, scope: number | null) => void; deleteDefinedName: (name: string, scope: number | null) => void;
selectedArea: () => string; getSelectedArea: () => string;
onNameSelected: (name: string) => void;
} }
const RightDrawer = ({ const RightDrawer = ({
@@ -42,7 +43,8 @@ const RightDrawer = ({
updateDefinedName, updateDefinedName,
newDefinedName, newDefinedName,
deleteDefinedName, deleteDefinedName,
selectedArea, getSelectedArea,
onNameSelected,
}: RightDrawerProps) => { }: RightDrawerProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const [drawerWidth, setDrawerWidth] = useState(width); const [drawerWidth, setDrawerWidth] = useState(width);
@@ -108,7 +110,8 @@ const RightDrawer = ({
updateDefinedName={updateDefinedName} updateDefinedName={updateDefinedName}
newDefinedName={newDefinedName} newDefinedName={newDefinedName}
deleteDefinedName={deleteDefinedName} deleteDefinedName={deleteDefinedName}
selectedArea={selectedArea} getSelectedArea={getSelectedArea}
onNameSelected={onNameSelected}
/> />
</DrawerContent> </DrawerContent>
</DrawerContainer> </DrawerContainer>

View File

@@ -1,8 +1,9 @@
import type { import {
BorderOptions, type BorderOptions,
ClipboardCell, type ClipboardCell,
Model, getTokens,
WorksheetProperties, type Model,
type WorksheetProperties,
} from "@ironcalc/wasm"; } from "@ironcalc/wasm";
import { styled } from "@mui/material/styles"; import { styled } from "@mui/material/styles";
import { t } from "i18next"; import { t } from "i18next";
@@ -12,6 +13,7 @@ import {
getNewClipboardId, getNewClipboardId,
} from "../clipboard"; } from "../clipboard";
import { TOOLBAR_HEIGHT } from "../constants"; import { TOOLBAR_HEIGHT } from "../constants";
import { tokenIsRangeType } from "../Editor/util";
import FormulaBar from "../FormulaBar/FormulaBar"; import FormulaBar from "../FormulaBar/FormulaBar";
import RightDrawer, { DEFAULT_DRAWER_WIDTH } from "../RightDrawer/RightDrawer"; import RightDrawer, { DEFAULT_DRAWER_WIDTH } from "../RightDrawer/RightDrawer";
import SheetTabBar from "../SheetTabBar"; import SheetTabBar from "../SheetTabBar";
@@ -768,11 +770,28 @@ const Workbook = (props: { model: Model; workbookState: WorkbookState }) => {
model.deleteDefinedName(name, scope); model.deleteDefinedName(name, scope);
setRedrawId((id) => id + 1); setRedrawId((id) => id + 1);
}} }}
selectedArea={() => { getSelectedArea={() => {
const worksheetNames = worksheets.map((s) => s.name); const worksheetNames = worksheets.map((s) => s.name);
const selectedView = model.getSelectedView(); const selectedView = model.getSelectedView();
return getFullRangeToString(selectedView, worksheetNames); return getFullRangeToString(selectedView, worksheetNames);
}} }}
onNameSelected={(formula) => {
const tokens = getTokens(formula);
const { token } = tokens[0];
if (tokenIsRangeType(token)) {
const sheetName = worksheets[model.getSelectedSheet()].name;
const {
sheet: refSheet,
left: { row: rowStart, column: columnStart },
right: { row: rowEnd, column: columnEnd },
} = token.Range;
if (refSheet !== null && refSheet === sheetName) {
model.setSelectedCell(rowStart, columnStart);
model.setSelectedRange(rowStart, columnStart, rowEnd, columnEnd);
}
}
setRedrawId((id) => id + 1);
}}
/> />
</Container> </Container>
); );