fix: selection style overflow when acrossing freeze line

Rework of https://github.com/ruilisi/fortune-sheet/pull/320
This commit is contained in:
zyc9012 2023-04-28 12:00:35 +08:00
parent a417df231f
commit 3c05925a23
4 changed files with 158 additions and 83 deletions

View File

@ -1,5 +1,5 @@
import _, { isPlainObject } from "lodash";
import type { Sheet as SheetType, Selection, Freezen, Range } from "../types";
import type { Sheet as SheetType, Freezen, Range } from "../types";
import { Context, getFlowdata } from "../context";
import {
getCellValue,
@ -2197,34 +2197,21 @@ export function selectAll(ctx: Context) {
normalizeSelection(ctx, ctx.luckysheet_select_save);
}
export function getSelectionStyle(
export function fixRowStyleOverflowInFreeze(
ctx: Context,
selection: Selection,
r1: number,
r2: number,
freeze: Freezen | undefined
): {
left: number | undefined;
top: number | undefined;
width: number | undefined;
height: number | undefined;
display: string;
backgroundColor?: string;
top?: number;
height?: number;
display?: string;
} {
const ret = {
left: selection.left_move,
top: selection.top_move,
width: selection.width_move,
height: selection.height_move,
display: "block",
};
if (!freeze) return ret;
if (!freeze) return {};
const ret: ReturnType<typeof fixRowStyleOverflowInFreeze> = {};
const { scrollTop } = ctx;
const { scrollLeft } = ctx;
const freezenverticaldata = freeze?.vertical?.freezenverticaldata;
const freezenhorizontaldata = freeze?.horizontal?.freezenhorizontaldata;
const obj = selection;
const freezenhorizontaldata = freeze.horizontal?.freezenhorizontaldata;
let rangeshow = true;
@ -2233,9 +2220,6 @@ export function getSelectionStyle(
const freezen_rowindex = freezenhorizontaldata[1];
const offTop = scrollTop - freezenhorizontaldata[2];
const r1 = obj.row[0];
const r2 = obj.row[1];
const row = ctx.visibledatarow[r2];
const row_pre = r1 - 1 === -1 ? 0 : ctx.visibledatarow[r1 - 1];
@ -2266,14 +2250,35 @@ export function getSelectionStyle(
}
}
if (!rangeshow) {
ret.display = "none";
}
return ret;
}
export function fixColumnStyleOverflowInFreeze(
ctx: Context,
c1: number,
c2: number,
freeze: Freezen | undefined
): {
left?: number;
width?: number;
display?: string;
} {
if (!freeze) return {};
const ret: ReturnType<typeof fixColumnStyleOverflowInFreeze> = {};
const { scrollLeft } = ctx;
const freezenverticaldata = freeze.vertical?.freezenverticaldata;
let rangeshow = true;
if (freezenverticaldata != null) {
const freezenLeft = freezenverticaldata[0];
const freezen_colindex = freezenverticaldata[1];
const offLeft = scrollLeft - freezenverticaldata[2];
const c1 = obj.column[0];
const c2 = obj.column[1];
const col = ctx.visibledatacolumn[c2];
const col_pre = c1 - 1 === -1 ? 0 : ctx.visibledatacolumn[c1 - 1];

View File

@ -8,6 +8,7 @@ import {
handleContextMenu,
isAllowEdit,
getFlowdata,
fixColumnStyleOverflowInFreeze,
} from "@fortune-sheet/core";
import _ from "lodash";
import React, {
@ -27,9 +28,10 @@ const ColumnHeader: React.FC = () => {
const [hoverLocation, setHoverLocation] = useState({
col: -1,
col_pre: -1,
col_index: -1,
});
const [selectedLocation, setSelectedLocation] = useState<
{ col: number; col_pre: number }[]
{ col: number; col_pre: number; c1: number; c2: number }[]
>([]);
const allowEditRef = useRef<boolean>(true);
@ -43,9 +45,9 @@ const ColumnHeader: React.FC = () => {
containerRef.current!.getBoundingClientRect().left +
containerRef.current!.scrollLeft;
const col_location = colLocation(x, context.visibledatacolumn);
const [col_pre, col] = col_location;
if (col_pre !== hoverLocation.col_pre || col !== hoverLocation.col) {
setHoverLocation({ col_pre, col });
const [col_pre, col, col_index] = col_location;
if (col_index !== hoverLocation.col_index) {
setHoverLocation({ col_pre, col, col_index });
}
const flowdata = getFlowdata(context);
if (!_.isNil(flowdata))
@ -58,7 +60,7 @@ const ColumnHeader: React.FC = () => {
},
]);
},
[context, hoverLocation.col, hoverLocation.col_pre]
[context, hoverLocation.col_index]
);
const onMouseDown = useCallback(
@ -82,7 +84,7 @@ const ColumnHeader: React.FC = () => {
if (context.luckysheet_cols_change_size) {
return;
}
setHoverLocation({ col: -1, col_pre: -1 });
setHoverLocation({ col: -1, col_pre: -1, col_index: -1 });
}, [context.luckysheet_cols_change_size]);
const onColSizeHandleMouseDown = useCallback(
@ -131,14 +133,15 @@ const ColumnHeader: React.FC = () => {
columnTitleMap = selectTitlesMap(columnTitleMap, c1, c2);
}
const columnTitleRange = selectTitlesRange(columnTitleMap);
const selects: { col: number; col_pre: number }[] = [];
const selects: { col: number; col_pre: number; c1: number; c2: number }[] =
[];
for (let j = 0; j < columnTitleRange.length; j += 1) {
const c1 = columnTitleRange[j][0];
const c2 = columnTitleRange[j][columnTitleRange[j].length - 1];
const col = colLocationByIndex(c2, context.visibledatacolumn)[1];
const col_pre = colLocationByIndex(c1, context.visibledatacolumn)[0];
if (_.isNumber(col) && _.isNumber(col_pre)) {
selects.push({ col, col_pre });
selects.push({ col, col_pre, c1, c2 });
}
}
setSelectedLocation(selects);
@ -170,16 +173,22 @@ const ColumnHeader: React.FC = () => {
opacity: context.luckysheet_cols_change_size ? 1 : 0,
}}
/>
{!context.luckysheet_cols_change_size &&
hoverLocation.col >= 0 &&
hoverLocation.col_pre >= 0 ? (
{!context.luckysheet_cols_change_size && hoverLocation.col_index >= 0 ? (
<div
className="fortune-col-header-hover"
style={{
left: hoverLocation.col_pre,
width: hoverLocation.col - hoverLocation.col_pre - 1,
display: "block",
}}
style={_.assign(
{
left: hoverLocation.col_pre,
width: hoverLocation.col - hoverLocation.col_pre - 1,
display: "block",
},
fixColumnStyleOverflowInFreeze(
context,
hoverLocation.col_index,
hoverLocation.col_index,
refs.globalCache.freezen?.[context.currentSheetId]
)
)}
>
{allowEditRef.current && (
<span
@ -199,16 +208,24 @@ const ColumnHeader: React.FC = () => {
)}
</div>
) : null}
{selectedLocation.map(({ col, col_pre }, i) => (
{selectedLocation.map(({ col, col_pre, c1, c2 }, i) => (
<div
className="fortune-col-header-selected"
key={i}
style={{
left: col_pre,
width: col - col_pre - 1,
display: "block",
backgroundColor: "rgba(76, 76, 76, 0.1)",
}}
style={_.assign(
{
left: col_pre,
width: col - col_pre - 1,
display: "block",
backgroundColor: "rgba(76, 76, 76, 0.1)",
},
fixColumnStyleOverflowInFreeze(
context,
c1,
c2,
refs.globalCache.freezen?.[context.currentSheetId]
)
)}
/>
))}
{/* placeholder to overflow the container, making the container scrollable */}

View File

@ -6,6 +6,7 @@ import {
handleContextMenu,
handleRowHeaderMouseDown,
handleRowSizeHandleMouseDown,
fixRowStyleOverflowInFreeze,
} from "@fortune-sheet/core";
import _ from "lodash";
import React, {
@ -24,9 +25,10 @@ const RowHeader: React.FC = () => {
const [hoverLocation, setHoverLocation] = useState({
row: -1,
row_pre: -1,
row_index: -1,
});
const [selectedLocation, setSelectedLocation] = useState<
{ row: number; row_pre: number }[]
{ row: number; row_pre: number; r1: number; r2: number }[]
>([]);
const onMouseMove = useCallback(
@ -39,9 +41,9 @@ const RowHeader: React.FC = () => {
containerRef.current!.getBoundingClientRect().top +
containerRef.current!.scrollTop;
const row_location = rowLocation(y, context.visibledatarow);
const [row_pre, row] = row_location;
const [row_pre, row, row_index] = row_location;
if (row_pre !== hoverLocation.row_pre || row !== hoverLocation.row) {
setHoverLocation({ row_pre, row });
setHoverLocation({ row_pre, row, row_index });
}
},
[
@ -73,7 +75,7 @@ const RowHeader: React.FC = () => {
if (context.luckysheet_rows_change_size) {
return;
}
setHoverLocation({ row: -1, row_pre: -1 });
setHoverLocation({ row: -1, row_pre: -1, row_index: -1 });
}, [context.luckysheet_rows_change_size]);
const onRowSizeHandleMouseDown = useCallback(
@ -120,14 +122,15 @@ const RowHeader: React.FC = () => {
rowTitleMap = selectTitlesMap(rowTitleMap, r1, r2);
}
const rowTitleRange = selectTitlesRange(rowTitleMap);
const selects: { row: number; row_pre: number }[] = [];
const selects: { row: number; row_pre: number; r1: number; r2: number }[] =
[];
for (let i = 0; i < rowTitleRange.length; i += 1) {
const r1 = rowTitleRange[i][0];
const r2 = rowTitleRange[i][rowTitleRange[i].length - 1];
const row = rowLocationByIndex(r2, context.visibledatarow)[1];
const row_pre = rowLocationByIndex(r1, context.visibledatarow)[0];
if (_.isNumber(row_pre) && _.isNumber(row)) {
selects.push({ row, row_pre });
selects.push({ row, row_pre, r1, r2 });
}
}
setSelectedLocation(selects);
@ -159,26 +162,42 @@ const RowHeader: React.FC = () => {
opacity: context.luckysheet_rows_change_size ? 1 : 0,
}}
/>
{hoverLocation.row >= 0 && hoverLocation.row_pre >= 0 ? (
{!context.luckysheet_rows_change_size && hoverLocation.row_index >= 0 ? (
<div
className="fortune-row-header-hover"
style={{
top: hoverLocation.row_pre,
height: hoverLocation.row - hoverLocation.row_pre - 1,
display: "block",
}}
style={_.assign(
{
top: hoverLocation.row_pre,
height: hoverLocation.row - hoverLocation.row_pre - 1,
display: "block",
},
fixRowStyleOverflowInFreeze(
context,
hoverLocation.row_index,
hoverLocation.row_index,
refs.globalCache.freezen?.[context.currentSheetId]
)
)}
/>
) : null}
{selectedLocation.map(({ row, row_pre }, i) => (
{selectedLocation.map(({ row, row_pre, r1, r2 }, i) => (
<div
className="fortune-row-header-selected"
key={i}
style={{
top: row_pre,
height: row - row_pre - 1,
display: "block",
backgroundColor: "rgba(76, 76, 76, 0.1)",
}}
style={_.assign(
{
top: row_pre,
height: row - row_pre - 1,
display: "block",
backgroundColor: "rgba(76, 76, 76, 0.1)",
},
fixRowStyleOverflowInFreeze(
context,
r1,
r2,
refs.globalCache.freezen?.[context.currentSheetId]
)
)}
/>
))}
{/* placeholder to overflow the container, making the container scrollable */}

View File

@ -16,7 +16,6 @@ import {
handleOverlayMouseMove,
handleOverlayMouseUp,
selectAll,
getSelectionStyle,
handleOverlayTouchEnd,
handleOverlayTouchMove,
handleOverlayTouchStart,
@ -29,6 +28,8 @@ import {
onCellsMoveStart,
insertRowCol,
getSheetIndex,
fixRowStyleOverflowInFreeze,
fixColumnStyleOverflowInFreeze,
} from "@fortune-sheet/core";
import _ from "lodash";
import WorkbookContext, { SetContextOptions } from "../../context";
@ -482,13 +483,30 @@ const SheetOverlay: React.FC = () => {
className="luckysheet-cell-selected-focus"
style={
(context.luckysheet_select_save?.length ?? 0) > 0
? {
display: "block",
left: _.last(context.luckysheet_select_save)?.left,
width: _.last(context.luckysheet_select_save)?.width,
top: _.last(context.luckysheet_select_save)?.top,
height: _.last(context.luckysheet_select_save)?.height,
}
? (() => {
const selection = _.last(context.luckysheet_select_save)!;
return _.assign(
{
left: selection.left,
top: selection.top,
width: selection.width,
height: selection.height,
display: "block",
},
fixRowStyleOverflowInFreeze(
context,
selection.row_focus || 0,
selection.row_focus || 0,
refs.globalCache.freezen?.[context.currentSheetId]
),
fixColumnStyleOverflowInFreeze(
context,
selection.column_focus || 0,
selection.column_focus || 0,
refs.globalCache.freezen?.[context.currentSheetId]
)
);
})()
: {}
}
onMouseDown={(e) => e.preventDefault()}
@ -543,10 +561,26 @@ const SheetOverlay: React.FC = () => {
key={index}
id="luckysheet-cell-selected"
className="luckysheet-cell-selected"
style={getSelectionStyle(
context,
selection,
refs.globalCache.freezen?.[context.currentSheetId]
style={_.assign(
{
left: selection.left_move,
top: selection.top_move,
width: selection.width_move,
height: selection.height_move,
display: "block",
},
fixRowStyleOverflowInFreeze(
context,
selection.row[0],
selection.row[1],
refs.globalCache.freezen?.[context.currentSheetId]
),
fixColumnStyleOverflowInFreeze(
context,
selection.column[0],
selection.column[1],
refs.globalCache.freezen?.[context.currentSheetId]
)
)}
onMouseDown={(e) => {
e.stopPropagation();