4900 multi select field front implement expanded cells (#5151)
Add expanded cell https://github.com/twentyhq/twenty/assets/29927851/363f2b44-7b3c-4771-a651-dfc4014da6ac 
This commit is contained in:
@ -2,6 +2,7 @@ import { useContext } from 'react';
|
||||
|
||||
import { LinksFieldDisplay } from '@/object-record/record-field/meta-types/display/components/LinksFieldDisplay';
|
||||
import { isFieldLinks } from '@/object-record/record-field/types/guards/isFieldLinks';
|
||||
import { ExpandableListProps } from '@/ui/layout/expandable-list/components/ExpandableList';
|
||||
|
||||
import { FieldContext } from '../contexts/FieldContext';
|
||||
import { AddressFieldDisplay } from '../meta-types/display/components/AddressFieldDisplay';
|
||||
@ -13,7 +14,7 @@ import { EmailFieldDisplay } from '../meta-types/display/components/EmailFieldDi
|
||||
import { FullNameFieldDisplay } from '../meta-types/display/components/FullNameFieldDisplay';
|
||||
import { JsonFieldDisplay } from '../meta-types/display/components/JsonFieldDisplay';
|
||||
import { LinkFieldDisplay } from '../meta-types/display/components/LinkFieldDisplay';
|
||||
import { MultiSelectFieldDisplay } from '../meta-types/display/components/MultiSelectFieldDisplay.tsx';
|
||||
import { MultiSelectFieldDisplay } from '../meta-types/display/components/MultiSelectFieldDisplay';
|
||||
import { NumberFieldDisplay } from '../meta-types/display/components/NumberFieldDisplay';
|
||||
import { PhoneFieldDisplay } from '../meta-types/display/components/PhoneFieldDisplay';
|
||||
import { RelationFieldDisplay } from '../meta-types/display/components/RelationFieldDisplay';
|
||||
@ -36,7 +37,13 @@ import { isFieldSelect } from '../types/guards/isFieldSelect';
|
||||
import { isFieldText } from '../types/guards/isFieldText';
|
||||
import { isFieldUuid } from '../types/guards/isFieldUuid';
|
||||
|
||||
export const FieldDisplay = () => {
|
||||
type FieldDisplayProps = ExpandableListProps;
|
||||
|
||||
export const FieldDisplay = ({
|
||||
isHovered,
|
||||
reference,
|
||||
fromTableCell,
|
||||
}: FieldDisplayProps & { fromTableCell?: boolean }) => {
|
||||
const { fieldDefinition, isLabelIdentifier } = useContext(FieldContext);
|
||||
|
||||
const isChipDisplay =
|
||||
@ -74,7 +81,11 @@ export const FieldDisplay = () => {
|
||||
) : isFieldSelect(fieldDefinition) ? (
|
||||
<SelectFieldDisplay />
|
||||
) : isFieldMultiSelect(fieldDefinition) ? (
|
||||
<MultiSelectFieldDisplay />
|
||||
<MultiSelectFieldDisplay
|
||||
isHovered={isHovered}
|
||||
reference={reference}
|
||||
withDropDownBorder={fromTableCell}
|
||||
/>
|
||||
) : isFieldAddress(fieldDefinition) ? (
|
||||
<AddressFieldDisplay />
|
||||
) : isFieldRawJson(fieldDefinition) ? (
|
||||
|
||||
@ -4,7 +4,7 @@ import { AddressFieldInput } from '@/object-record/record-field/meta-types/input
|
||||
import { DateFieldInput } from '@/object-record/record-field/meta-types/input/components/DateFieldInput';
|
||||
import { FullNameFieldInput } from '@/object-record/record-field/meta-types/input/components/FullNameFieldInput';
|
||||
import { LinksFieldInput } from '@/object-record/record-field/meta-types/input/components/LinksFieldInput';
|
||||
import { MultiSelectFieldInput } from '@/object-record/record-field/meta-types/input/components/MultiSelectFieldInput.tsx';
|
||||
import { MultiSelectFieldInput } from '@/object-record/record-field/meta-types/input/components/MultiSelectFieldInput';
|
||||
import { RawJsonFieldInput } from '@/object-record/record-field/meta-types/input/components/RawJsonFieldInput';
|
||||
import { SelectFieldInput } from '@/object-record/record-field/meta-types/input/components/SelectFieldInput';
|
||||
import { RecordFieldInputScope } from '@/object-record/record-field/scopes/RecordFieldInputScope';
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { useContext } from 'react';
|
||||
import { IconComponent, IconPencil } from 'twenty-ui';
|
||||
|
||||
import { isFieldMultiSelect } from '@/object-record/record-field/types/guards/isFieldMultiSelect';
|
||||
import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
|
||||
@ -17,7 +18,8 @@ export const useGetButtonIcon = (): IconComponent | undefined => {
|
||||
if (
|
||||
isFieldLink(fieldDefinition) ||
|
||||
isFieldEmail(fieldDefinition) ||
|
||||
isFieldPhone(fieldDefinition)
|
||||
isFieldPhone(fieldDefinition) ||
|
||||
isFieldMultiSelect(fieldDefinition)
|
||||
) {
|
||||
return IconPencil;
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ import { isFieldFullNameValue } from '@/object-record/record-field/types/guards/
|
||||
import { isFieldLinks } from '@/object-record/record-field/types/guards/isFieldLinks';
|
||||
import { isFieldLinksValue } from '@/object-record/record-field/types/guards/isFieldLinksValue';
|
||||
import { isFieldMultiSelect } from '@/object-record/record-field/types/guards/isFieldMultiSelect';
|
||||
import { isFieldMultiSelectValue } from '@/object-record/record-field/types/guards/isFieldMultiSelectValue.ts';
|
||||
import { isFieldMultiSelectValue } from '@/object-record/record-field/types/guards/isFieldMultiSelectValue';
|
||||
import { isFieldRawJson } from '@/object-record/record-field/types/guards/isFieldRawJson';
|
||||
import { isFieldRawJsonValue } from '@/object-record/record-field/types/guards/isFieldRawJsonValue';
|
||||
import { isFieldSelect } from '@/object-record/record-field/types/guards/isFieldSelect';
|
||||
|
||||
@ -1,13 +1,16 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { useMultiSelectField } from '@/object-record/record-field/meta-types/hooks/useMultiSelectField';
|
||||
import { Tag } from '@/ui/display/tag/components/Tag';
|
||||
import {
|
||||
ExpandableList,
|
||||
ExpandableListProps,
|
||||
} from '@/ui/layout/expandable-list/components/ExpandableList';
|
||||
|
||||
const StyledTagContainer = styled.div`
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
`;
|
||||
export const MultiSelectFieldDisplay = () => {
|
||||
type MultiSelectFieldDisplayProps = ExpandableListProps;
|
||||
export const MultiSelectFieldDisplay = ({
|
||||
isHovered,
|
||||
reference,
|
||||
withDropDownBorder,
|
||||
}: MultiSelectFieldDisplayProps) => {
|
||||
const { fieldValues, fieldDefinition } = useMultiSelectField();
|
||||
|
||||
const selectedOptions = fieldValues
|
||||
@ -17,7 +20,11 @@ export const MultiSelectFieldDisplay = () => {
|
||||
: [];
|
||||
|
||||
return selectedOptions ? (
|
||||
<StyledTagContainer>
|
||||
<ExpandableList
|
||||
isHovered={isHovered}
|
||||
reference={reference}
|
||||
withDropDownBorder={withDropDownBorder}
|
||||
>
|
||||
{selectedOptions.map((selectedOption, index) => (
|
||||
<Tag
|
||||
key={index}
|
||||
@ -25,7 +32,7 @@ export const MultiSelectFieldDisplay = () => {
|
||||
text={selectedOption.label}
|
||||
/>
|
||||
))}
|
||||
</StyledTagContainer>
|
||||
</ExpandableList>
|
||||
) : (
|
||||
<></>
|
||||
);
|
||||
|
||||
@ -9,7 +9,7 @@ import { assertFieldMetadata } from '@/object-record/record-field/types/guards/a
|
||||
import { isFieldMultiSelect } from '@/object-record/record-field/types/guards/isFieldMultiSelect';
|
||||
import { isFieldMultiSelectValue } from '@/object-record/record-field/types/guards/isFieldMultiSelectValue';
|
||||
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
|
||||
import { FieldMetadataType } from '~/generated/graphql.tsx';
|
||||
import { FieldMetadataType } from '~/generated/graphql';
|
||||
|
||||
export const useMultiSelectField = () => {
|
||||
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
|
||||
|
||||
@ -7,7 +7,7 @@ import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||
import { MenuItemMultiSelectTag } from '@/ui/navigation/menu-item/components/MenuItemMultiSelectTag.tsx';
|
||||
import { MenuItemMultiSelectTag } from '@/ui/navigation/menu-item/components/MenuItemMultiSelectTag';
|
||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { useContext, useState } from 'react';
|
||||
import React, { useContext, useEffect, useRef, useState } from 'react';
|
||||
import { Tooltip } from 'react-tooltip';
|
||||
import { css, useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { motion } from 'framer-motion';
|
||||
import { IconComponent } from 'twenty-ui';
|
||||
|
||||
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
|
||||
import { EllipsisDisplay } from '@/ui/field/display/components/EllipsisDisplay';
|
||||
import { ExpandableListProps } from '@/ui/layout/expandable-list/components/ExpandableList';
|
||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||
|
||||
import { useInlineCell } from '../hooks/useInlineCell';
|
||||
@ -48,11 +48,6 @@ const StyledLabelContainer = styled.div<{ width?: number }>`
|
||||
width: ${({ width }) => width}px;
|
||||
`;
|
||||
|
||||
const StyledEditButtonContainer = styled(motion.div)`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
`;
|
||||
|
||||
const StyledClickableContainer = styled.div<{ readonly?: boolean }>`
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
@ -119,18 +114,24 @@ export const RecordInlineCellContainer = ({
|
||||
disableHoverEffect,
|
||||
}: RecordInlineCellContainerProps) => {
|
||||
const { entityId, fieldDefinition } = useContext(FieldContext);
|
||||
const reference = useRef<HTMLDivElement>(null);
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
const [isHoveredForDisplayMode, setIsHoveredForDisplayMode] = useState(false);
|
||||
const [newDisplayModeContent, setNewDisplayModeContent] =
|
||||
useState<React.ReactNode>(displayModeContent);
|
||||
|
||||
const handleContainerMouseEnter = () => {
|
||||
if (!readonly) {
|
||||
setIsHovered(true);
|
||||
}
|
||||
setIsHoveredForDisplayMode(true);
|
||||
};
|
||||
|
||||
const handleContainerMouseLeave = () => {
|
||||
if (!readonly) {
|
||||
setIsHovered(false);
|
||||
}
|
||||
setIsHoveredForDisplayMode(false);
|
||||
};
|
||||
|
||||
const { isInlineCellInEditMode, openInlineCell } = useInlineCell();
|
||||
@ -151,6 +152,17 @@ export const RecordInlineCellContainer = ({
|
||||
const theme = useTheme();
|
||||
const labelId = `label-${entityId}-${fieldDefinition?.metadata?.fieldName}`;
|
||||
|
||||
useEffect(() => {
|
||||
if (React.isValidElement<ExpandableListProps>(displayModeContent)) {
|
||||
setNewDisplayModeContent(
|
||||
React.cloneElement(displayModeContent, {
|
||||
isHovered: isHoveredForDisplayMode,
|
||||
reference: reference.current || undefined,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}, [isHoveredForDisplayMode, displayModeContent, reference]);
|
||||
|
||||
return (
|
||||
<StyledInlineCellBaseContainer
|
||||
onMouseEnter={handleContainerMouseEnter}
|
||||
@ -181,7 +193,7 @@ export const RecordInlineCellContainer = ({
|
||||
)}
|
||||
</StyledLabelAndIconContainer>
|
||||
)}
|
||||
<StyledValueContainer>
|
||||
<StyledValueContainer ref={reference}>
|
||||
{!readonly && isInlineCellInEditMode ? (
|
||||
<RecordInlineCellEditMode>{editModeContent}</RecordInlineCellEditMode>
|
||||
) : editModeContentOnly ? (
|
||||
@ -208,18 +220,9 @@ export const RecordInlineCellContainer = ({
|
||||
isHovered={isHovered}
|
||||
emptyPlaceholder={showLabel ? 'Empty' : label}
|
||||
>
|
||||
{displayModeContent}
|
||||
{newDisplayModeContent}
|
||||
</RecordInlineCellDisplayMode>
|
||||
{showEditButton && (
|
||||
<StyledEditButtonContainer
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.1 }}
|
||||
whileHover={{ scale: 1.04 }}
|
||||
>
|
||||
<RecordInlineCellButton Icon={buttonIcon} />
|
||||
</StyledEditButtonContainer>
|
||||
)}
|
||||
{showEditButton && <RecordInlineCellButton Icon={buttonIcon} />}
|
||||
</StyledClickableContainer>
|
||||
)}
|
||||
</StyledValueContainer>
|
||||
|
||||
@ -1,13 +1,23 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { IconComponent } from 'twenty-ui';
|
||||
|
||||
import { AnimatedContainer } from '@/object-record/record-table/components/AnimatedContainer';
|
||||
import { FloatingIconButton } from '@/ui/input/button/components/FloatingIconButton';
|
||||
|
||||
const StyledInlineCellButtonContainer = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
`;
|
||||
export const RecordInlineCellButton = ({ Icon }: { Icon: IconComponent }) => {
|
||||
return (
|
||||
<FloatingIconButton
|
||||
size="small"
|
||||
Icon={Icon}
|
||||
data-testid="inline-cell-edit-mode-container"
|
||||
/>
|
||||
<AnimatedContainer>
|
||||
<StyledInlineCellButtonContainer>
|
||||
<FloatingIconButton
|
||||
size="small"
|
||||
Icon={Icon}
|
||||
data-testid="inline-cell-edit-mode-container"
|
||||
/>
|
||||
</StyledInlineCellButtonContainer>
|
||||
</AnimatedContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
const StyledAnimatedChipContainer = styled(motion.div)``;
|
||||
|
||||
export const AnimatedContainer = ({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) => (
|
||||
<StyledAnimatedChipContainer
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.1 }}
|
||||
whileHover={{ scale: 1.04 }}
|
||||
>
|
||||
{children}
|
||||
</StyledAnimatedChipContainer>
|
||||
);
|
||||
@ -102,7 +102,7 @@ export const RecordTableCell = ({
|
||||
isReadOnly={isReadOnly}
|
||||
/>
|
||||
}
|
||||
nonEditModeContent={<FieldDisplay />}
|
||||
nonEditModeContent={<FieldDisplay fromTableCell />}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { motion } from 'framer-motion';
|
||||
import { IconComponent } from 'twenty-ui';
|
||||
|
||||
import { AnimatedContainer } from '@/object-record/record-table/components/AnimatedContainer';
|
||||
import { FloatingIconButton } from '@/ui/input/button/components/FloatingIconButton';
|
||||
|
||||
const StyledEditButtonContainer = styled(motion.div)`
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
const StyledButtonContainer = styled.div`
|
||||
margin: ${({ theme }) => theme.spacing(1)};
|
||||
`;
|
||||
|
||||
type RecordTableCellButtonProps = {
|
||||
@ -18,12 +17,9 @@ export const RecordTableCellButton = ({
|
||||
onClick,
|
||||
Icon,
|
||||
}: RecordTableCellButtonProps) => (
|
||||
<StyledEditButtonContainer
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.1 }}
|
||||
whileHover={{ scale: 1.04 }}
|
||||
>
|
||||
<FloatingIconButton size="small" onClick={onClick} Icon={Icon} />
|
||||
</StyledEditButtonContainer>
|
||||
<AnimatedContainer>
|
||||
<StyledButtonContainer>
|
||||
<FloatingIconButton size="small" onClick={onClick} Icon={Icon} />
|
||||
</StyledButtonContainer>
|
||||
</AnimatedContainer>
|
||||
);
|
||||
|
||||
@ -1,4 +1,10 @@
|
||||
import React, { ReactElement, useContext, useState } from 'react';
|
||||
import React, {
|
||||
ReactElement,
|
||||
useContext,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { IconArrowUpRight } from 'twenty-ui';
|
||||
@ -14,6 +20,7 @@ import { useOpenRecordTableCellFromCell } from '@/object-record/record-table/rec
|
||||
import { RecordTableScopeInternalContext } from '@/object-record/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext';
|
||||
import { isSoftFocusOnTableCellComponentFamilyState } from '@/object-record/record-table/states/isSoftFocusOnTableCellComponentFamilyState';
|
||||
import { isTableCellInEditModeComponentFamilyState } from '@/object-record/record-table/states/isTableCellInEditModeComponentFamilyState';
|
||||
import { ExpandableListProps } from '@/ui/layout/expandable-list/components/ExpandableList';
|
||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||
import { getScopeIdOrUndefinedFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdOrUndefinedFromComponentId';
|
||||
@ -33,7 +40,7 @@ const StyledTd = styled.td<{ isSelected: boolean; isInEditMode: boolean }>`
|
||||
z-index: ${({ isInEditMode }) => (isInEditMode ? '4 !important' : '3')};
|
||||
`;
|
||||
|
||||
const StyledCellBaseContainer = styled.div`
|
||||
const StyledCellBaseContainer = styled.div<{ softFocus: boolean }>`
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
@ -41,6 +48,12 @@ const StyledCellBaseContainer = styled.div`
|
||||
height: 32px;
|
||||
position: relative;
|
||||
user-select: none;
|
||||
${(props) =>
|
||||
props.softFocus
|
||||
? `background: ${props.theme.background.transparent.secondary};
|
||||
border-radius: ${props.theme.border.radius.sm};
|
||||
outline: 1px solid ${props.theme.font.color.extraLight};`
|
||||
: ''}
|
||||
`;
|
||||
|
||||
export type RecordTableCellContainerProps = {
|
||||
@ -63,6 +76,10 @@ export const RecordTableCellContainer = ({
|
||||
editHotkeyScope,
|
||||
}: RecordTableCellContainerProps) => {
|
||||
const { columnIndex } = useContext(RecordTableCellContext);
|
||||
const reference = useRef<HTMLTableCellElement>(null);
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
const [newNonEditModeContent, setNewNonEditModeContent] =
|
||||
useState<ReactElement>(nonEditModeContent);
|
||||
const { isReadOnly, isSelected, recordId } = useContext(
|
||||
RecordTableRowContext,
|
||||
);
|
||||
@ -71,8 +88,6 @@ export const RecordTableCellContainer = ({
|
||||
|
||||
const cellPosition = useCurrentTableCellPosition();
|
||||
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
|
||||
const { openTableCell } = useOpenRecordTableCellFromCell();
|
||||
|
||||
const tableScopeId = useAvailableScopeIdOrThrow(
|
||||
@ -135,8 +150,20 @@ export const RecordTableCellContainer = ({
|
||||
(!isFirstColumn || !isEmpty) &&
|
||||
!isReadOnly;
|
||||
|
||||
useEffect(() => {
|
||||
if (React.isValidElement<ExpandableListProps>(nonEditModeContent)) {
|
||||
setNewNonEditModeContent(
|
||||
React.cloneElement(nonEditModeContent, {
|
||||
isHovered: showButton,
|
||||
reference: reference.current || undefined,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}, [nonEditModeContent, showButton, reference]);
|
||||
|
||||
return (
|
||||
<StyledTd
|
||||
ref={reference}
|
||||
isSelected={isSelected}
|
||||
onContextMenu={handleContextMenu}
|
||||
isInEditMode={isCurrentTableCellInEditMode}
|
||||
@ -147,34 +174,37 @@ export const RecordTableCellContainer = ({
|
||||
<StyledCellBaseContainer
|
||||
onMouseEnter={handleContainerMouseEnter}
|
||||
onMouseLeave={handleContainerMouseLeave}
|
||||
softFocus={hasSoftFocus}
|
||||
>
|
||||
{isCurrentTableCellInEditMode ? (
|
||||
<RecordTableCellEditMode>{editModeContent}</RecordTableCellEditMode>
|
||||
) : hasSoftFocus ? (
|
||||
<>
|
||||
<RecordTableCellSoftFocusMode>
|
||||
{editModeContentOnly ? editModeContent : newNonEditModeContent}
|
||||
</RecordTableCellSoftFocusMode>
|
||||
{showButton && (
|
||||
<RecordTableCellButton
|
||||
onClick={handleButtonClick}
|
||||
Icon={buttonIcon}
|
||||
/>
|
||||
)}
|
||||
<RecordTableCellSoftFocusMode>
|
||||
{editModeContentOnly ? editModeContent : nonEditModeContent}
|
||||
</RecordTableCellSoftFocusMode>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{!isEmpty && (
|
||||
<RecordTableCellDisplayMode>
|
||||
{editModeContentOnly
|
||||
? editModeContent
|
||||
: newNonEditModeContent}
|
||||
</RecordTableCellDisplayMode>
|
||||
)}
|
||||
{showButton && (
|
||||
<RecordTableCellButton
|
||||
onClick={handleButtonClick}
|
||||
Icon={buttonIcon}
|
||||
/>
|
||||
)}
|
||||
{!isEmpty && (
|
||||
<RecordTableCellDisplayMode>
|
||||
{editModeContentOnly ? editModeContent : nonEditModeContent}
|
||||
</RecordTableCellDisplayMode>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</StyledCellBaseContainer>
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { motion } from 'framer-motion';
|
||||
import { IconComponent } from 'twenty-ui';
|
||||
|
||||
import { FloatingIconButton } from '@/ui/input/button/components/FloatingIconButton';
|
||||
|
||||
const StyledEditButtonContainer = styled(motion.div)`
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
`;
|
||||
|
||||
type RecordTableCellEditButtonProps = {
|
||||
onClick?: () => void;
|
||||
Icon: IconComponent;
|
||||
};
|
||||
|
||||
export const RecordTableCellEditButton = ({
|
||||
onClick,
|
||||
Icon,
|
||||
}: RecordTableCellEditButtonProps) => (
|
||||
<StyledEditButtonContainer
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.1 }}
|
||||
whileHover={{ scale: 1.04 }}
|
||||
>
|
||||
<FloatingIconButton size="small" onClick={onClick} Icon={Icon} />
|
||||
</StyledEditButtonContainer>
|
||||
);
|
||||
@ -101,7 +101,6 @@ export const RecordTableCellSoftFocusMode = ({
|
||||
return (
|
||||
<RecordTableCellDisplayContainer
|
||||
onClick={handleClick}
|
||||
softFocus
|
||||
scrollRef={scrollRef}
|
||||
>
|
||||
{children}
|
||||
|
||||
Reference in New Issue
Block a user