Skip to content

Commit

Permalink
feat: define move direction on enter (#1966)
Browse files Browse the repository at this point in the history
* test: add tests

* feat: define move direction on enter

* docs: add option description

* fix: fix lint error

* fix: remove unnecessary comment
  • Loading branch information
jajugoguma committed Sep 15, 2023
1 parent 1037d31 commit 99c79d9
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 17 deletions.
68 changes: 66 additions & 2 deletions packages/toast-ui.grid/cypress/integration/keyMap.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { clipboardType } from '../helper/util';
import { assertFocusedCell, assertSelectedRange } from '../helper/assert';
import { GridOptions } from '@t/index';

// unable to test clipboard
// https://github.com/cypress-io/cypress/issues/2386
Expand All @@ -13,7 +14,7 @@ function assertEditFinished() {
cy.getByCls('content-text').should('not.exist');
}

function createGrid() {
function createGrid(options?: Partial<GridOptions>) {
const data = [
{ name: 'Han', value: 1 },
{ name: 'Kim', value: 2 },
Expand All @@ -26,7 +27,7 @@ function createGrid() {
{ name: 'value', editor: 'text' },
];

cy.createGrid({ data, columns });
cy.createGrid({ data, columns, ...options });
}

describe('editor', () => {
Expand Down Expand Up @@ -132,6 +133,69 @@ describe('Focus', () => {
});
});

describe('Move focus on enter', () => {
it('should not move the focus on enter(default)', () => {
createGrid();
cy.getCellByIdx(0, 0).click();

clipboardType('{enter}');

assertFocusedCell('name', 0);
});

it('should move the focus to next cell on enter(nextCell)', () => {
createGrid({ moveDirectionOnEnter: 'nextCell' });
cy.getCellByIdx(0, 0).click();

clipboardType('{enter}');

assertFocusedCell('value', 0);

clipboardType('{enter}');

assertFocusedCell('name', 1);
});

it('should move the focus to next cell on enter(prevCell)', () => {
createGrid({ moveDirectionOnEnter: 'prevCell' });
cy.getCellByIdx(1, 1).click();

clipboardType('{enter}');

assertFocusedCell('name', 1);

clipboardType('{enter}');

assertFocusedCell('value', 0);
});

it('should move the focus to next cell on enter(down)', () => {
createGrid({ moveDirectionOnEnter: 'down' });
cy.getCellByIdx(0, 0).click();

clipboardType('{enter}');

assertFocusedCell('name', 1);

clipboardType('{enter}');

assertFocusedCell('name', 2);
});

it('should move the focus to next cell on enter(up)', () => {
createGrid({ moveDirectionOnEnter: 'up' });
cy.getCellByIdx(2, 0).click();

clipboardType('{enter}');

assertFocusedCell('name', 1);

clipboardType('{enter}');

assertFocusedCell('name', 0);
});
});

describe('Selection', () => {
it('select by pressing shift + arrowKey', () => {
createGrid();
Expand Down
14 changes: 9 additions & 5 deletions packages/toast-ui.grid/src/dispatch/keyboard.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Store } from '@t/store';
import { SelectionRange } from '@t/store/selection';
import { KeyboardEventCommandType, TabCommandType } from '../helper/keyboard';
import { EnterCommandType, KeyboardEventCommandType, TabCommandType } from '../helper/keyboard';
import { getNextCellIndex, getRemoveRange, getNextCellIndexWithRowSpan } from '../query/keyboard';
import { changeFocus, startEditing } from './focus';
import { changeSelectionRange } from './selection';
Expand Down Expand Up @@ -54,13 +54,17 @@ export function editFocus(store: Store, command: KeyboardEventCommandType) {

if (command === 'currentCell') {
startEditing(store, rowKey, columnName);
} else if (command === 'nextCell' || command === 'prevCell') {
// move prevCell or nextCell by tab keyMap
moveTabFocus(store, command);
} else if (
command === 'nextCell' ||
command === 'prevCell' ||
command === 'up' ||
command === 'down'
) {
moveTabAndEnterFocus(store, command);
}
}

export function moveTabFocus(store: Store, command: TabCommandType) {
export function moveTabAndEnterFocus(store: Store, command: TabCommandType | EnterCommandType) {
const { focus, data, column, id } = store;
const { visibleColumnsWithRowHeader } = column;
const { rowKey, columnName, rowIndex, totalColumnIndex: columnIndex } = focus;
Expand Down
1 change: 1 addition & 0 deletions packages/toast-ui.grid/src/grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ if ((module as any).hot) {
* @param {function} [options.onGridBeforeDestroy] - The function that will be called before destroying the grid.
* @param {boolean} [options.draggable] - Whether to enable to drag the row for changing the order of rows.
* @param {Array} [options.contextMenu] - Option array for the context menu.
* @param {string} [options.moveDirectionOnEnter] - Define moving focus direction on Enter. If not set, the focus does not move.
*/
export default class Grid implements TuiGrid {
el: HTMLElement;
Expand Down
4 changes: 4 additions & 0 deletions packages/toast-ui.grid/src/helper/keyboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ export type KeyStrokeCommandType = keyof typeof keyStrokeCommandMap;
export type KeyboardEventType = keyof typeof keyboardEventTypeMap;
export type KeyboardEventCommandType = keyof typeof keyboardEventCommandMap;
export type TabCommandType = 'nextCell' | 'prevCell';
export type EnterCommandType =
| TabCommandType
| keyof Pick<typeof keyboardEventCommandMap, 'up' | 'down'>;

/**
* Returns the keyStroke string
Expand Down Expand Up @@ -130,6 +133,7 @@ export function keyEventGenerate(ev: KeyboardEvent) {

return commandInfo
? {
keyStroke,
type: commandInfo[0],
command: commandInfo[1],
}
Expand Down
2 changes: 2 additions & 0 deletions packages/toast-ui.grid/src/store/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export function createStore(id: number, options: OptGrid): Store {
disabled = false,
draggable = false,
contextMenu: createMenuGroups,
moveDirectionOnEnter,
} = options;
const { frozenBorderWidth } = columnOptions;
const { height: summaryHeight, position: summaryPosition } = summaryOptions;
Expand Down Expand Up @@ -112,6 +113,7 @@ export function createStore(id: number, options: OptGrid): Store {
editingEvent,
tabMode,
id,
moveDirectionOnEnter,
});
const summary = createSummary({ column, data, summary: summaryOptions });
const selection = createSelection({
Expand Down
4 changes: 4 additions & 0 deletions packages/toast-ui.grid/src/store/focus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { observable } from '../helper/observable';
import { someProp, findPropIndex, isNull } from '../helper/common';
import { isRowSpanEnabled, getVerticalPosWithRowSpan, getRowSpanByRowKey } from '../query/rowSpan';
import { findIndexByRowKey, isClientPagination } from '../query/data';
import { EnterCommandType } from '../helper/keyboard';

interface FocusOption {
data: Data;
Expand All @@ -18,6 +19,7 @@ interface FocusOption {
editingEvent: EditingEvent;
tabMode: TabMode;
id: number;
moveDirectionOnEnter?: EnterCommandType;
}

export function create({
Expand All @@ -29,6 +31,7 @@ export function create({
editingEvent,
tabMode,
id,
moveDirectionOnEnter,
}: FocusOption) {
return observable({
rowKey: null,
Expand All @@ -40,6 +43,7 @@ export function create({
navigating: false,
forcedDestroyEditing: false,
tabMode,
moveDirectionOnEnter,

get side() {
if (this.columnName === null) {
Expand Down
18 changes: 14 additions & 4 deletions packages/toast-ui.grid/src/view/clipboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ import {
setClipboardSelection,
WindowWithClipboard,
} from '../helper/dom';
import { KeyboardEventCommandType, KeyboardEventType, keyEventGenerate } from '../helper/keyboard';
import {
EnterCommandType,
KeyboardEventCommandType,
KeyboardEventType,
keyEventGenerate,
} from '../helper/keyboard';
import { isEdge, isMobile } from '../helper/browser';
import { getText } from '../query/clipboard';
import { convertTextToData } from '../helper/common';
Expand All @@ -24,6 +29,7 @@ interface StoreProps {
columnName: string | null;
filtering: boolean;
eventBus: EventBus;
moveDirectionOnEnter?: EnterCommandType;
}

type Props = StoreProps & DispatchProps;
Expand Down Expand Up @@ -162,7 +168,7 @@ class ClipboardComp extends Component<Props> {
return;
}

const { type, command } = keyEventGenerate(ev);
const { keyStroke, type, command } = keyEventGenerate(ev);

if (!type) {
return;
Expand All @@ -175,7 +181,7 @@ class ClipboardComp extends Component<Props> {
}

if (!(type === 'clipboard' && command === 'paste')) {
const { rowKey, columnName } = this.props;
const { rowKey, columnName, moveDirectionOnEnter } = this.props;
const gridEvent = new GridEvent({ keyboardEvent: ev, rowKey, columnName });
/**
* Occurs when key down event is triggered.
Expand All @@ -188,7 +194,10 @@ class ClipboardComp extends Component<Props> {
this.props.eventBus.trigger('keydown', gridEvent);

if (!gridEvent.isStopped()) {
this.dispatchKeyboardEvent(type, command);
this.dispatchKeyboardEvent(
type,
keyStroke === 'enter' && moveDirectionOnEnter ? moveDirectionOnEnter : command
);
}
}
};
Expand Down Expand Up @@ -264,4 +273,5 @@ export const Clipboard = connect<StoreProps>(({ focus, filterLayerState, id }) =
editing: !!focus.editingAddress,
filtering: !!filterLayerState.activeColumnAddress,
eventBus: getEventBus(id),
moveDirectionOnEnter: focus.moveDirectionOnEnter,
}))(ClipboardComp);
20 changes: 14 additions & 6 deletions packages/toast-ui.grid/src/view/editingLayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { CellEditor } from '@t/editor';
import { connect } from './hoc';
import { DispatchProps } from '../dispatch/create';
import { cls, getTextWidth } from '../helper/dom';
import { getKeyStrokeString, TabCommandType } from '../helper/keyboard';
import { EnterCommandType, getKeyStrokeString, TabCommandType } from '../helper/keyboard';
import { findProp, getLongestText, isNil, isNull, isUndefined } from '../helper/common';
import { getInstance } from '../instance';
import Grid from '../grid';
Expand Down Expand Up @@ -40,6 +40,7 @@ interface StoreProps {
bodyWidth: number;
headerHeight: number;
leftSideWidth: number;
moveDirectionOnEnter?: EnterCommandType;
}

interface OwnProps {
Expand All @@ -57,29 +58,34 @@ export class EditingLayerComp extends Component<Props> {

private longestTextWidths: { [columnName: string]: number } = {};

private moveTabFocus(ev: KeyboardEvent, command: TabCommandType) {
private moveTabAndEnterFocus(ev: KeyboardEvent, command: TabCommandType | EnterCommandType) {
const { dispatch } = this.props;

ev.preventDefault();
dispatch('moveTabFocus', command);
dispatch('moveTabAndEnterFocus', command);
dispatch('setScrollToFocus');
}

private handleKeyDown = (ev: KeyboardEvent) => {
const { moveDirectionOnEnter } = this.props;
const keyName = getKeyStrokeString(ev);

switch (keyName) {
case 'enter':
this.saveAndFinishEditing(true);
if (isUndefined(moveDirectionOnEnter)) {
this.saveAndFinishEditing(true);
} else {
this.moveTabAndEnterFocus(ev, moveDirectionOnEnter);
}
break;
case 'esc':
this.cancelEditing();
break;
case 'tab':
this.moveTabFocus(ev, 'nextCell');
this.moveTabAndEnterFocus(ev, 'nextCell');
break;
case 'shift-tab':
this.moveTabFocus(ev, 'prevCell');
this.moveTabAndEnterFocus(ev, 'prevCell');
break;
default:
// do nothing;
Expand Down Expand Up @@ -291,6 +297,7 @@ export const EditingLayer = connect<StoreProps, OwnProps>((store, { side }) => {
columnName: focusedColumnName,
forcedDestroyEditing,
cellPosRect,
moveDirectionOnEnter,
} = focus;
const { scrollTop, scrollLeft } = viewport;
const {
Expand Down Expand Up @@ -319,5 +326,6 @@ export const EditingLayer = connect<StoreProps, OwnProps>((store, { side }) => {
bodyWidth: width - scrollYWidth,
headerHeight,
leftSideWidth: side === 'L' ? 0 : columnCoords.areaWidth.L,
moveDirectionOnEnter,
};
}, true)(EditingLayerComp);
2 changes: 2 additions & 0 deletions packages/toast-ui.grid/types/options.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { SummaryColumnContentMapOnlyFn, SummaryPosition } from './store/summary'
import { TuiGridEvent } from './event';
import { CellRendererClass, CellRendererProps, HeaderRendererClass } from './renderer';
import { CellEditorClass } from './editor';
import { EnterCommandType } from '../src/helper/keyboard';

export interface Dictionary<T> {
[index: string]: T;
Expand Down Expand Up @@ -115,6 +116,7 @@ export interface OptGrid {
onGridBeforeDestroy?: GridEventListener;
draggable?: boolean;
contextMenu?: CreateMenuGroups;
moveDirectionOnEnter?: EnterCommandType;
}

export type OptRowProp = CellValue | RecursivePartial<RowAttributes & RowSpanAttribute> | OptRow[];
Expand Down
2 changes: 2 additions & 0 deletions packages/toast-ui.grid/types/store/focus.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { RowKey } from './data';
import { EnterCommandType } from '../../src/helper/keyboard';

export type EditingEvent = 'click' | 'dblclick';
export type TabMode = 'move' | 'moveAndEdit';
Expand All @@ -24,6 +25,7 @@ export interface Focus {
prevRowKey: RowKey | null;
prevColumnName: string | null;
forcedDestroyEditing: boolean;
moveDirectionOnEnter?: EnterCommandType;
readonly side: Side | null;
readonly columnIndex: number | null;
readonly totalColumnIndex: number | null;
Expand Down

0 comments on commit 99c79d9

Please sign in to comment.