feat: add Table and TableSection components (#1849)
* refactor: rename ui/table to ui/data-table * feat: add Table and TableSection components Closes #1806
This commit is contained in:
@ -0,0 +1,74 @@
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { FieldDisplay } from '@/ui/field/components/FieldDisplay';
|
||||
import { FieldInput } from '@/ui/field/components/FieldInput';
|
||||
import { FieldContext } from '@/ui/field/contexts/FieldContext';
|
||||
import { FieldInputEvent } from '@/ui/field/types/FieldInputEvent';
|
||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||
|
||||
import { useMoveSoftFocus } from '../../hooks/useMoveSoftFocus';
|
||||
import { useTableCell } from '../hooks/useTableCell';
|
||||
|
||||
import { TableCellContainer } from './TableCellContainer';
|
||||
|
||||
export const TableCell = ({
|
||||
customHotkeyScope,
|
||||
}: {
|
||||
customHotkeyScope: HotkeyScope;
|
||||
}) => {
|
||||
const { fieldDefinition } = useContext(FieldContext);
|
||||
|
||||
const { closeTableCell } = useTableCell();
|
||||
|
||||
const { moveLeft, moveRight, moveDown } = useMoveSoftFocus();
|
||||
|
||||
const handleEnter: FieldInputEvent = (persistField) => {
|
||||
persistField();
|
||||
closeTableCell();
|
||||
moveDown();
|
||||
};
|
||||
|
||||
const handleSubmit: FieldInputEvent = (persistField) => {
|
||||
persistField();
|
||||
closeTableCell();
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
closeTableCell();
|
||||
};
|
||||
|
||||
const handleEscape = () => {
|
||||
closeTableCell();
|
||||
};
|
||||
|
||||
const handleTab: FieldInputEvent = (persistField) => {
|
||||
persistField();
|
||||
closeTableCell();
|
||||
moveRight();
|
||||
};
|
||||
|
||||
const handleShiftTab: FieldInputEvent = (persistField) => {
|
||||
persistField();
|
||||
closeTableCell();
|
||||
moveLeft();
|
||||
};
|
||||
|
||||
return (
|
||||
<TableCellContainer
|
||||
editHotkeyScope={customHotkeyScope}
|
||||
editModeContent={
|
||||
<FieldInput
|
||||
onCancel={handleCancel}
|
||||
onClickOutside={handleCancel}
|
||||
onEnter={handleEnter}
|
||||
onEscape={handleEscape}
|
||||
onShiftTab={handleShiftTab}
|
||||
onSubmit={handleSubmit}
|
||||
onTab={handleTab}
|
||||
/>
|
||||
}
|
||||
nonEditModeContent={<FieldDisplay />}
|
||||
buttonIcon={fieldDefinition.buttonIcon}
|
||||
></TableCellContainer>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,26 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
import { FloatingIconButton } from '@/ui/button/components/FloatingIconButton';
|
||||
import { IconComponent } from '@/ui/icon/types/IconComponent';
|
||||
|
||||
const StyledEditButtonContainer = styled(motion.div)`
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
`;
|
||||
|
||||
type TableCellButtonProps = {
|
||||
onClick?: () => void;
|
||||
Icon: IconComponent;
|
||||
};
|
||||
|
||||
export const TableCellButton = ({ onClick, Icon }: TableCellButtonProps) => (
|
||||
<StyledEditButtonContainer
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.1 }}
|
||||
whileHover={{ scale: 1.04 }}
|
||||
>
|
||||
<FloatingIconButton size="small" onClick={onClick} Icon={Icon} />
|
||||
</StyledEditButtonContainer>
|
||||
);
|
||||
@ -0,0 +1,134 @@
|
||||
import { ReactElement, useContext, useState } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { useIsFieldEmpty } from '@/ui/field/hooks/useIsFieldEmpty';
|
||||
import { useIsFieldInputOnly } from '@/ui/field/hooks/useIsFieldInputOnly';
|
||||
import { IconComponent } from '@/ui/icon/types/IconComponent';
|
||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||
|
||||
import { CellHotkeyScopeContext } from '../../contexts/CellHotkeyScopeContext';
|
||||
import { ColumnIndexContext } from '../../contexts/ColumnIndexContext';
|
||||
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
||||
import { useCurrentTableCellEditMode } from '../hooks/useCurrentTableCellEditMode';
|
||||
import { useIsSoftFocusOnCurrentTableCell } from '../hooks/useIsSoftFocusOnCurrentTableCell';
|
||||
import { useSetSoftFocusOnCurrentTableCell } from '../hooks/useSetSoftFocusOnCurrentTableCell';
|
||||
import { useTableCell } from '../hooks/useTableCell';
|
||||
|
||||
import { TableCellButton } from './TableCellButton';
|
||||
import { TableCellDisplayMode } from './TableCellDisplayMode';
|
||||
import { TableCellEditMode } from './TableCellEditMode';
|
||||
import { TableCellSoftFocusMode } from './TableCellSoftFocusMode';
|
||||
|
||||
const StyledCellBaseContainer = styled.div`
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
height: 32px;
|
||||
position: relative;
|
||||
user-select: none;
|
||||
`;
|
||||
|
||||
export type EditableCellProps = {
|
||||
editModeContent: ReactElement;
|
||||
nonEditModeContent: ReactElement;
|
||||
editModeHorizontalAlign?: 'left' | 'right';
|
||||
editModeVerticalPosition?: 'over' | 'below';
|
||||
editHotkeyScope?: HotkeyScope;
|
||||
transparent?: boolean;
|
||||
maxContentWidth?: number;
|
||||
buttonIcon?: IconComponent;
|
||||
onSubmit?: () => void;
|
||||
onCancel?: () => void;
|
||||
};
|
||||
|
||||
const DEFAULT_CELL_SCOPE: HotkeyScope = {
|
||||
scope: TableHotkeyScope.CellEditMode,
|
||||
};
|
||||
|
||||
export const TableCellContainer = ({
|
||||
editModeHorizontalAlign = 'left',
|
||||
editModeVerticalPosition = 'over',
|
||||
editModeContent,
|
||||
nonEditModeContent,
|
||||
editHotkeyScope,
|
||||
transparent = false,
|
||||
maxContentWidth,
|
||||
buttonIcon,
|
||||
}: EditableCellProps) => {
|
||||
const { isCurrentTableCellInEditMode } = useCurrentTableCellEditMode();
|
||||
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
|
||||
const setSoftFocusOnCurrentTableCell = useSetSoftFocusOnCurrentTableCell();
|
||||
|
||||
const { openTableCell } = useTableCell();
|
||||
|
||||
const handleButtonClick = () => {
|
||||
setSoftFocusOnCurrentTableCell();
|
||||
openTableCell();
|
||||
};
|
||||
|
||||
const handleContainerMouseEnter = () => {
|
||||
setIsHovered(true);
|
||||
};
|
||||
|
||||
const handleContainerMouseLeave = () => {
|
||||
setIsHovered(false);
|
||||
};
|
||||
|
||||
const editModeContentOnly = useIsFieldInputOnly();
|
||||
|
||||
const isFirstColumnCell = useContext(ColumnIndexContext) === 0;
|
||||
|
||||
const isEmpty = useIsFieldEmpty();
|
||||
|
||||
const showButton =
|
||||
buttonIcon &&
|
||||
isHovered &&
|
||||
!isCurrentTableCellInEditMode &&
|
||||
!editModeContentOnly &&
|
||||
(!isFirstColumnCell || !isEmpty);
|
||||
|
||||
const hasSoftFocus = useIsSoftFocusOnCurrentTableCell();
|
||||
|
||||
return (
|
||||
<CellHotkeyScopeContext.Provider
|
||||
value={editHotkeyScope ?? DEFAULT_CELL_SCOPE}
|
||||
>
|
||||
<StyledCellBaseContainer
|
||||
onMouseEnter={handleContainerMouseEnter}
|
||||
onMouseLeave={handleContainerMouseLeave}
|
||||
>
|
||||
{isCurrentTableCellInEditMode ? (
|
||||
<TableCellEditMode
|
||||
maxContentWidth={maxContentWidth}
|
||||
transparent={transparent}
|
||||
editModeHorizontalAlign={editModeHorizontalAlign}
|
||||
editModeVerticalPosition={editModeVerticalPosition}
|
||||
>
|
||||
{editModeContent}
|
||||
</TableCellEditMode>
|
||||
) : hasSoftFocus ? (
|
||||
<>
|
||||
{showButton && (
|
||||
<TableCellButton onClick={handleButtonClick} Icon={buttonIcon} />
|
||||
)}
|
||||
<TableCellSoftFocusMode>
|
||||
{editModeContentOnly ? editModeContent : nonEditModeContent}
|
||||
</TableCellSoftFocusMode>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{showButton && (
|
||||
<TableCellButton onClick={handleButtonClick} Icon={buttonIcon} />
|
||||
)}
|
||||
<TableCellDisplayMode isHovered={isHovered}>
|
||||
{editModeContentOnly ? editModeContent : nonEditModeContent}
|
||||
</TableCellDisplayMode>
|
||||
</>
|
||||
)}
|
||||
</StyledCellBaseContainer>
|
||||
</CellHotkeyScopeContext.Provider>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,57 @@
|
||||
import { Ref } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
export type EditableCellDisplayContainerProps = {
|
||||
softFocus?: boolean;
|
||||
onClick?: () => void;
|
||||
scrollRef?: Ref<HTMLDivElement>;
|
||||
isHovered?: boolean;
|
||||
};
|
||||
|
||||
const StyledEditableCellDisplayModeOuterContainer = styled.div<
|
||||
Pick<EditableCellDisplayContainerProps, 'softFocus' | 'isHovered'>
|
||||
>`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
padding-left: ${({ theme }) => theme.spacing(2)};
|
||||
padding-right: ${({ theme }) => theme.spacing(1)};
|
||||
width: 100%;
|
||||
${(props) =>
|
||||
props.softFocus || props.isHovered
|
||||
? `background: ${props.theme.background.transparent.secondary};
|
||||
border-radius: ${props.theme.border.radius.sm};
|
||||
outline: 1px solid ${props.theme.font.color.extraLight};`
|
||||
: ''}
|
||||
`;
|
||||
|
||||
const StyledEditableCellDisplayModeInnerContainer = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const TableCellDisplayContainer = ({
|
||||
children,
|
||||
softFocus,
|
||||
onClick,
|
||||
scrollRef,
|
||||
isHovered,
|
||||
}: React.PropsWithChildren<EditableCellDisplayContainerProps>) => (
|
||||
<StyledEditableCellDisplayModeOuterContainer
|
||||
data-testid={
|
||||
softFocus ? 'editable-cell-soft-focus-mode' : 'editable-cell-display-mode'
|
||||
}
|
||||
onClick={onClick}
|
||||
isHovered={isHovered}
|
||||
softFocus={softFocus}
|
||||
ref={scrollRef}
|
||||
>
|
||||
<StyledEditableCellDisplayModeInnerContainer>
|
||||
{children}
|
||||
</StyledEditableCellDisplayModeInnerContainer>
|
||||
</StyledEditableCellDisplayModeOuterContainer>
|
||||
);
|
||||
@ -0,0 +1,31 @@
|
||||
import { useIsFieldInputOnly } from '@/ui/field/hooks/useIsFieldInputOnly';
|
||||
|
||||
import { useSetSoftFocusOnCurrentTableCell } from '../hooks/useSetSoftFocusOnCurrentTableCell';
|
||||
import { useTableCell } from '../hooks/useTableCell';
|
||||
|
||||
import { TableCellDisplayContainer } from './TableCellDisplayContainer';
|
||||
|
||||
export const TableCellDisplayMode = ({
|
||||
children,
|
||||
isHovered,
|
||||
}: React.PropsWithChildren<unknown> & { isHovered?: boolean }) => {
|
||||
const setSoftFocusOnCurrentCell = useSetSoftFocusOnCurrentTableCell();
|
||||
|
||||
const isFieldInputOnly = useIsFieldInputOnly();
|
||||
|
||||
const { openTableCell } = useTableCell();
|
||||
|
||||
const handleClick = () => {
|
||||
setSoftFocusOnCurrentCell();
|
||||
|
||||
if (!isFieldInputOnly) {
|
||||
openTableCell();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<TableCellDisplayContainer isHovered={isHovered} onClick={handleClick}>
|
||||
{children}
|
||||
</TableCellDisplayContainer>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,26 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
import { FloatingIconButton } from '@/ui/button/components/FloatingIconButton';
|
||||
import { IconComponent } from '@/ui/icon/types/IconComponent';
|
||||
|
||||
const StyledEditButtonContainer = styled(motion.div)`
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
`;
|
||||
|
||||
type TableCellButtonProps = {
|
||||
onClick?: () => void;
|
||||
Icon: IconComponent;
|
||||
};
|
||||
|
||||
export const TableCellButton = ({ onClick, Icon }: TableCellButtonProps) => (
|
||||
<StyledEditButtonContainer
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.1 }}
|
||||
whileHover={{ scale: 1.04 }}
|
||||
>
|
||||
<FloatingIconButton size="small" onClick={onClick} Icon={Icon} />
|
||||
</StyledEditButtonContainer>
|
||||
);
|
||||
@ -0,0 +1,53 @@
|
||||
import { ReactElement } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { overlayBackground } from '@/ui/theme/constants/effects';
|
||||
|
||||
const StyledEditableCellEditModeContainer = styled.div<EditableCellEditModeProps>`
|
||||
align-items: center;
|
||||
border: ${({ transparent, theme }) =>
|
||||
transparent ? 'none' : `1px solid ${theme.border.color.light}`};
|
||||
border-radius: ${({ transparent, theme }) =>
|
||||
transparent ? 'none' : theme.border.radius.sm};
|
||||
display: flex;
|
||||
left: ${(props) =>
|
||||
props.editModeHorizontalAlign === 'right' ? 'auto' : '0'};
|
||||
margin: -1px;
|
||||
max-width: ${({ maxContentWidth }) =>
|
||||
maxContentWidth ? `${maxContentWidth}px` : 'none'};
|
||||
min-height: 100%;
|
||||
min-width: ${({ maxContentWidth }) => (maxContentWidth ? `none` : '100%')};
|
||||
position: absolute;
|
||||
right: ${(props) =>
|
||||
props.editModeHorizontalAlign === 'right' ? '0' : 'auto'};
|
||||
top: ${(props) => (props.editModeVerticalPosition === 'over' ? '0' : '100%')};
|
||||
${({ transparent }) => (transparent ? '' : overlayBackground)};
|
||||
z-index: 1;
|
||||
`;
|
||||
|
||||
export type EditableCellEditModeProps = {
|
||||
children: ReactElement;
|
||||
transparent?: boolean;
|
||||
maxContentWidth?: number;
|
||||
editModeHorizontalAlign?: 'left' | 'right';
|
||||
editModeVerticalPosition?: 'over' | 'below';
|
||||
initialValue?: string;
|
||||
};
|
||||
|
||||
export const TableCellEditMode = ({
|
||||
editModeHorizontalAlign,
|
||||
editModeVerticalPosition,
|
||||
children,
|
||||
transparent = false,
|
||||
maxContentWidth,
|
||||
}: EditableCellEditModeProps) => (
|
||||
<StyledEditableCellEditModeContainer
|
||||
maxContentWidth={maxContentWidth}
|
||||
transparent={transparent}
|
||||
data-testid="editable-cell-edit-mode-container"
|
||||
editModeHorizontalAlign={editModeHorizontalAlign}
|
||||
editModeVerticalPosition={editModeVerticalPosition}
|
||||
>
|
||||
{children}
|
||||
</StyledEditableCellEditModeContainer>
|
||||
);
|
||||
@ -0,0 +1,74 @@
|
||||
import { PropsWithChildren, useEffect, useRef } from 'react';
|
||||
|
||||
import { useIsFieldInputOnly } from '@/ui/field/hooks/useIsFieldInputOnly';
|
||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import { isNonTextWritingKey } from '@/ui/utilities/hotkey/utils/isNonTextWritingKey';
|
||||
|
||||
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
||||
import { useTableCell } from '../hooks/useTableCell';
|
||||
|
||||
import { TableCellDisplayContainer } from './TableCellDisplayContainer';
|
||||
|
||||
type OwnProps = PropsWithChildren<unknown>;
|
||||
|
||||
export const TableCellSoftFocusMode = ({ children }: OwnProps) => {
|
||||
const { openTableCell } = useTableCell();
|
||||
|
||||
const isFieldInputOnly = useIsFieldInputOnly();
|
||||
|
||||
const scrollRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
scrollRef.current?.scrollIntoView({ block: 'nearest' });
|
||||
}, []);
|
||||
|
||||
useScopedHotkeys(
|
||||
'enter',
|
||||
() => {
|
||||
openTableCell();
|
||||
},
|
||||
TableHotkeyScope.TableSoftFocus,
|
||||
[openTableCell],
|
||||
{
|
||||
enabled: !isFieldInputOnly,
|
||||
},
|
||||
);
|
||||
|
||||
useScopedHotkeys(
|
||||
'*',
|
||||
(keyboardEvent) => {
|
||||
const isWritingText =
|
||||
!isNonTextWritingKey(keyboardEvent.key) &&
|
||||
!keyboardEvent.ctrlKey &&
|
||||
!keyboardEvent.metaKey;
|
||||
|
||||
if (!isWritingText) {
|
||||
return;
|
||||
}
|
||||
|
||||
openTableCell();
|
||||
},
|
||||
TableHotkeyScope.TableSoftFocus,
|
||||
[openTableCell],
|
||||
{
|
||||
preventDefault: false,
|
||||
enabled: !isFieldInputOnly,
|
||||
},
|
||||
);
|
||||
|
||||
const handleClick = () => {
|
||||
if (!isFieldInputOnly) {
|
||||
openTableCell();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<TableCellDisplayContainer
|
||||
onClick={handleClick}
|
||||
softFocus
|
||||
scrollRef={scrollRef}
|
||||
>
|
||||
{children}
|
||||
</TableCellDisplayContainer>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,20 @@
|
||||
import { useContext, useMemo } from 'react';
|
||||
|
||||
import { ColumnIndexContext } from '../../contexts/ColumnIndexContext';
|
||||
import { RowIndexContext } from '../../contexts/RowIndexContext';
|
||||
import { TableCellPosition } from '../../types/TableCellPosition';
|
||||
|
||||
export const useCurrentTableCellPosition = () => {
|
||||
const currentRowNumber = useContext(RowIndexContext);
|
||||
const currentColumnNumber = useContext(ColumnIndexContext);
|
||||
|
||||
const currentTableCellPosition: TableCellPosition = useMemo(
|
||||
() => ({
|
||||
column: currentColumnNumber,
|
||||
row: currentRowNumber,
|
||||
}),
|
||||
[currentColumnNumber, currentRowNumber],
|
||||
);
|
||||
|
||||
return currentTableCellPosition;
|
||||
};
|
||||
@ -0,0 +1,26 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { useMoveEditModeToTableCellPosition } from '../../hooks/useMoveEditModeToCellPosition';
|
||||
import { isTableCellInEditModeFamilyState } from '../../states/isTableCellInEditModeFamilyState';
|
||||
|
||||
import { useCurrentTableCellPosition } from './useCurrentCellPosition';
|
||||
|
||||
export const useCurrentTableCellEditMode = () => {
|
||||
const moveEditModeToTableCellPosition = useMoveEditModeToTableCellPosition();
|
||||
|
||||
const currentTableCellPosition = useCurrentTableCellPosition();
|
||||
|
||||
const [isCurrentTableCellInEditMode] = useRecoilState(
|
||||
isTableCellInEditModeFamilyState(currentTableCellPosition),
|
||||
);
|
||||
|
||||
const setCurrentTableCellInEditMode = useCallback(() => {
|
||||
moveEditModeToTableCellPosition(currentTableCellPosition);
|
||||
}, [currentTableCellPosition, moveEditModeToTableCellPosition]);
|
||||
|
||||
return {
|
||||
isCurrentTableCellInEditMode,
|
||||
setCurrentTableCellInEditMode,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,15 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { isSoftFocusOnTableCellFamilyState } from '../../states/isSoftFocusOnTableCellFamilyState';
|
||||
|
||||
import { useCurrentTableCellPosition } from './useCurrentCellPosition';
|
||||
|
||||
export const useIsSoftFocusOnCurrentTableCell = () => {
|
||||
const currentTableCellPosition = useCurrentTableCellPosition();
|
||||
|
||||
const isSoftFocusOnTableCell = useRecoilValue(
|
||||
isSoftFocusOnTableCellFamilyState(currentTableCellPosition),
|
||||
);
|
||||
|
||||
return isSoftFocusOnTableCell;
|
||||
};
|
||||
@ -0,0 +1,29 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||
|
||||
import { useSetSoftFocusPosition } from '../../hooks/useSetSoftFocusPosition';
|
||||
import { isSoftFocusActiveState } from '../../states/isSoftFocusActiveState';
|
||||
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
||||
|
||||
import { useCurrentTableCellPosition } from './useCurrentCellPosition';
|
||||
|
||||
export const useSetSoftFocusOnCurrentTableCell = () => {
|
||||
const setSoftFocusPosition = useSetSoftFocusPosition();
|
||||
|
||||
const currentTableCellPosition = useCurrentTableCellPosition();
|
||||
|
||||
const setHotkeyScope = useSetHotkeyScope();
|
||||
|
||||
return useRecoilCallback(
|
||||
({ set }) =>
|
||||
() => {
|
||||
setSoftFocusPosition(currentTableCellPosition);
|
||||
|
||||
set(isSoftFocusActiveState, true);
|
||||
|
||||
setHotkeyScope(TableHotkeyScope.TableSoftFocus);
|
||||
},
|
||||
[setHotkeyScope, currentTableCellPosition, setSoftFocusPosition],
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,68 @@
|
||||
import { useContext } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { FieldContext } from '@/ui/field/contexts/FieldContext';
|
||||
import { useIsFieldEmpty } from '@/ui/field/hooks/useIsFieldEmpty';
|
||||
import { useDragSelect } from '@/ui/utilities/drag-select/hooks/useDragSelect';
|
||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||
|
||||
import { CellHotkeyScopeContext } from '../../contexts/CellHotkeyScopeContext';
|
||||
import { ColumnIndexContext } from '../../contexts/ColumnIndexContext';
|
||||
import { useCloseCurrentTableCellInEditMode } from '../../hooks/useCloseCurrentTableCellInEditMode';
|
||||
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
||||
|
||||
import { useCurrentTableCellEditMode } from './useCurrentTableCellEditMode';
|
||||
|
||||
const DEFAULT_CELL_SCOPE: HotkeyScope = {
|
||||
scope: TableHotkeyScope.CellEditMode,
|
||||
};
|
||||
|
||||
export const useTableCell = () => {
|
||||
const { setCurrentTableCellInEditMode } = useCurrentTableCellEditMode();
|
||||
|
||||
const setHotkeyScope = useSetHotkeyScope();
|
||||
const { setDragSelectionStartEnabled } = useDragSelect();
|
||||
|
||||
const closeCurrentTableCellInEditMode = useCloseCurrentTableCellInEditMode();
|
||||
|
||||
const customCellHotkeyScope = useContext(CellHotkeyScopeContext);
|
||||
|
||||
const closeTableCell = () => {
|
||||
setDragSelectionStartEnabled(true);
|
||||
closeCurrentTableCellInEditMode();
|
||||
setHotkeyScope(TableHotkeyScope.TableSoftFocus);
|
||||
};
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const isFirstColumnCell = useContext(ColumnIndexContext) === 0;
|
||||
|
||||
const isEmpty = useIsFieldEmpty();
|
||||
|
||||
const { entityId, fieldDefinition } = useContext(FieldContext);
|
||||
|
||||
const openTableCell = () => {
|
||||
if (isFirstColumnCell && !isEmpty && fieldDefinition.basePathToShowPage) {
|
||||
navigate(`${fieldDefinition.basePathToShowPage}${entityId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
setDragSelectionStartEnabled(false);
|
||||
setCurrentTableCellInEditMode();
|
||||
|
||||
if (customCellHotkeyScope) {
|
||||
setHotkeyScope(
|
||||
customCellHotkeyScope.scope,
|
||||
customCellHotkeyScope.customScopes,
|
||||
);
|
||||
} else {
|
||||
setHotkeyScope(DEFAULT_CELL_SCOPE.scope, DEFAULT_CELL_SCOPE.customScopes);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
closeTableCell,
|
||||
openTableCell,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,6 @@
|
||||
import { atomFamily } from 'recoil';
|
||||
|
||||
export const isCreateModeScopedState = atomFamily<boolean, string>({
|
||||
key: 'isCreateModeScopedState',
|
||||
default: false,
|
||||
});
|
||||
Reference in New Issue
Block a user