Optimize table loading (#866)
* wip * wip * Ok * Deleted unused code * Fixed lint * Minor fixes * Minor fixes * Minor Fixes * Minor merge fixes * Ok * Fix storybook tests * Removed console.log * Fix login * asd * Fixed storybook * Added await * Fixed await * Added sleep for failing test * Fix sleep * Fix test * Fix tests --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -3,9 +3,10 @@ import styled from '@emotion/styled';
|
||||
|
||||
import { HotkeyScope } from '@/ui/hotkey/types/HotkeyScope';
|
||||
|
||||
import { CellHotkeyScopeContext } from '../../states/CellHotkeyScopeContext';
|
||||
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
||||
import { useCurrentCellEditMode } from '../hooks/useCurrentCellEditMode';
|
||||
import { useIsSoftFocusOnCurrentCell } from '../hooks/useIsSoftFocusOnCurrentCell';
|
||||
import { useRegisterEditableCell } from '../hooks/useRegisterEditableCell';
|
||||
|
||||
import { EditableCellDisplayMode } from './EditableCellDisplayMode';
|
||||
import { EditableCellEditMode } from './EditableCellEditMode';
|
||||
@ -34,6 +35,10 @@ type OwnProps = {
|
||||
onCancel?: () => void;
|
||||
};
|
||||
|
||||
const DEFAULT_CELL_SCOPE: HotkeyScope = {
|
||||
scope: TableHotkeyScope.CellEditMode,
|
||||
};
|
||||
|
||||
export function EditableCell({
|
||||
editModeHorizontalAlign = 'left',
|
||||
editModeVerticalPosition = 'over',
|
||||
@ -42,35 +47,35 @@ export function EditableCell({
|
||||
editHotkeyScope,
|
||||
transparent = false,
|
||||
maxContentWidth,
|
||||
onSubmit,
|
||||
onCancel,
|
||||
}: OwnProps) {
|
||||
const { isCurrentCellInEditMode } = useCurrentCellEditMode();
|
||||
|
||||
const hasSoftFocus = useIsSoftFocusOnCurrentCell();
|
||||
|
||||
useRegisterEditableCell(editHotkeyScope);
|
||||
|
||||
return (
|
||||
<CellBaseContainer>
|
||||
{isCurrentCellInEditMode ? (
|
||||
<EditableCellEditMode
|
||||
maxContentWidth={maxContentWidth}
|
||||
transparent={transparent}
|
||||
editModeHorizontalAlign={editModeHorizontalAlign}
|
||||
editModeVerticalPosition={editModeVerticalPosition}
|
||||
onSubmit={onSubmit}
|
||||
onCancel={onCancel}
|
||||
>
|
||||
{editModeContent}
|
||||
</EditableCellEditMode>
|
||||
) : hasSoftFocus ? (
|
||||
<EditableCellSoftFocusMode>
|
||||
{nonEditModeContent}
|
||||
</EditableCellSoftFocusMode>
|
||||
) : (
|
||||
<EditableCellDisplayMode>{nonEditModeContent}</EditableCellDisplayMode>
|
||||
)}
|
||||
</CellBaseContainer>
|
||||
<CellHotkeyScopeContext.Provider
|
||||
value={editHotkeyScope ?? DEFAULT_CELL_SCOPE}
|
||||
>
|
||||
<CellBaseContainer>
|
||||
{isCurrentCellInEditMode ? (
|
||||
<EditableCellEditMode
|
||||
maxContentWidth={maxContentWidth}
|
||||
transparent={transparent}
|
||||
editModeHorizontalAlign={editModeHorizontalAlign}
|
||||
editModeVerticalPosition={editModeVerticalPosition}
|
||||
>
|
||||
{editModeContent}
|
||||
</EditableCellEditMode>
|
||||
) : hasSoftFocus ? (
|
||||
<EditableCellSoftFocusMode>
|
||||
{nonEditModeContent}
|
||||
</EditableCellSoftFocusMode>
|
||||
) : (
|
||||
<EditableCellDisplayMode>
|
||||
{nonEditModeContent}
|
||||
</EditableCellDisplayMode>
|
||||
)}
|
||||
</CellBaseContainer>
|
||||
</CellHotkeyScopeContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
import { ReactElement, useRef } from 'react';
|
||||
import { ReactElement } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { overlayBackground } from '@/ui/themes/effects';
|
||||
|
||||
import { useRegisterCloseCellHandlers } from '../hooks/useRegisterCloseCellHandlers';
|
||||
|
||||
export const EditableCellEditModeContainer = styled.div<OwnProps>`
|
||||
align-items: center;
|
||||
border: ${({ transparent, theme }) =>
|
||||
@ -36,30 +34,21 @@ type OwnProps = {
|
||||
maxContentWidth?: number;
|
||||
editModeHorizontalAlign?: 'left' | 'right';
|
||||
editModeVerticalPosition?: 'over' | 'below';
|
||||
onOutsideClick?: () => void;
|
||||
onCancel?: () => void;
|
||||
onSubmit?: () => void;
|
||||
initialValue?: string;
|
||||
};
|
||||
|
||||
export function EditableCellEditMode({
|
||||
editModeHorizontalAlign,
|
||||
editModeVerticalPosition,
|
||||
children,
|
||||
onCancel,
|
||||
onSubmit,
|
||||
transparent = false,
|
||||
maxContentWidth,
|
||||
}: OwnProps) {
|
||||
const wrapperRef = useRef(null);
|
||||
|
||||
useRegisterCloseCellHandlers(wrapperRef, onSubmit, onCancel);
|
||||
|
||||
return (
|
||||
<EditableCellEditModeContainer
|
||||
maxContentWidth={maxContentWidth}
|
||||
transparent={transparent}
|
||||
data-testid="editable-cell-edit-mode-container"
|
||||
ref={wrapperRef}
|
||||
editModeHorizontalAlign={editModeHorizontalAlign}
|
||||
editModeVerticalPosition={editModeVerticalPosition}
|
||||
>
|
||||
|
||||
@ -4,6 +4,7 @@ import { userEvent, within } from '@storybook/testing-library';
|
||||
|
||||
import { CellPositionDecorator } from '~/testing/decorators/CellPositionDecorator';
|
||||
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||
import { sleep } from '~/testing/sleep';
|
||||
|
||||
import { EditableCellText } from '../../types/EditableCellText';
|
||||
|
||||
@ -28,13 +29,12 @@ export const SoftFocusMode: Story = {
|
||||
play: async ({ canvasElement, step }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
await step('Click once', () =>
|
||||
userEvent.click(canvas.getByText('Content')),
|
||||
);
|
||||
const content = await canvas.findByText('Content');
|
||||
|
||||
await step('Escape', () => {
|
||||
userEvent.keyboard('{esc}');
|
||||
});
|
||||
await userEvent.click(content);
|
||||
await userEvent.keyboard('{esc}');
|
||||
|
||||
await sleep(10);
|
||||
|
||||
await step('Has soft focus mode', () => {
|
||||
expect(canvas.getByTestId('editable-cell-soft-focus-mode')).toBeDefined();
|
||||
@ -47,7 +47,7 @@ export const EditMode: Story = {
|
||||
play: async ({ canvasElement, step }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const click = async () => userEvent.click(canvas.getByText('Content'));
|
||||
const click = () => userEvent.click(canvas.getByText('Content'));
|
||||
|
||||
await step('Click once', click);
|
||||
|
||||
|
||||
@ -1,23 +1,12 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useContext, useMemo } from 'react';
|
||||
|
||||
import { useRecoilScopedState } from '@/ui/recoil-scope/hooks/useRecoilScopedState';
|
||||
|
||||
import { CellContext } from '../../states/CellContext';
|
||||
import { currentColumnNumberScopedState } from '../../states/currentColumnNumberScopedState';
|
||||
import { currentRowNumberScopedState } from '../../states/currentRowNumberScopedState';
|
||||
import { RowContext } from '../../states/RowContext';
|
||||
import { ColumnIndexContext } from '../../states/ColumnIndexContext';
|
||||
import { RowIndexContext } from '../../states/RowIndexContext';
|
||||
import { CellPosition } from '../../types/CellPosition';
|
||||
|
||||
export function useCurrentCellPosition() {
|
||||
const [currentRowNumber] = useRecoilScopedState(
|
||||
currentRowNumberScopedState,
|
||||
RowContext,
|
||||
);
|
||||
|
||||
const [currentColumnNumber] = useRecoilScopedState(
|
||||
currentColumnNumberScopedState,
|
||||
CellContext,
|
||||
);
|
||||
const currentRowNumber = useContext(RowIndexContext);
|
||||
const currentColumnNumber = useContext(ColumnIndexContext);
|
||||
|
||||
const currentCellPosition: CellPosition = useMemo(
|
||||
() => ({
|
||||
|
||||
@ -1,15 +1,13 @@
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { useSetHotkeyScope } from '@/ui/hotkey/hooks/useSetHotkeyScope';
|
||||
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 { CellContext } from '../../states/CellContext';
|
||||
import { CellHotkeyScopeContext } from '../../states/CellHotkeyScopeContext';
|
||||
import { isSomeInputInEditModeState } from '../../states/isSomeInputInEditModeState';
|
||||
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
||||
import { customCellHotkeyScopeScopedState } from '../states/customCellHotkeyScopeScopedState';
|
||||
|
||||
import { useCurrentCellEditMode } from './useCurrentCellEditMode';
|
||||
|
||||
@ -24,7 +22,7 @@ export function useEditableCell() {
|
||||
|
||||
const closeCurrentCellInEditMode = useCloseCurrentCellInEditMode();
|
||||
|
||||
const cellContextId = useContextScopeId(CellContext);
|
||||
const customCellHotkeyScope = useContext(CellHotkeyScopeContext);
|
||||
|
||||
function closeEditableCell() {
|
||||
closeCurrentCellInEditMode();
|
||||
@ -38,12 +36,6 @@ export function useEditableCell() {
|
||||
.getLoadable(isSomeInputInEditModeState)
|
||||
.valueOrThrow();
|
||||
|
||||
const customCellHotkeyScope = getSnapshotScopedState({
|
||||
snapshot,
|
||||
state: customCellHotkeyScopeScopedState,
|
||||
contextScopeId: cellContextId,
|
||||
});
|
||||
|
||||
if (!isSomeInputInEditMode) {
|
||||
set(isSomeInputInEditModeState, true);
|
||||
|
||||
@ -62,7 +54,7 @@ export function useEditableCell() {
|
||||
}
|
||||
}
|
||||
},
|
||||
[setCurrentCellInEditMode, setHotkeyScope, cellContextId],
|
||||
[setCurrentCellInEditMode, setHotkeyScope, customCellHotkeyScope],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@ -14,6 +14,7 @@ export function useRegisterCloseCellHandlers(
|
||||
) {
|
||||
const { closeEditableCell } = useEditableCell();
|
||||
const { isCurrentCellInEditMode } = useCurrentCellEditMode();
|
||||
|
||||
useListenClickOutside({
|
||||
refs: [wrapperRef],
|
||||
callback: (event) => {
|
||||
@ -26,6 +27,7 @@ export function useRegisterCloseCellHandlers(
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const { moveRight, moveLeft, moveDown } = useMoveSoftFocus();
|
||||
|
||||
useScopedHotkeys(
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
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]);
|
||||
}
|
||||
@ -1,50 +1,29 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { useSetHotkeyScope } from '@/ui/hotkey/hooks/useSetHotkeyScope';
|
||||
import { useRecoilScopedState } from '@/ui/recoil-scope/hooks/useRecoilScopedState';
|
||||
|
||||
import { useSetSoftFocusPosition } from '../../hooks/useSetSoftFocusPosition';
|
||||
import { CellContext } from '../../states/CellContext';
|
||||
import { currentColumnNumberScopedState } from '../../states/currentColumnNumberScopedState';
|
||||
import { currentRowNumberScopedState } from '../../states/currentRowNumberScopedState';
|
||||
import { isSoftFocusActiveState } from '../../states/isSoftFocusActiveState';
|
||||
import { RowContext } from '../../states/RowContext';
|
||||
import { CellPosition } from '../../types/CellPosition';
|
||||
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
||||
|
||||
import { useCurrentCellPosition } from './useCurrentCellPosition';
|
||||
|
||||
export function useSetSoftFocusOnCurrentCell() {
|
||||
const setSoftFocusPosition = useSetSoftFocusPosition();
|
||||
|
||||
const [currentRowNumber] = useRecoilScopedState(
|
||||
currentRowNumberScopedState,
|
||||
RowContext,
|
||||
);
|
||||
|
||||
const [currentColumnNumber] = useRecoilScopedState(
|
||||
currentColumnNumberScopedState,
|
||||
CellContext,
|
||||
);
|
||||
|
||||
const currentTablePosition: CellPosition = useMemo(
|
||||
() => ({
|
||||
column: currentColumnNumber,
|
||||
row: currentRowNumber,
|
||||
}),
|
||||
[currentColumnNumber, currentRowNumber],
|
||||
);
|
||||
const currentCellPosition = useCurrentCellPosition();
|
||||
|
||||
const setHotkeyScope = useSetHotkeyScope();
|
||||
|
||||
return useRecoilCallback(
|
||||
({ set }) =>
|
||||
() => {
|
||||
setSoftFocusPosition(currentTablePosition);
|
||||
setSoftFocusPosition(currentCellPosition);
|
||||
|
||||
set(isSoftFocusActiveState, true);
|
||||
|
||||
setHotkeyScope(TableHotkeyScope.TableSoftFocus);
|
||||
},
|
||||
[setHotkeyScope, currentTablePosition, setSoftFocusPosition],
|
||||
[setHotkeyScope, currentCellPosition, setSoftFocusPosition],
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
import { atomFamily } from 'recoil';
|
||||
|
||||
import { HotkeyScope } from '../../../hotkey/types/HotkeyScope';
|
||||
|
||||
export const customCellHotkeyScopeScopedState = atomFamily<
|
||||
HotkeyScope | null,
|
||||
string
|
||||
>({
|
||||
key: 'customCellHotkeyScopeScopedState',
|
||||
default: null,
|
||||
});
|
||||
@ -1,9 +1,11 @@
|
||||
import { useRef } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { Key } from 'ts-key-enum';
|
||||
|
||||
import { useScopedHotkeys } from '@/ui/hotkey/hooks/useScopedHotkeys';
|
||||
import { InplaceInputDate } from '@/ui/inplace-input/components/InplaceInputDate';
|
||||
|
||||
import { useListenClickOutside } from '../../../hooks/useListenClickOutside';
|
||||
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
||||
import { useEditableCell } from '../hooks/useEditableCell';
|
||||
|
||||
@ -38,8 +40,21 @@ export function EditableCellDateEditMode({
|
||||
[closeEditableCell],
|
||||
);
|
||||
|
||||
const containerRef = useRef(null);
|
||||
|
||||
useListenClickOutside({
|
||||
refs: [containerRef],
|
||||
callback: (event) => {
|
||||
event.stopImmediatePropagation();
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
closeEditableCell();
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<EditableCellDateEditModeContainer>
|
||||
<EditableCellDateEditModeContainer ref={containerRef}>
|
||||
<InplaceInputDate onChange={handleDateChange} value={value} />
|
||||
</EditableCellDateEditModeContainer>
|
||||
);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ReactElement, useEffect, useState } from 'react';
|
||||
import { ReactElement } from 'react';
|
||||
|
||||
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
||||
import { CellSkeleton } from '../components/CellSkeleton';
|
||||
@ -12,8 +12,7 @@ type OwnProps = {
|
||||
firstValuePlaceholder: string;
|
||||
secondValuePlaceholder: string;
|
||||
nonEditModeContent: ReactElement;
|
||||
onChange: (firstValue: string, secondValue: string) => void;
|
||||
onSubmit?: () => void;
|
||||
onSubmit?: (firstValue: string, secondValue: string) => void;
|
||||
onCancel?: () => void;
|
||||
loading?: boolean;
|
||||
};
|
||||
@ -23,36 +22,21 @@ export function EditableCellDoubleText({
|
||||
secondValue,
|
||||
firstValuePlaceholder,
|
||||
secondValuePlaceholder,
|
||||
onChange,
|
||||
|
||||
onSubmit,
|
||||
onCancel,
|
||||
nonEditModeContent,
|
||||
loading,
|
||||
}: OwnProps) {
|
||||
const [firstInternalValue, setFirstInternalValue] = useState(firstValue);
|
||||
const [secondInternalValue, setSecondInternalValue] = useState(secondValue);
|
||||
|
||||
useEffect(() => {
|
||||
setFirstInternalValue(firstValue);
|
||||
setSecondInternalValue(secondValue);
|
||||
}, [firstValue, secondValue]);
|
||||
|
||||
function handleOnChange(firstValue: string, secondValue: string): void {
|
||||
setFirstInternalValue(firstValue);
|
||||
setSecondInternalValue(secondValue);
|
||||
onChange(firstValue, secondValue);
|
||||
}
|
||||
|
||||
return (
|
||||
<EditableCell
|
||||
editHotkeyScope={{ scope: TableHotkeyScope.CellDoubleTextInput }}
|
||||
editModeContent={
|
||||
<EditableCellDoubleTextEditMode
|
||||
firstValue={firstInternalValue}
|
||||
secondValue={secondInternalValue}
|
||||
firstValue={firstValue}
|
||||
secondValue={secondValue}
|
||||
firstValuePlaceholder={firstValuePlaceholder}
|
||||
secondValuePlaceholder={secondValuePlaceholder}
|
||||
onChange={handleOnChange}
|
||||
onSubmit={onSubmit}
|
||||
onCancel={onCancel}
|
||||
/>
|
||||
|
||||
@ -1,21 +1,22 @@
|
||||
import { ChangeEvent, useRef, useState } from 'react';
|
||||
import { ChangeEvent, useEffect, useRef, useState } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { Key } from 'ts-key-enum';
|
||||
|
||||
import { useScopedHotkeys } from '@/ui/hotkey/hooks/useScopedHotkeys';
|
||||
import { InplaceInputTextEditMode } from '@/ui/inplace-input/components/InplaceInputTextEditMode';
|
||||
import { StyledInput } from '@/ui/inplace-input/components/InplaceInputTextEditMode';
|
||||
|
||||
import { useMoveSoftFocus } from '../../hooks/useMoveSoftFocus';
|
||||
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
||||
import { useEditableCell } from '../hooks/useEditableCell';
|
||||
import { useRegisterCloseCellHandlers } from '../hooks/useRegisterCloseCellHandlers';
|
||||
|
||||
type OwnProps = {
|
||||
firstValue: string;
|
||||
secondValue: string;
|
||||
firstValuePlaceholder: string;
|
||||
secondValuePlaceholder: string;
|
||||
onChange: (firstValue: string, secondValue: string) => void;
|
||||
onSubmit?: () => void;
|
||||
onChange?: (firstValue: string, secondValue: string) => void;
|
||||
onSubmit?: (firstValue: string, secondValue: string) => void;
|
||||
onCancel?: () => void;
|
||||
};
|
||||
|
||||
@ -39,6 +40,19 @@ export function EditableCellDoubleTextEditMode({
|
||||
onSubmit,
|
||||
onCancel,
|
||||
}: OwnProps) {
|
||||
const [firstInternalValue, setFirstInternalValue] = useState(firstValue);
|
||||
const [secondInternalValue, setSecondInternalValue] = useState(secondValue);
|
||||
|
||||
useEffect(() => {
|
||||
setFirstInternalValue(firstValue);
|
||||
setSecondInternalValue(secondValue);
|
||||
}, [firstValue, secondValue]);
|
||||
|
||||
function handleOnChange(firstValue: string, secondValue: string): void {
|
||||
setFirstInternalValue(firstValue);
|
||||
setSecondInternalValue(secondValue);
|
||||
}
|
||||
|
||||
const [focusPosition, setFocusPosition] = useState<'left' | 'right'>('left');
|
||||
|
||||
const firstValueInputRef = useRef<HTMLInputElement>(null);
|
||||
@ -52,12 +66,23 @@ export function EditableCellDoubleTextEditMode({
|
||||
closeEditableCell();
|
||||
}
|
||||
|
||||
function handleCancel() {
|
||||
setFirstInternalValue(firstValue);
|
||||
setSecondInternalValue(secondValue);
|
||||
|
||||
onCancel?.();
|
||||
}
|
||||
|
||||
function handleSubmit() {
|
||||
onSubmit?.(firstInternalValue, secondInternalValue);
|
||||
}
|
||||
|
||||
useScopedHotkeys(
|
||||
Key.Enter,
|
||||
() => {
|
||||
closeCell();
|
||||
moveDown();
|
||||
onSubmit?.();
|
||||
handleSubmit();
|
||||
},
|
||||
TableHotkeyScope.CellDoubleTextInput,
|
||||
[closeCell],
|
||||
@ -66,7 +91,7 @@ export function EditableCellDoubleTextEditMode({
|
||||
useScopedHotkeys(
|
||||
Key.Escape,
|
||||
() => {
|
||||
onCancel?.();
|
||||
handleCancel();
|
||||
closeCell();
|
||||
},
|
||||
TableHotkeyScope.CellDoubleTextInput,
|
||||
@ -80,7 +105,8 @@ export function EditableCellDoubleTextEditMode({
|
||||
setFocusPosition('right');
|
||||
secondValueInputRef.current?.focus();
|
||||
} else {
|
||||
onSubmit?.();
|
||||
handleSubmit();
|
||||
|
||||
closeCell();
|
||||
moveRight();
|
||||
}
|
||||
@ -96,7 +122,7 @@ export function EditableCellDoubleTextEditMode({
|
||||
setFocusPosition('left');
|
||||
firstValueInputRef.current?.focus();
|
||||
} else {
|
||||
onSubmit?.();
|
||||
handleSubmit();
|
||||
closeCell();
|
||||
moveLeft();
|
||||
}
|
||||
@ -105,23 +131,27 @@ export function EditableCellDoubleTextEditMode({
|
||||
[closeCell, moveRight, focusPosition],
|
||||
);
|
||||
|
||||
const wrapperRef = useRef(null);
|
||||
|
||||
useRegisterCloseCellHandlers(wrapperRef, handleSubmit, handleCancel);
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
<InplaceInputTextEditMode
|
||||
<StyledContainer ref={wrapperRef}>
|
||||
<StyledInput
|
||||
autoFocus
|
||||
placeholder={firstValuePlaceholder}
|
||||
ref={firstValueInputRef}
|
||||
value={firstValue}
|
||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||
onChange(event.target.value, secondValue);
|
||||
handleOnChange(event.target.value, secondValue);
|
||||
}}
|
||||
/>
|
||||
<InplaceInputTextEditMode
|
||||
<StyledInput
|
||||
placeholder={secondValuePlaceholder}
|
||||
ref={secondValueInputRef}
|
||||
value={secondValue}
|
||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||
onChange(firstValue, event.target.value);
|
||||
handleOnChange(firstValue, event.target.value);
|
||||
}}
|
||||
/>
|
||||
</StyledContainer>
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import { ChangeEvent, useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { InplaceInputPhoneDisplayMode } from '@/ui/display/component/InplaceInputPhoneDisplayMode';
|
||||
import { InplaceInputTextEditMode } from '@/ui/inplace-input/components/InplaceInputTextEditMode';
|
||||
|
||||
@ -8,42 +6,21 @@ import { EditableCell } from '../components/EditableCell';
|
||||
type OwnProps = {
|
||||
placeholder?: string;
|
||||
value: string;
|
||||
onChange: (updated: string) => void;
|
||||
onSubmit?: () => void;
|
||||
onCancel?: () => void;
|
||||
onSubmit?: (newText: string) => void;
|
||||
};
|
||||
|
||||
export function EditableCellPhone({
|
||||
value,
|
||||
placeholder,
|
||||
onChange,
|
||||
onSubmit,
|
||||
onCancel,
|
||||
}: OwnProps) {
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const [inputValue, setInputValue] = useState(value);
|
||||
|
||||
useEffect(() => {
|
||||
setInputValue(value);
|
||||
}, [value]);
|
||||
|
||||
export function EditableCellPhone({ value, placeholder, onSubmit }: OwnProps) {
|
||||
return (
|
||||
<EditableCell
|
||||
editModeContent={
|
||||
<InplaceInputTextEditMode
|
||||
autoFocus
|
||||
placeholder={placeholder || ''}
|
||||
ref={inputRef}
|
||||
value={inputValue}
|
||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||
setInputValue(event.target.value);
|
||||
onChange(event.target.value);
|
||||
}}
|
||||
value={value}
|
||||
onSubmit={(newText) => onSubmit?.(newText)}
|
||||
/>
|
||||
}
|
||||
nonEditModeContent={<InplaceInputPhoneDisplayMode value={inputValue} />}
|
||||
onSubmit={onSubmit}
|
||||
onCancel={onCancel}
|
||||
nonEditModeContent={<InplaceInputPhoneDisplayMode value={value} />}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import { ChangeEvent, useEffect, useState } from 'react';
|
||||
|
||||
import { InplaceInputTextDisplayMode } from '@/ui/display/component/InplaceInputTextDisplayMode';
|
||||
import { InplaceInputTextEditMode } from '@/ui/inplace-input/components/InplaceInputTextEditMode';
|
||||
|
||||
@ -9,10 +7,10 @@ import { EditableCell } from '../components/EditableCell';
|
||||
type OwnProps = {
|
||||
placeholder?: string;
|
||||
value: string;
|
||||
onChange: (newValue: string) => void;
|
||||
onChange?: (newValue: string) => void;
|
||||
editModeHorizontalAlign?: 'left' | 'right';
|
||||
loading?: boolean;
|
||||
onSubmit?: () => void;
|
||||
onSubmit?: (newText: string) => void;
|
||||
onCancel?: () => void;
|
||||
};
|
||||
|
||||
@ -25,12 +23,6 @@ export function EditableCellText({
|
||||
onCancel,
|
||||
onSubmit,
|
||||
}: OwnProps) {
|
||||
const [internalValue, setInternalValue] = useState(value);
|
||||
|
||||
useEffect(() => {
|
||||
setInternalValue(value);
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<EditableCell
|
||||
editModeHorizontalAlign={editModeHorizontalAlign}
|
||||
@ -38,22 +30,15 @@ export function EditableCellText({
|
||||
<InplaceInputTextEditMode
|
||||
placeholder={placeholder || ''}
|
||||
autoFocus
|
||||
value={internalValue}
|
||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||
setInternalValue(event.target.value);
|
||||
onChange(event.target.value);
|
||||
}}
|
||||
value={value}
|
||||
onSubmit={(newText) => onSubmit?.(newText)}
|
||||
/>
|
||||
}
|
||||
onSubmit={onSubmit}
|
||||
onCancel={onCancel}
|
||||
nonEditModeContent={
|
||||
loading ? (
|
||||
<CellSkeleton />
|
||||
) : (
|
||||
<InplaceInputTextDisplayMode>
|
||||
{internalValue}
|
||||
</InplaceInputTextDisplayMode>
|
||||
<InplaceInputTextDisplayMode>{value}</InplaceInputTextDisplayMode>
|
||||
)
|
||||
}
|
||||
></EditableCell>
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import { ChangeEvent, useEffect, useState } from 'react';
|
||||
|
||||
import { InplaceInputTextEditMode } from '@/ui/inplace-input/components/InplaceInputTextEditMode';
|
||||
|
||||
import { RawLink } from '../../../link/components/RawLink';
|
||||
@ -9,53 +7,40 @@ import { EditableCell } from '../components/EditableCell';
|
||||
type OwnProps = {
|
||||
placeholder?: string;
|
||||
url: string;
|
||||
onChange: (newURL: string) => void;
|
||||
onChange?: (newURL: string) => void;
|
||||
editModeHorizontalAlign?: 'left' | 'right';
|
||||
loading?: boolean;
|
||||
onSubmit?: () => void;
|
||||
onSubmit?: (newURL: string) => void;
|
||||
onCancel?: () => void;
|
||||
};
|
||||
|
||||
export function EditableCellURL({
|
||||
url,
|
||||
placeholder,
|
||||
onChange,
|
||||
editModeHorizontalAlign,
|
||||
loading,
|
||||
onCancel,
|
||||
onSubmit,
|
||||
}: OwnProps) {
|
||||
const [internalValue, setInternalValue] = useState(url);
|
||||
|
||||
useEffect(() => {
|
||||
setInternalValue(url);
|
||||
}, [url]);
|
||||
|
||||
return (
|
||||
<EditableCell
|
||||
editModeHorizontalAlign={editModeHorizontalAlign}
|
||||
editModeContent={
|
||||
<InplaceInputTextEditMode
|
||||
placeholder={placeholder || ''}
|
||||
placeholder={placeholder}
|
||||
autoFocus
|
||||
value={internalValue}
|
||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||
setInternalValue(event.target.value);
|
||||
onChange(event.target.value);
|
||||
}}
|
||||
value={url}
|
||||
onSubmit={(newURL) => onSubmit?.(newURL)}
|
||||
/>
|
||||
}
|
||||
onSubmit={onSubmit}
|
||||
onCancel={onCancel}
|
||||
nonEditModeContent={
|
||||
loading ? (
|
||||
<CellSkeleton />
|
||||
) : (
|
||||
<RawLink
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
href={internalValue ? 'https://' + internalValue : ''}
|
||||
href={url ? 'https://' + url : ''}
|
||||
>
|
||||
{internalValue}
|
||||
{url}
|
||||
</RawLink>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,30 +1,21 @@
|
||||
import { ChangeEvent, ReactNode, useEffect, useRef, useState } from 'react';
|
||||
import { ReactNode, useEffect, useState } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { textInputStyle } from '@/ui/themes/effects';
|
||||
|
||||
import { InplaceInputTextEditMode } from '../../../inplace-input/components/InplaceInputTextEditMode';
|
||||
import { EditableCell } from '../components/EditableCell';
|
||||
|
||||
export type EditableChipProps = {
|
||||
placeholder?: string;
|
||||
value: string;
|
||||
changeHandler: (updated: string) => void;
|
||||
editModeHorizontalAlign?: 'left' | 'right';
|
||||
ChipComponent: React.ReactNode;
|
||||
commentThreadCount?: number;
|
||||
onCommentClick?: (event: React.MouseEvent<HTMLDivElement>) => void;
|
||||
rightEndContents?: ReactNode[];
|
||||
onSubmit?: () => void;
|
||||
onSubmit?: (newValue: string) => void;
|
||||
onCancel?: () => void;
|
||||
};
|
||||
|
||||
// TODO: refactor
|
||||
const StyledInplaceInput = styled.input`
|
||||
width: 100%;
|
||||
|
||||
${textInputStyle}
|
||||
`;
|
||||
|
||||
const NoEditModeContainer = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
@ -40,14 +31,11 @@ const RightContainer = styled.div`
|
||||
export function EditableCellChip({
|
||||
value,
|
||||
placeholder,
|
||||
changeHandler,
|
||||
editModeHorizontalAlign,
|
||||
ChipComponent,
|
||||
rightEndContents,
|
||||
onSubmit,
|
||||
onCancel,
|
||||
}: EditableChipProps) {
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const [inputValue, setInputValue] = useState(value);
|
||||
|
||||
useEffect(() => {
|
||||
@ -64,19 +52,13 @@ export function EditableCellChip({
|
||||
<EditableCell
|
||||
editModeHorizontalAlign={editModeHorizontalAlign}
|
||||
editModeContent={
|
||||
<StyledInplaceInput
|
||||
<InplaceInputTextEditMode
|
||||
placeholder={placeholder || ''}
|
||||
autoFocus
|
||||
ref={inputRef}
|
||||
value={inputValue}
|
||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||
setInputValue(event.target.value);
|
||||
changeHandler(event.target.value);
|
||||
}}
|
||||
onSubmit={(newValue) => onSubmit?.(newValue)}
|
||||
/>
|
||||
}
|
||||
onSubmit={onSubmit}
|
||||
onCancel={onCancel}
|
||||
nonEditModeContent={
|
||||
<NoEditModeContainer>
|
||||
{ChipComponent}
|
||||
|
||||
Reference in New Issue
Block a user