Feat/open input not focus (#811)
* Fixed click outside * Finished * Fixed tests
This commit is contained in:
@ -1,14 +1,14 @@
|
|||||||
import { ReactNode, useRef } from 'react';
|
import { ReactNode } from 'react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { Key } from 'ts-key-enum';
|
import { Key } from 'ts-key-enum';
|
||||||
|
|
||||||
import { DropdownMenu } from '@/ui/dropdown/components/DropdownMenu';
|
|
||||||
import { useListenClickOutsideArrayOfRef } from '@/ui/hooks/useListenClickOutsideArrayOfRef';
|
|
||||||
import { useScopedHotkeys } from '@/ui/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/hotkey/hooks/useScopedHotkeys';
|
||||||
import { IconChevronDown } from '@/ui/icon/index';
|
import { IconChevronDown } from '@/ui/icon/index';
|
||||||
|
|
||||||
import { FiltersHotkeyScope } from '../types/FiltersHotkeyScope';
|
import { FiltersHotkeyScope } from '../types/FiltersHotkeyScope';
|
||||||
|
|
||||||
|
import { DropdownMenuContainer } from './DropdownMenuContainer';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
label: string;
|
label: string;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
@ -50,12 +50,6 @@ const StyledDropdownButton = styled.div<StyledDropdownButtonProps>`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const StyledDropdownMenuContainer = styled.ul`
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 14px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledDropdownTopOption = styled.li`
|
const StyledDropdownTopOption = styled.li`
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
color: ${({ theme }) => theme.font.color.primary};
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -104,12 +98,6 @@ function DropdownButton({
|
|||||||
onIsUnfoldedChange?.(false);
|
onIsUnfoldedChange?.(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const dropdownRef = useRef(null);
|
|
||||||
useListenClickOutsideArrayOfRef({
|
|
||||||
refs: [dropdownRef],
|
|
||||||
callback: onOutsideClick,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledDropdownButtonContainer>
|
<StyledDropdownButtonContainer>
|
||||||
<StyledDropdownButton
|
<StyledDropdownButton
|
||||||
@ -121,9 +109,9 @@ function DropdownButton({
|
|||||||
{label}
|
{label}
|
||||||
</StyledDropdownButton>
|
</StyledDropdownButton>
|
||||||
{isUnfolded && (
|
{isUnfolded && (
|
||||||
<StyledDropdownMenuContainer>
|
<DropdownMenuContainer onClose={onOutsideClick}>
|
||||||
<DropdownMenu ref={dropdownRef}>{children}</DropdownMenu>
|
{children}
|
||||||
</StyledDropdownMenuContainer>
|
</DropdownMenuContainer>
|
||||||
)}
|
)}
|
||||||
</StyledDropdownButtonContainer>
|
</StyledDropdownButtonContainer>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -0,0 +1,34 @@
|
|||||||
|
import { useRef } from 'react';
|
||||||
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
import { DropdownMenu } from '../../dropdown/components/DropdownMenu';
|
||||||
|
import { useListenClickOutsideArrayOfRef } from '../../hooks/useListenClickOutsideArrayOfRef';
|
||||||
|
|
||||||
|
export const StyledDropdownMenuContainer = styled.ul`
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 14px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export function DropdownMenuContainer({
|
||||||
|
children,
|
||||||
|
onClose,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
onClose?: () => void;
|
||||||
|
}) {
|
||||||
|
const dropdownRef = useRef(null);
|
||||||
|
|
||||||
|
useListenClickOutsideArrayOfRef({
|
||||||
|
refs: [dropdownRef],
|
||||||
|
callback: () => {
|
||||||
|
onClose?.();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledDropdownMenuContainer>
|
||||||
|
<DropdownMenu ref={dropdownRef}>{children}</DropdownMenu>
|
||||||
|
</StyledDropdownMenuContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -28,12 +28,12 @@ test('useListenClickOutsideArrayOfRef hook works in dom mode', async () => {
|
|||||||
const inside2 = getByText('Inside 2');
|
const inside2 = getByText('Inside 2');
|
||||||
const outside = getByText('Outside');
|
const outside = getByText('Outside');
|
||||||
|
|
||||||
fireEvent.mouseUp(inside);
|
fireEvent.click(inside);
|
||||||
expect(onOutsideClick).toHaveBeenCalledTimes(0);
|
expect(onOutsideClick).toHaveBeenCalledTimes(0);
|
||||||
|
|
||||||
fireEvent.mouseUp(inside2);
|
fireEvent.click(inside2);
|
||||||
expect(onOutsideClick).toHaveBeenCalledTimes(0);
|
expect(onOutsideClick).toHaveBeenCalledTimes(0);
|
||||||
|
|
||||||
fireEvent.mouseUp(outside);
|
fireEvent.click(outside);
|
||||||
expect(onOutsideClick).toHaveBeenCalledTimes(1);
|
expect(onOutsideClick).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
|
|
||||||
import { isDefined } from '~/utils/isDefined';
|
|
||||||
|
|
||||||
export enum ClickOutsideMode {
|
export enum ClickOutsideMode {
|
||||||
absolute = 'absolute',
|
absolute = 'absolute',
|
||||||
dom = 'dom',
|
dom = 'dom',
|
||||||
@ -13,7 +11,7 @@ export function useListenClickOutsideArrayOfRef<T extends Element>({
|
|||||||
mode = ClickOutsideMode.dom,
|
mode = ClickOutsideMode.dom,
|
||||||
}: {
|
}: {
|
||||||
refs: Array<React.RefObject<T>>;
|
refs: Array<React.RefObject<T>>;
|
||||||
callback: (event?: MouseEvent | TouchEvent) => void;
|
callback: (event: MouseEvent | TouchEvent) => void;
|
||||||
mode?: ClickOutsideMode;
|
mode?: ClickOutsideMode;
|
||||||
}) {
|
}) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -59,16 +57,18 @@ export function useListenClickOutsideArrayOfRef<T extends Element>({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasAtLeastOneRefDefined = refs.some((ref) => isDefined(ref.current));
|
document.addEventListener('click', handleClickOutside, { capture: true });
|
||||||
|
document.addEventListener('touchend', handleClickOutside, {
|
||||||
if (hasAtLeastOneRefDefined) {
|
capture: true,
|
||||||
document.addEventListener('mouseup', handleClickOutside);
|
});
|
||||||
document.addEventListener('touchend', handleClickOutside);
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener('mouseup', handleClickOutside);
|
document.removeEventListener('click', handleClickOutside, {
|
||||||
document.removeEventListener('touchend', handleClickOutside);
|
capture: true,
|
||||||
|
});
|
||||||
|
document.removeEventListener('touchend', handleClickOutside, {
|
||||||
|
capture: true,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}, [refs, callback, mode]);
|
}, [refs, callback, mode]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { HotkeyScope } from '@/ui/hotkey/types/HotkeyScope';
|
|||||||
|
|
||||||
import { useCurrentCellEditMode } from '../hooks/useCurrentCellEditMode';
|
import { useCurrentCellEditMode } from '../hooks/useCurrentCellEditMode';
|
||||||
import { useIsSoftFocusOnCurrentCell } from '../hooks/useIsSoftFocusOnCurrentCell';
|
import { useIsSoftFocusOnCurrentCell } from '../hooks/useIsSoftFocusOnCurrentCell';
|
||||||
|
import { useRegisterEditableCell } from '../hooks/useRegisterEditableCell';
|
||||||
|
|
||||||
import { EditableCellDisplayMode } from './EditableCellDisplayMode';
|
import { EditableCellDisplayMode } from './EditableCellDisplayMode';
|
||||||
import { EditableCellEditMode } from './EditableCellEditMode';
|
import { EditableCellEditMode } from './EditableCellEditMode';
|
||||||
@ -48,6 +49,8 @@ export function EditableCell({
|
|||||||
|
|
||||||
const hasSoftFocus = useIsSoftFocusOnCurrentCell();
|
const hasSoftFocus = useIsSoftFocusOnCurrentCell();
|
||||||
|
|
||||||
|
useRegisterEditableCell(editHotkeyScope);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CellBaseContainer>
|
<CellBaseContainer>
|
||||||
{isCurrentCellInEditMode ? (
|
{isCurrentCellInEditMode ? (
|
||||||
@ -62,7 +65,7 @@ export function EditableCell({
|
|||||||
{editModeContent}
|
{editModeContent}
|
||||||
</EditableCellEditMode>
|
</EditableCellEditMode>
|
||||||
) : hasSoftFocus ? (
|
) : hasSoftFocus ? (
|
||||||
<EditableCellSoftFocusMode editHotkeyScope={editHotkeyScope}>
|
<EditableCellSoftFocusMode>
|
||||||
{nonEditModeContent}
|
{nonEditModeContent}
|
||||||
</EditableCellSoftFocusMode>
|
</EditableCellSoftFocusMode>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@ -40,6 +40,11 @@ export function EditableCellDisplayContainer({
|
|||||||
}: React.PropsWithChildren<Props>) {
|
}: React.PropsWithChildren<Props>) {
|
||||||
return (
|
return (
|
||||||
<EditableCellDisplayModeOuterContainer
|
<EditableCellDisplayModeOuterContainer
|
||||||
|
data-testid={
|
||||||
|
softFocus
|
||||||
|
? 'editable-cell-soft-focus-mode'
|
||||||
|
: 'editable-cell-display-mode'
|
||||||
|
}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
softFocus={softFocus}
|
softFocus={softFocus}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { useEditableCell } from '../hooks/useEditableCell';
|
||||||
import { useSetSoftFocusOnCurrentCell } from '../hooks/useSetSoftFocusOnCurrentCell';
|
import { useSetSoftFocusOnCurrentCell } from '../hooks/useSetSoftFocusOnCurrentCell';
|
||||||
|
|
||||||
import { EditableCellDisplayContainer } from './EditableCellContainer';
|
import { EditableCellDisplayContainer } from './EditableCellContainer';
|
||||||
@ -7,8 +8,11 @@ export function EditableCellDisplayMode({
|
|||||||
}: React.PropsWithChildren<unknown>) {
|
}: React.PropsWithChildren<unknown>) {
|
||||||
const setSoftFocusOnCurrentCell = useSetSoftFocusOnCurrentCell();
|
const setSoftFocusOnCurrentCell = useSetSoftFocusOnCurrentCell();
|
||||||
|
|
||||||
|
const { openEditableCell } = useEditableCell();
|
||||||
|
|
||||||
function handleClick() {
|
function handleClick() {
|
||||||
setSoftFocusOnCurrentCell();
|
setSoftFocusOnCurrentCell();
|
||||||
|
openEditableCell();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { PropsWithChildren } from 'react';
|
import { PropsWithChildren } from 'react';
|
||||||
|
|
||||||
import { useScopedHotkeys } from '@/ui/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/hotkey/hooks/useScopedHotkeys';
|
||||||
import { HotkeyScope } from '@/ui/hotkey/types/HotkeyScope';
|
|
||||||
import { isNonTextWritingKey } from '@/ui/hotkey/utils/isNonTextWritingKey';
|
import { isNonTextWritingKey } from '@/ui/hotkey/utils/isNonTextWritingKey';
|
||||||
|
|
||||||
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
||||||
@ -9,22 +8,13 @@ import { useEditableCell } from '../hooks/useEditableCell';
|
|||||||
|
|
||||||
import { EditableCellDisplayContainer } from './EditableCellContainer';
|
import { EditableCellDisplayContainer } from './EditableCellContainer';
|
||||||
|
|
||||||
type OwnProps = PropsWithChildren<{
|
type OwnProps = PropsWithChildren<unknown>;
|
||||||
editHotkeyScope?: HotkeyScope;
|
|
||||||
}>;
|
|
||||||
|
|
||||||
export function EditableCellSoftFocusMode({
|
export function EditableCellSoftFocusMode({ children }: OwnProps) {
|
||||||
children,
|
|
||||||
editHotkeyScope,
|
|
||||||
}: OwnProps) {
|
|
||||||
const { openEditableCell } = useEditableCell();
|
const { openEditableCell } = useEditableCell();
|
||||||
|
|
||||||
function openEditMode() {
|
function openEditMode() {
|
||||||
openEditableCell(
|
openEditableCell();
|
||||||
editHotkeyScope ?? {
|
|
||||||
scope: TableHotkeyScope.CellEditMode,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
useScopedHotkeys(
|
useScopedHotkeys(
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { expect } from '@storybook/jest';
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, within } from '@storybook/testing-library';
|
import { userEvent, within } from '@storybook/testing-library';
|
||||||
|
|
||||||
@ -28,9 +29,18 @@ export const SoftFocusMode: Story = {
|
|||||||
...DisplayMode,
|
...DisplayMode,
|
||||||
play: async ({ canvasElement, step }) => {
|
play: async ({ canvasElement, step }) => {
|
||||||
const canvas = within(canvasElement);
|
const canvas = within(canvasElement);
|
||||||
|
|
||||||
await step('Click once', () =>
|
await step('Click once', () =>
|
||||||
userEvent.click(canvas.getByText('Content')),
|
userEvent.click(canvas.getByText('Content')),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await step('Escape', () => {
|
||||||
|
userEvent.keyboard('{esc}');
|
||||||
|
});
|
||||||
|
|
||||||
|
await step('Has soft focus mode', () => {
|
||||||
|
expect(canvas.getByTestId('editable-cell-soft-focus-mode')).toBeDefined();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -38,9 +48,15 @@ export const EditMode: Story = {
|
|||||||
...DisplayMode,
|
...DisplayMode,
|
||||||
play: async ({ canvasElement, step }) => {
|
play: async ({ canvasElement, step }) => {
|
||||||
const canvas = within(canvasElement);
|
const canvas = within(canvasElement);
|
||||||
|
|
||||||
const click = async () => userEvent.click(canvas.getByText('Content'));
|
const click = async () => userEvent.click(canvas.getByText('Content'));
|
||||||
|
|
||||||
await step('Click once', click);
|
await step('Click once', click);
|
||||||
await step('Click twice', click);
|
|
||||||
|
await step('Has edit mode', () => {
|
||||||
|
expect(
|
||||||
|
canvas.getByTestId('editable-cell-edit-mode-container'),
|
||||||
|
).toBeDefined();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -3,12 +3,20 @@ import { useRecoilCallback } from 'recoil';
|
|||||||
import { useSetHotkeyScope } from '@/ui/hotkey/hooks/useSetHotkeyScope';
|
import { useSetHotkeyScope } from '@/ui/hotkey/hooks/useSetHotkeyScope';
|
||||||
import { HotkeyScope } from '@/ui/hotkey/types/HotkeyScope';
|
import { HotkeyScope } from '@/ui/hotkey/types/HotkeyScope';
|
||||||
|
|
||||||
|
import { useContextScopeId } from '../../../recoil-scope/hooks/useContextScopeId';
|
||||||
|
import { getSnapshotScopedState } from '../../../recoil-scope/utils/getSnapshotScopedState';
|
||||||
import { useCloseCurrentCellInEditMode } from '../../hooks/useClearCellInEditMode';
|
import { useCloseCurrentCellInEditMode } from '../../hooks/useClearCellInEditMode';
|
||||||
|
import { CellContext } from '../../states/CellContext';
|
||||||
import { isSomeInputInEditModeState } from '../../states/isSomeInputInEditModeState';
|
import { isSomeInputInEditModeState } from '../../states/isSomeInputInEditModeState';
|
||||||
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
||||||
|
import { customCellHotkeyScopeScopedState } from '../states/customCellHotkeyScopeScopedState';
|
||||||
|
|
||||||
import { useCurrentCellEditMode } from './useCurrentCellEditMode';
|
import { useCurrentCellEditMode } from './useCurrentCellEditMode';
|
||||||
|
|
||||||
|
const DEFAULT_CELL_SCOPE: HotkeyScope = {
|
||||||
|
scope: TableHotkeyScope.CellEditMode,
|
||||||
|
};
|
||||||
|
|
||||||
export function useEditableCell() {
|
export function useEditableCell() {
|
||||||
const { setCurrentCellInEditMode } = useCurrentCellEditMode();
|
const { setCurrentCellInEditMode } = useCurrentCellEditMode();
|
||||||
|
|
||||||
@ -16,6 +24,8 @@ export function useEditableCell() {
|
|||||||
|
|
||||||
const closeCurrentCellInEditMode = useCloseCurrentCellInEditMode();
|
const closeCurrentCellInEditMode = useCloseCurrentCellInEditMode();
|
||||||
|
|
||||||
|
const cellContextId = useContextScopeId(CellContext);
|
||||||
|
|
||||||
function closeEditableCell() {
|
function closeEditableCell() {
|
||||||
closeCurrentCellInEditMode();
|
closeCurrentCellInEditMode();
|
||||||
setHotkeyScope(TableHotkeyScope.TableSoftFocus);
|
setHotkeyScope(TableHotkeyScope.TableSoftFocus);
|
||||||
@ -23,20 +33,36 @@ export function useEditableCell() {
|
|||||||
|
|
||||||
const openEditableCell = useRecoilCallback(
|
const openEditableCell = useRecoilCallback(
|
||||||
({ snapshot, set }) =>
|
({ snapshot, set }) =>
|
||||||
(HotkeyScope: HotkeyScope) => {
|
() => {
|
||||||
const isSomeInputInEditMode = snapshot
|
const isSomeInputInEditMode = snapshot
|
||||||
.getLoadable(isSomeInputInEditModeState)
|
.getLoadable(isSomeInputInEditModeState)
|
||||||
.valueOrThrow();
|
.valueOrThrow();
|
||||||
|
|
||||||
|
const customCellHotkeyScope = getSnapshotScopedState({
|
||||||
|
snapshot,
|
||||||
|
state: customCellHotkeyScopeScopedState,
|
||||||
|
contextScopeId: cellContextId,
|
||||||
|
});
|
||||||
|
|
||||||
if (!isSomeInputInEditMode) {
|
if (!isSomeInputInEditMode) {
|
||||||
set(isSomeInputInEditModeState, true);
|
set(isSomeInputInEditModeState, true);
|
||||||
|
|
||||||
setCurrentCellInEditMode();
|
setCurrentCellInEditMode();
|
||||||
|
|
||||||
setHotkeyScope(HotkeyScope.scope);
|
if (customCellHotkeyScope) {
|
||||||
|
setHotkeyScope(
|
||||||
|
customCellHotkeyScope.scope,
|
||||||
|
customCellHotkeyScope.customScopes,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
setHotkeyScope(
|
||||||
|
DEFAULT_CELL_SCOPE.scope,
|
||||||
|
DEFAULT_CELL_SCOPE.customScopes,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[setCurrentCellInEditMode, setHotkeyScope],
|
[setCurrentCellInEditMode, setHotkeyScope, cellContextId],
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -16,9 +16,12 @@ export function useRegisterCloseCellHandlers(
|
|||||||
const { isCurrentCellInEditMode } = useCurrentCellEditMode();
|
const { isCurrentCellInEditMode } = useCurrentCellEditMode();
|
||||||
useListenClickOutsideArrayOfRef({
|
useListenClickOutsideArrayOfRef({
|
||||||
refs: [wrapperRef],
|
refs: [wrapperRef],
|
||||||
callback: () => {
|
callback: (event) => {
|
||||||
if (isCurrentCellInEditMode) {
|
if (isCurrentCellInEditMode) {
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
|
||||||
onSubmit?.();
|
onSubmit?.();
|
||||||
|
|
||||||
closeEditableCell();
|
closeEditableCell();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
|
import { HotkeyScope } from '@/ui/hotkey/types/HotkeyScope';
|
||||||
|
|
||||||
|
import { useRecoilScopedState } from '../../../recoil-scope/hooks/useRecoilScopedState';
|
||||||
|
import { CellContext } from '../../states/CellContext';
|
||||||
|
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
||||||
|
import { customCellHotkeyScopeScopedState } from '../states/customCellHotkeyScopeScopedState';
|
||||||
|
|
||||||
|
const DEFAULT_CELL_SCOPE: HotkeyScope = {
|
||||||
|
scope: TableHotkeyScope.CellEditMode,
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useRegisterEditableCell(cellHotkeyScope?: HotkeyScope) {
|
||||||
|
const [, setCustomCellHotkeyScope] = useRecoilScopedState(
|
||||||
|
customCellHotkeyScopeScopedState,
|
||||||
|
CellContext,
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setCustomCellHotkeyScope(cellHotkeyScope ?? DEFAULT_CELL_SCOPE);
|
||||||
|
}, [cellHotkeyScope, setCustomCellHotkeyScope]);
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
import { atomFamily } from 'recoil';
|
||||||
|
|
||||||
|
import { HotkeyScope } from '../../../hotkey/types/HotkeyScope';
|
||||||
|
|
||||||
|
export const customCellHotkeyScopeScopedState = atomFamily<
|
||||||
|
HotkeyScope | null,
|
||||||
|
string
|
||||||
|
>({
|
||||||
|
key: 'customCellHotkeyScopeScopedState',
|
||||||
|
default: null,
|
||||||
|
});
|
||||||
@ -71,7 +71,7 @@ export const EditNote: Story = {
|
|||||||
).toBeInTheDocument();
|
).toBeInTheDocument();
|
||||||
|
|
||||||
const workspaceName = await canvas.findByText('Twenty');
|
const workspaceName = await canvas.findByText('Twenty');
|
||||||
await fireEvent.mouseUp(workspaceName);
|
await fireEvent.click(workspaceName);
|
||||||
|
|
||||||
expect(await canvas.queryByDisplayValue('My very first note')).toBeNull();
|
expect(await canvas.queryByDisplayValue('My very first note')).toBeNull();
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,13 @@ export const InteractWithManyRows: Story = {
|
|||||||
play: async ({ canvasElement }) => {
|
play: async ({ canvasElement }) => {
|
||||||
const canvas = within(canvasElement);
|
const canvas = within(canvasElement);
|
||||||
|
|
||||||
let firstRowEmailCell = await canvas.findByText(mockedPeopleData[0].email);
|
const firstRowEmailCell = await canvas.findByText(
|
||||||
|
mockedPeopleData[0].email,
|
||||||
|
);
|
||||||
|
|
||||||
|
const secondRowEmailCell = await canvas.findByText(
|
||||||
|
mockedPeopleData[1].email,
|
||||||
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
canvas.queryByTestId('editable-cell-edit-mode-container'),
|
canvas.queryByTestId('editable-cell-edit-mode-container'),
|
||||||
@ -38,29 +44,19 @@ export const InteractWithManyRows: Story = {
|
|||||||
|
|
||||||
await userEvent.click(firstRowEmailCell);
|
await userEvent.click(firstRowEmailCell);
|
||||||
|
|
||||||
firstRowEmailCell = await canvas.findByText(mockedPeopleData[0].email);
|
|
||||||
await userEvent.click(firstRowEmailCell);
|
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
canvas.queryByTestId('editable-cell-edit-mode-container'),
|
canvas.queryByTestId('editable-cell-edit-mode-container'),
|
||||||
).toBeInTheDocument();
|
).toBeInTheDocument();
|
||||||
|
|
||||||
const secondRowEmailCell = await canvas.findByText(
|
|
||||||
mockedPeopleData[1].email,
|
|
||||||
);
|
|
||||||
await userEvent.click(secondRowEmailCell);
|
await userEvent.click(secondRowEmailCell);
|
||||||
|
|
||||||
await sleep(25);
|
await sleep(25);
|
||||||
|
|
||||||
const secondRowEmailCellFocused = await canvas.findByText(
|
|
||||||
mockedPeopleData[1].email,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
canvas.queryByTestId('editable-cell-edit-mode-container'),
|
canvas.queryByTestId('editable-cell-edit-mode-container'),
|
||||||
).toBeNull();
|
).toBeNull();
|
||||||
|
|
||||||
await userEvent.click(secondRowEmailCellFocused);
|
await userEvent.click(secondRowEmailCell);
|
||||||
|
|
||||||
await sleep(25);
|
await sleep(25);
|
||||||
|
|
||||||
@ -190,39 +186,44 @@ const editRelationMocks = (
|
|||||||
|
|
||||||
export const EditRelation: Story = {
|
export const EditRelation: Story = {
|
||||||
render: getRenderWrapperForPage(<People />, '/people'),
|
render: getRenderWrapperForPage(<People />, '/people'),
|
||||||
play: async ({ canvasElement }) => {
|
play: async ({ canvasElement, step }) => {
|
||||||
const canvas = within(canvasElement);
|
const canvas = within(canvasElement);
|
||||||
|
|
||||||
let secondRowCompanyCell = await canvas.findByText(
|
await step('Click on second row company cell', async () => {
|
||||||
mockedPeopleData[1].company.name,
|
const secondRowCompanyCell = await canvas.findByText(
|
||||||
);
|
mockedPeopleData[1].company.name,
|
||||||
await sleep(25);
|
);
|
||||||
|
|
||||||
await userEvent.click(secondRowCompanyCell);
|
await userEvent.click(secondRowCompanyCell);
|
||||||
|
|
||||||
secondRowCompanyCell = await canvas.findByText(
|
|
||||||
mockedPeopleData[1].company.name,
|
|
||||||
);
|
|
||||||
await sleep(25);
|
|
||||||
|
|
||||||
await userEvent.click(secondRowCompanyCell);
|
|
||||||
|
|
||||||
const relationInput = await canvas.findByPlaceholderText('Search');
|
|
||||||
|
|
||||||
await userEvent.type(relationInput, 'Air', {
|
|
||||||
delay: 200,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const airbnbChip = await canvas.findByText('Airbnb', {
|
await step('Type "Air" in relation picker', async () => {
|
||||||
selector: 'div',
|
const relationInput = await canvas.findByPlaceholderText('Search');
|
||||||
|
|
||||||
|
await userEvent.type(relationInput, 'Air', {
|
||||||
|
delay: 200,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
await userEvent.click(airbnbChip);
|
await step('Select "Airbnb"', async () => {
|
||||||
|
const airbnbChip = await canvas.findByText('Airbnb', {
|
||||||
|
selector: 'div',
|
||||||
|
});
|
||||||
|
|
||||||
const otherCell = await canvas.findByText('Janice Dane');
|
await userEvent.click(airbnbChip);
|
||||||
await userEvent.click(otherCell);
|
});
|
||||||
|
|
||||||
await canvas.findByText('Airbnb');
|
await step(
|
||||||
|
'Click on last row company cell to exit relation picker',
|
||||||
|
async () => {
|
||||||
|
const otherCell = await canvas.findByText('Janice Dane');
|
||||||
|
await userEvent.click(otherCell);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
await step('Check if Airbnb is in second row company cell', async () => {
|
||||||
|
await canvas.findByText('Airbnb');
|
||||||
|
});
|
||||||
},
|
},
|
||||||
parameters: {
|
parameters: {
|
||||||
actions: {},
|
actions: {},
|
||||||
|
|||||||
Reference in New Issue
Block a user