Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion packages/core/src/locale/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11094,6 +11094,11 @@ export default {
confirmCellEditShortcut: "Confirm cell edit and move down: Enter.",
moveRightShortcut: "Move right: Tab.",
moveLeftShortcut: "Move left: Shift, Tab.",
contextMenuShortcut: "Open context menu: Control or Meta key, Shift, M.",
rowContextMenuShortcut:
"Open row header context menu: Control or Meta key, Shift, R.",
columnContextMenuShortcut:
"Open column header context menu: Control or Meta key, Shift, L.",
shortcuts: "Keyboard Shortcuts",
},
currencyDetail: [
Expand Down Expand Up @@ -11419,7 +11424,7 @@ export default {
sortBy: "Sort by",
addOthers: "Add another sort column",
close: "close",
confirm: "sort",
confirm: "Sort",

columnOperation: "Column",
secondaryTitle: "then by",
Expand Down
7 changes: 6 additions & 1 deletion packages/core/src/locale/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11069,6 +11069,11 @@ export default {
"Confirmar edición de celda y mover hacia abajo: Enter.",
moveRightShortcut: "Mover a la derecha: Tab.",
moveLeftShortcut: "Mover a la izquierda: Shift, Tab.",
contextMenuShortcut: "Abrir menú contextual: Control o Meta, Shift, M.",
rowContextMenuShortcut:
"Abrir menú contextual de fila: Control o Meta, Shift, R.",
columnContextMenuShortcut:
"Abrir menú contextual de columna: Control o Meta, Shift, L.",
shortcuts: "Atajos de teclado",
},
currencyDetail: {
Expand Down Expand Up @@ -11385,7 +11390,7 @@ export default {
sortBy: "Ordenar por",
addOthers: "Añadir otra columna de ordenación",
close: "cerrar",
confirm: "ordenar",
confirm: "Ordenar",

columnOperation: "Columna",
secondaryTitle: "y después por",
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/locale/hi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11099,6 +11099,11 @@ export default {
"Confirmar edición de celda y mover hacia abajo: Enter.",
moveRightShortcut: "Mover a la derecha: Tab.",
moveLeftShortcut: "Mover a la izquierda: Shift, Tab.",
contextMenuShortcut: "Open context menu: Control or Meta, Shift, M.",
rowContextMenuShortcut:
"Open row header context menu: Control or Meta, Shift, R.",
columnContextMenuShortcut:
"Open column header context menu: Control or Meta, Shift, L.",
shortcuts: "कुंजीपटल अल्प मार्ग",
},
currencyDetail: [
Expand Down
6 changes: 6 additions & 0 deletions packages/core/src/locale/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12975,6 +12975,12 @@ export default {
"Подтвердить редактирование ячейки и перейти вниз: Enter.",
moveRightShortcut: "Перейти вправо: Tab.",
moveLeftShortcut: "Перейти влево: Shift, Tab.",
contextMenuShortcut:
"Открыть контекстное меню: Control или Meta, Shift, M.",
rowContextMenuShortcut:
"Открыть контекстное меню заголовка строки: Control или Meta, Shift, R.",
columnContextMenuShortcut:
"Открыть контекстное меню заголовка столбца: Control или Meta, Shift, L.",
shortcuts: "Горячие клавиши",
},
currencyDetail: [
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/locale/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11075,6 +11075,11 @@ export default {
confirmCellEditShortcut: "确认编辑并向下移动: Enter。",
moveRightShortcut: "向右移动: Tab。",
moveLeftShortcut: "向左移动: Shift, Tab。",
contextMenuShortcut: "打开上下文菜单: Control 或 Meta 键, Shift, M。",
rowContextMenuShortcut:
"打开行标题上下文菜单: Control 或 Meta 键, Shift, R。",
columnContextMenuShortcut:
"打开列标题上下文菜单: Control 或 Meta 键, Shift, L。",
shortcuts: "键盘快捷键",
},
currencyDetail: [
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/locale/zh_tw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11042,6 +11042,11 @@ export default {
confirmCellEditShortcut: "確認編輯並向下移動: Enter。",
moveRightShortcut: "向右移動: Tab。",
moveLeftShortcut: "向左移動: Shift, Tab。",
contextMenuShortcut: "開啟內容選單: Control 或 Meta 鍵, Shift, M。",
rowContextMenuShortcut:
"開啟列標題內容選單: Control 或 Meta 鍵, Shift, R。",
columnContextMenuShortcut:
"開啟欄標題內容選單: Control 或 Meta 鍵, Shift, L。",
shortcuts: "鍵盤快速鍵",
},
currencyDetail: {
Expand Down
13 changes: 13 additions & 0 deletions packages/react/src/components/ContextMenu/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,19 @@ const Menu: React.FC<Props> = ({
ref={containerRef}
className="luckysheet-cols-menuitem luckysheet-mousedown-cancel"
onClick={(e) => onClick?.(e, containerRef.current!)}
onKeyDown={(e) => {
if (e.key === "Enter") {
if (e.repeat) return;
e.preventDefault();
e.stopPropagation();
containerRef.current?.dispatchEvent(
new MouseEvent("click", {
bubbles: true,
cancelable: true,
})
);
}
}}
onMouseLeave={(e) => onMouseLeave?.(e, containerRef.current!)}
onMouseEnter={(e) => onMouseEnter?.(e, containerRef.current!)}
tabIndex={0}
Expand Down
8 changes: 8 additions & 0 deletions packages/react/src/components/CustomSort/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
margin: 0 0 16px;
}

.fortune-sort-title-range {
margin: 0 4px;
}

.fortune-sort-modal > div {
margin-bottom: 10px;
}
Expand All @@ -17,6 +21,10 @@
white-space: nowrap;
}

.fortune-sort-by-select {
margin-left: 8px;
}

.fortune-sort-button {
margin-top: 10px;
margin-bottom: 25px;
Expand Down
44 changes: 30 additions & 14 deletions packages/react/src/components/CustomSort/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,28 @@ import { useDialog } from "../../hooks/useDialog";
type RadioChangeEvent = React.ChangeEvent<HTMLInputElement>;

const CustomSort: React.FC<{}> = () => {
const [rangeColChar, setRangeColChar] = useState<String[]>([]);
const [rangeColChar, setRangeColChar] = useState<string[]>([]);
const [ascOrDesc, setAscOrDesc] = useState(true);
const { context, setContext } = useContext(WorkbookContext);
const [selectedValue, setSelectedValue] = useState<string>("0");
const [isTitleChange, setIstitleChange] = useState(false);
const { sort } = locale(context);
const { hideDialog } = useDialog();

const handleSortConfirm = useCallback(() => {
setContext((draftCtx: Context) => {
sortSelection(draftCtx, ascOrDesc, parseInt(selectedValue, 10));
draftCtx.contextMenu = {};
});
hideDialog();
}, [ascOrDesc, hideDialog, selectedValue, setContext]);

const col_start = context.luckysheet_select_save![0].column[0];
const col_end = context.luckysheet_select_save![0].column[1];
const row_start = context.luckysheet_select_save![0].row[0];
const row_end = context.luckysheet_select_save![0].row[1];
const startCell = `${indexToColumnChar(col_start)}${row_start + 1}`;
const endCell = `${indexToColumnChar(col_end)}${row_end + 1}`;

const sheetIndex = getSheetIndex(context, context.currentSheetId) as number;

Expand Down Expand Up @@ -87,13 +97,11 @@ const CustomSort: React.FC<{}> = () => {
return (
<div className="fortune-sort">
<div className="fortune-sort-title">
<span>
<span id="fortune-sort-title">
<span>{sort.sortRangeTitle}</span>
{indexToColumnChar(col_start)}
{row_start + 1}
<span className="fortune-sort-title-range">{startCell}</span>
<span>{sort.sortRangeTitleTo}</span>
{indexToColumnChar(col_end)}
{row_end + 1}
<span className="fortune-sort-title-range">{endCell}</span>
</span>
</div>

Expand All @@ -113,8 +121,15 @@ const CustomSort: React.FC<{}> = () => {
<tbody>
<tr>
<td style={{ width: "190px" }}>
{sort.sortBy}
<select name="sort_0" onChange={handleSelectChange}>
<label htmlFor="fortune-sort-by-select">
{sort.sortBy}
</label>
<select
id="fortune-sort-by-select"
name="sort_0"
className="fortune-sort-by-select"
onChange={handleSelectChange}
>
{rangeColChar.map((col, index) => {
return (
<option value={index} key={index}>
Expand Down Expand Up @@ -155,14 +170,15 @@ const CustomSort: React.FC<{}> = () => {
<div className="fortune-sort-button">
<div
className="button-basic button-primary"
onClick={() => {
setContext((draftCtx: Context) => {
sortSelection(draftCtx, ascOrDesc, parseInt(selectedValue, 10));
draftCtx.contextMenu = {};
});
hideDialog();
onClick={handleSortConfirm}
onKeyDown={(e) => {
if (e.key === "Enter") {
e.preventDefault();
handleSortConfirm();
}
}}
tabIndex={0}
role="button"
>
{sort.confirm}
</div>
Expand Down
79 changes: 77 additions & 2 deletions packages/react/src/components/Dialog/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { locale } from "@fortune-sheet/core";
import React, { useContext } from "react";
import React, { useContext, useEffect, useRef } from "react";
import WorkbookContext from "../../context";
import SVGIcon from "../SVGIcon";
import "./index.css";
Expand All @@ -23,13 +23,85 @@ const Dialog: React.FC<Props> = ({
}) => {
const { context } = useContext(WorkbookContext);
const { button } = locale(context);
const dialogRef = useRef<HTMLDivElement>(null);
const previousActiveElement = useRef<HTMLElement | null>(null);

useEffect(() => {
previousActiveElement.current =
document.activeElement as HTMLElement | null;
const dialog = dialogRef.current;
if (!dialog) return undefined;
const trapFocus = (e: KeyboardEvent) => {
if (e.key === "Escape") {
e.preventDefault();
onCancel?.();
return;
}
if (e.key !== "Tab") return;
const focusable = Array.from(
dialog.querySelectorAll<HTMLElement>(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
)
).filter((el) => !el.hasAttribute("disabled"));
if (focusable.length === 0) {
e.preventDefault();
dialog.focus();
return;
}
const first = focusable[0];
const last = focusable[focusable.length - 1];
const current = document.activeElement as HTMLElement | null;
if (e.shiftKey && current === first) {
e.preventDefault();
last.focus();
} else if (!e.shiftKey && current === last) {
e.preventDefault();
first.focus();
}
};
const focusable = dialog.querySelectorAll<HTMLElement>(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
if (focusable.length > 0) {
focusable[0].focus();
} else {
dialog.focus();
}
dialog.addEventListener("keydown", trapFocus);
return () => {
dialog.removeEventListener("keydown", trapFocus);
if (previousActiveElement.current?.isConnected) {
previousActiveElement.current.focus();
}
};
}, [onCancel]);

const activateOnEnter = (e: React.KeyboardEvent<HTMLDivElement>) => {
if (e.key === "Enter") {
e.preventDefault();
e.currentTarget.click();
}
};

return (
<div className="fortune-dialog" style={containerStyle}>
<div
className="fortune-dialog"
style={containerStyle}
ref={dialogRef}
role="dialog"
aria-modal="true"
aria-labelledby="fortune-sort-title"
aria-label="Dialog"
tabIndex={-1}
>
<div className="fortune-modal-dialog-header">
<div
className="fortune-modal-dialog-icon-close"
onClick={onCancel}
onKeyDown={activateOnEnter}
tabIndex={0}
role="button"
aria-label={button.close}
>
<SVGIcon name="close" style={{ padding: 7, cursor: "pointer" }} />
</div>
Expand All @@ -43,6 +115,7 @@ const Dialog: React.FC<Props> = ({
<div
className="fortune-message-box-button button-default"
onClick={onOk}
onKeyDown={activateOnEnter}
tabIndex={0}
>
{button.confirm}
Expand All @@ -52,13 +125,15 @@ const Dialog: React.FC<Props> = ({
<div
className="fortune-message-box-button button-primary"
onClick={onOk}
onKeyDown={activateOnEnter}
tabIndex={0}
>
{button.confirm}
</div>
<div
className="fortune-message-box-button button-default"
onClick={onCancel}
onKeyDown={activateOnEnter}
tabIndex={0}
>
{button.cancel}
Expand Down
Loading
Loading