diff --git a/front/src/modules/activities/components/ActivityComments.tsx b/front/src/modules/activities/components/ActivityComments.tsx index 9687f6639..35dec2e1f 100644 --- a/front/src/modules/activities/components/ActivityComments.tsx +++ b/front/src/modules/activities/components/ActivityComments.tsx @@ -7,7 +7,7 @@ import { currentUserState } from '@/auth/states/currentUserState'; import { AutosizeTextInput, AutosizeTextInputVariant, -} from '@/ui/input/autosize-text/components/AutosizeTextInput'; +} from '@/ui/input/components/AutosizeTextInput'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import { Activity, useCreateCommentMutation } from '~/generated/graphql'; import { isNonEmptyString } from '~/utils/isNonEmptyString'; diff --git a/front/src/modules/activities/components/ActivityTitle.tsx b/front/src/modules/activities/components/ActivityTitle.tsx index 0f0b22cc3..a9fed0708 100644 --- a/front/src/modules/activities/components/ActivityTitle.tsx +++ b/front/src/modules/activities/components/ActivityTitle.tsx @@ -4,7 +4,7 @@ import { Checkbox, CheckboxShape, CheckboxSize, -} from '@/ui/input/checkbox/components/Checkbox'; +} from '@/ui/input/components/Checkbox'; import { ActivityType } from '~/generated/graphql'; const StyledEditableTitleInput = styled.input<{ diff --git a/front/src/modules/activities/tasks/components/TaskRow.tsx b/front/src/modules/activities/tasks/components/TaskRow.tsx index 3bf508df7..e91644130 100644 --- a/front/src/modules/activities/tasks/components/TaskRow.tsx +++ b/front/src/modules/activities/tasks/components/TaskRow.tsx @@ -4,10 +4,7 @@ import styled from '@emotion/styled'; import { ActivityTargetChips } from '@/activities/components/ActivityTargetChips'; import { useOpenActivityRightDrawer } from '@/activities/hooks/useOpenActivityRightDrawer'; import { IconCalendar, IconComment } from '@/ui/icon'; -import { - Checkbox, - CheckboxShape, -} from '@/ui/input/checkbox/components/Checkbox'; +import { Checkbox, CheckboxShape } from '@/ui/input/components/Checkbox'; import { OverflowingTextWithTooltip } from '@/ui/tooltip/OverflowingTextWithTooltip'; import { beautifyExactDate, hasDatePassed } from '~/utils/date-utils'; diff --git a/front/src/modules/activities/timeline/components/TimelineActivityTitle.tsx b/front/src/modules/activities/timeline/components/TimelineActivityTitle.tsx index 684866211..8a76ca1f4 100644 --- a/front/src/modules/activities/timeline/components/TimelineActivityTitle.tsx +++ b/front/src/modules/activities/timeline/components/TimelineActivityTitle.tsx @@ -1,9 +1,6 @@ import styled from '@emotion/styled'; -import { - Checkbox, - CheckboxShape, -} from '@/ui/input/checkbox/components/Checkbox'; +import { Checkbox, CheckboxShape } from '@/ui/input/components/Checkbox'; import { OverflowingTextWithTooltip } from '@/ui/tooltip/OverflowingTextWithTooltip'; import { ActivityType } from '~/generated/graphql'; diff --git a/front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx b/front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx index a04c7ff8e..b8c3f517a 100644 --- a/front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx +++ b/front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx @@ -6,7 +6,7 @@ import { motion } from 'framer-motion'; import { MainButton } from '@/ui/button/components/MainButton'; import { IconBrandGoogle } from '@/ui/icon'; -import { TextInput } from '@/ui/input/text/components/TextInput'; +import { TextInputSettings } from '@/ui/input/text/components/TextInputSettings'; import { AnimatedEaseIn } from '@/ui/utilities/animation/components/AnimatedEaseIn'; import { Logo } from '../../components/Logo'; @@ -132,7 +132,7 @@ export function SignInUpForm() { fieldState: { error }, }) => ( - ( - {isCreationDropdownOpen ? ( - - - - - ( } default: component = ( - { onRowChange({ ...row, [columnKey]: value }); diff --git a/front/src/modules/ui/input/phone/components/PhoneInputDisplay.tsx b/front/src/modules/ui/content-display/components/PhoneDisplay.tsx similarity index 91% rename from front/src/modules/ui/input/phone/components/PhoneInputDisplay.tsx rename to front/src/modules/ui/content-display/components/PhoneDisplay.tsx index 526131323..8a9488068 100644 --- a/front/src/modules/ui/input/phone/components/PhoneInputDisplay.tsx +++ b/front/src/modules/ui/content-display/components/PhoneDisplay.tsx @@ -7,7 +7,7 @@ type OwnProps = { value: string | null; }; -export function PhoneInputDisplay({ value }: OwnProps) { +export function PhoneDisplay({ value }: OwnProps) { return value && isValidPhoneNumber(value) ? ( {text}; +} diff --git a/front/src/modules/ui/input/url/components/URLTextInputDisplay.tsx b/front/src/modules/ui/content-display/components/URLDisplay.tsx similarity index 95% rename from front/src/modules/ui/input/url/components/URLTextInputDisplay.tsx rename to front/src/modules/ui/content-display/components/URLDisplay.tsx index 6902a8e43..ea5d1825f 100644 --- a/front/src/modules/ui/input/url/components/URLTextInputDisplay.tsx +++ b/front/src/modules/ui/content-display/components/URLDisplay.tsx @@ -33,7 +33,7 @@ const checkUrlType = (url: string) => { return LinkType.Url; }; -export function InplaceInputURLDisplayMode({ value }: OwnProps) { +export function URLDisplay({ value }: OwnProps) { function handleClick(event: MouseEvent) { event.stopPropagation(); } diff --git a/front/src/modules/ui/input/phone/components/__stories__/PhoneInputDisplay.stories.tsx b/front/src/modules/ui/content-display/components/__stories__/PhoneInputDisplay.stories.tsx similarity index 67% rename from front/src/modules/ui/input/phone/components/__stories__/PhoneInputDisplay.stories.tsx rename to front/src/modules/ui/content-display/components/__stories__/PhoneInputDisplay.stories.tsx index f8ce5c787..1c759c554 100644 --- a/front/src/modules/ui/input/phone/components/__stories__/PhoneInputDisplay.stories.tsx +++ b/front/src/modules/ui/content-display/components/__stories__/PhoneInputDisplay.stories.tsx @@ -2,11 +2,11 @@ import { Meta, StoryObj } from '@storybook/react'; import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator'; -import { PhoneInputDisplay } from '../PhoneInputDisplay'; // Adjust the import path as needed +import { PhoneDisplay } from '../PhoneDisplay'; // Adjust the import path as needed const meta: Meta = { title: 'UI/Input/PhoneInputDisplay', - component: PhoneInputDisplay, + component: PhoneDisplay, decorators: [ComponentWithRouterDecorator], args: { value: '+33788901234', @@ -15,6 +15,6 @@ const meta: Meta = { export default meta; -type Story = StoryObj; +type Story = StoryObj; export const Default: Story = {}; diff --git a/front/src/modules/ui/editable-field/components/EditableField.tsx b/front/src/modules/ui/editable-field/components/EditableField.tsx index 682140f73..9b520b7ca 100644 --- a/front/src/modules/ui/editable-field/components/EditableField.tsx +++ b/front/src/modules/ui/editable-field/components/EditableField.tsx @@ -83,8 +83,6 @@ type OwnProps = { isDisplayModeContentEmpty?: boolean; isDisplayModeFixHeight?: boolean; disableHoverEffect?: boolean; - onSubmit?: () => void; - onCancel?: () => void; }; export function EditableField({ @@ -99,8 +97,6 @@ export function EditableField({ displayModeContentOnly, isDisplayModeFixHeight, disableHoverEffect, - onSubmit, - onCancel, }: OwnProps) { const [isHovered, setIsHovered] = useState(false); @@ -115,10 +111,13 @@ export function EditableField({ const { isFieldInEditMode, openEditableField } = useEditableField(); function handleDisplayModeClick() { - openEditableField(customEditHotkeyScope); + if (!displayModeContentOnly) { + openEditableField(customEditHotkeyScope); + } } - const showEditButton = !isFieldInEditMode && isHovered && useEditButton; + const showEditButton = + !isFieldInEditMode && isHovered && useEditButton && !displayModeContentOnly; return ( - {isFieldInEditMode && !displayModeContentOnly ? ( - - {editModeContent} - + {isFieldInEditMode ? ( + {editModeContent} ) : ( ` align-items: center; @@ -14,28 +13,28 @@ const StyledEditableFieldEditModeContainer = styled.div` z-index: 10; `; +const StyledEditableFieldInput = styled.div` + align-items: center; + border: 1px solid ${({ theme }) => theme.border.color.medium}; + border-radius: ${({ theme }) => theme.border.radius.sm}; + display: flex; + margin-left: -1px; + min-height: 32px; + width: inherit; + + ${overlayBackground} + + z-index: 10; +`; + type OwnProps = { children: React.ReactNode; - onOutsideClick?: () => void; - onCancel?: () => void; - onSubmit?: () => void; }; -export function EditableFieldEditMode({ - children, - onCancel, - onSubmit, -}: OwnProps) { - const wrapperRef = useRef(null); - - useRegisterCloseFieldHandlers(wrapperRef, onSubmit, onCancel); - +export function EditableFieldEditMode({ children }: OwnProps) { return ( - - {children} + + {children} ); } diff --git a/front/src/modules/ui/editable-field/components/FieldDisplayURL.tsx b/front/src/modules/ui/editable-field/components/FieldDisplayURL.tsx deleted file mode 100644 index c2b9e7f02..000000000 --- a/front/src/modules/ui/editable-field/components/FieldDisplayURL.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { RoundedLink } from '@/ui/link/components/RoundedLink'; - -export function FieldDisplayURL({ URL }: { URL: string | undefined }) { - return {URL}; -} diff --git a/front/src/modules/ui/editable-field/components/GenericEditableBooleanFieldDisplayMode.tsx b/front/src/modules/ui/editable-field/components/GenericEditableBooleanFieldDisplayMode.tsx index 7c0bbf7a3..6286d6f1b 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableBooleanFieldDisplayMode.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableBooleanFieldDisplayMode.tsx @@ -1,9 +1,7 @@ import { useContext } from 'react'; -import { useTheme } from '@emotion/react'; -import styled from '@emotion/styled'; import { useRecoilState } from 'recoil'; -import { IconCheck, IconX } from '@/ui/icon'; +import { BooleanInput } from '@/ui/input/components/BooleanInput'; import { EditableFieldDefinitionContext } from '../contexts/EditableFieldDefinitionContext'; import { EditableFieldEntityIdContext } from '../contexts/EditableFieldEntityIdContext'; @@ -12,16 +10,6 @@ import { genericEntityFieldFamilySelector } from '../states/selectors/genericEnt import { FieldDefinition } from '../types/FieldDefinition'; import { FieldBooleanMetadata } from '../types/FieldMetadata'; -const StyledEditableBooleanFieldContainer = styled.div` - align-items: center; - cursor: pointer; - display: flex; -`; - -const StyledEditableBooleanFieldValue = styled.div` - margin-left: ${({ theme }) => theme.spacing(1)}; -`; - export function GenericEditableBooleanFieldDisplayMode() { const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext); const currentEditableFieldDefinition = useContext( @@ -37,32 +25,20 @@ export function GenericEditableBooleanFieldDisplayMode() { }), ); - const theme = useTheme(); const updateField = useUpdateGenericEntityField(); - function toggleValue() { - const newToggledValue = !fieldValue; - setFieldValue(newToggledValue); - + function handleSubmit(newValue: boolean) { if (currentEditableFieldEntityId && updateField) { updateField( currentEditableFieldEntityId, currentEditableFieldDefinition, - newToggledValue, + newValue, ); + + // TODO: use optimistic effect instead, but needs generic refactor + setFieldValue(newValue); } } - return ( - - {fieldValue ? ( - - ) : ( - - )} - - {fieldValue ? 'True' : 'False'} - - - ); + return ; } diff --git a/front/src/modules/ui/editable-field/components/GenericEditableDateFieldDisplayMode.tsx b/front/src/modules/ui/editable-field/components/GenericEditableDateFieldDisplayMode.tsx index 86f24bf68..1e1cb3f96 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableDateFieldDisplayMode.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableDateFieldDisplayMode.tsx @@ -1,7 +1,7 @@ import { useContext } from 'react'; import { useRecoilValue } from 'recoil'; -import { DateInputDisplay } from '@/ui/input/date/components/DateInputDisplay'; +import { DateInputDisplay } from '@/ui/input/components/DateInputDisplay'; import { parseDate } from '~/utils/date-utils'; import { EditableFieldDefinitionContext } from '../contexts/EditableFieldDefinitionContext'; diff --git a/front/src/modules/ui/editable-field/components/GenericEditablePhoneField.tsx b/front/src/modules/ui/editable-field/components/GenericEditablePhoneField.tsx index 14cd9d00c..db348c056 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditablePhoneField.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditablePhoneField.tsx @@ -1,7 +1,7 @@ import { useContext } from 'react'; import { useRecoilValue } from 'recoil'; -import { PhoneInputDisplay } from '@/ui/input/phone/components/PhoneInputDisplay'; +import { PhoneDisplay } from '@/ui/content-display/components/PhoneDisplay'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; import { EditableFieldDefinitionContext } from '../contexts/EditableFieldDefinitionContext'; @@ -35,7 +35,7 @@ export function GenericEditablePhoneField() { useEditButton IconLabel={currentEditableFieldDefinition.Icon} editModeContent={} - displayModeContent={} + displayModeContent={} isDisplayModeContentEmpty={!fieldValue} /> diff --git a/front/src/modules/ui/editable-field/components/GenericEditablePhoneFieldEditMode.tsx b/front/src/modules/ui/editable-field/components/GenericEditablePhoneFieldEditMode.tsx index 42585a0c8..b8cd216a4 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditablePhoneFieldEditMode.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditablePhoneFieldEditMode.tsx @@ -1,13 +1,15 @@ -import { useContext, useRef, useState } from 'react'; +import { useContext } from 'react'; +import { isPossiblePhoneNumber } from 'react-phone-number-input'; import { useRecoilState } from 'recoil'; -import { TextInputEdit } from '@/ui/input/text/components/TextInputEdit'; +import { PhoneInput } from '@/ui/input/components/PhoneInput'; import { EditableFieldDefinitionContext } from '../contexts/EditableFieldDefinitionContext'; import { EditableFieldEntityIdContext } from '../contexts/EditableFieldEntityIdContext'; -import { useRegisterCloseFieldHandlers } from '../hooks/useRegisterCloseFieldHandlers'; +import { useFieldInputEventHandlers } from '../hooks/useFieldInputEventHandlers'; import { useUpdateGenericEntityField } from '../hooks/useUpdateGenericEntityField'; import { genericEntityFieldFamilySelector } from '../states/selectors/genericEntityFieldFamilySelector'; +import { EditableFieldHotkeyScope } from '../types/EditableFieldHotkeyScope'; import { FieldDefinition } from '../types/FieldDefinition'; import { FieldPhoneMetadata } from '../types/FieldMetadata'; @@ -27,46 +29,34 @@ export function GenericEditablePhoneFieldEditMode() { }), ); - const [internalValue, setInternalValue] = useState(fieldValue); - const updateField = useUpdateGenericEntityField(); - const wrapperRef = useRef(null); + function handleSubmit(newValue: string) { + if (!isPossiblePhoneNumber(newValue)) return; - useRegisterCloseFieldHandlers(wrapperRef, handleSubmit, onCancel); - - function handleSubmit() { - if (internalValue === fieldValue) return; - - setFieldValue(internalValue); + setFieldValue(newValue); if (currentEditableFieldEntityId && updateField) { updateField( currentEditableFieldEntityId, currentEditableFieldDefinition, - internalValue, + newValue, ); } } - function onCancel() { - setFieldValue(fieldValue); - } - - function handleChange(newValue: string) { - setInternalValue(newValue); - } + const { handleEnter, handleEscape, handleClickOutside } = + useFieldInputEventHandlers({ + onSubmit: handleSubmit, + }); return ( -
- { - handleChange(newValue); - }} - /> -
+ ); } diff --git a/front/src/modules/ui/editable-field/components/GenericEditableTextField.tsx b/front/src/modules/ui/editable-field/components/GenericEditableTextField.tsx index 492745782..a8a7a9267 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableTextField.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableTextField.tsx @@ -1,6 +1,7 @@ import { useContext } from 'react'; import { useRecoilValue } from 'recoil'; +import { TextDisplay } from '@/ui/content-display/components/TextDisplay'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; import { EditableFieldDefinitionContext } from '../contexts/EditableFieldDefinitionContext'; @@ -33,7 +34,7 @@ export function GenericEditableTextField() { } - displayModeContent={fieldValue} + displayModeContent={} isDisplayModeContentEmpty={!fieldValue} /> diff --git a/front/src/modules/ui/editable-field/components/GenericEditableTextFieldEditMode.tsx b/front/src/modules/ui/editable-field/components/GenericEditableTextFieldEditMode.tsx index dc1c80178..f3ee487d4 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableTextFieldEditMode.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableTextFieldEditMode.tsx @@ -1,13 +1,14 @@ -import { useContext, useRef, useState } from 'react'; +import { useContext } from 'react'; import { useRecoilState } from 'recoil'; -import { TextInputEdit } from '@/ui/input/text/components/TextInputEdit'; +import { TextInput } from '@/ui/input/components/TextInput'; import { EditableFieldDefinitionContext } from '../contexts/EditableFieldDefinitionContext'; import { EditableFieldEntityIdContext } from '../contexts/EditableFieldEntityIdContext'; -import { useRegisterCloseFieldHandlers } from '../hooks/useRegisterCloseFieldHandlers'; +import { useFieldInputEventHandlers } from '../hooks/useFieldInputEventHandlers'; import { useUpdateGenericEntityField } from '../hooks/useUpdateGenericEntityField'; import { genericEntityFieldFamilySelector } from '../states/selectors/genericEntityFieldFamilySelector'; +import { EditableFieldHotkeyScope } from '../types/EditableFieldHotkeyScope'; import { FieldDefinition } from '../types/FieldDefinition'; import { FieldTextMetadata } from '../types/FieldMetadata'; @@ -27,46 +28,35 @@ export function GenericEditableTextFieldEditMode() { }), ); - const [internalValue, setInternalValue] = useState(fieldValue); - const updateField = useUpdateGenericEntityField(); - const wrapperRef = useRef(null); - - useRegisterCloseFieldHandlers(wrapperRef, handleSubmit, onCancel); - - function handleSubmit() { - if (internalValue === fieldValue) return; - - setFieldValue(internalValue); - + function handleSubmit(newValue: string) { if (currentEditableFieldEntityId && updateField) { updateField( currentEditableFieldEntityId, currentEditableFieldDefinition, - internalValue, + newValue, ); + + // TODO: use optimistic effect instead, but needs generic refactor + setFieldValue(newValue); } } - function onCancel() { - setFieldValue(fieldValue); - } - - function handleChange(newValue: string) { - setInternalValue(newValue); - } + const { handleEnter, handleEscape, handleClickOutside } = + useFieldInputEventHandlers({ + onSubmit: handleSubmit, + }); return ( -
- { - handleChange(newValue); - }} - /> -
+ ); } diff --git a/front/src/modules/ui/editable-field/components/GenericEditableURLField.tsx b/front/src/modules/ui/editable-field/components/GenericEditableURLField.tsx index b67e75d29..9ecb700f6 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableURLField.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableURLField.tsx @@ -1,6 +1,7 @@ import { useContext } from 'react'; import { useRecoilValue } from 'recoil'; +import { URLDisplay } from '@/ui/content-display/components/URLDisplay'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; import { EditableFieldDefinitionContext } from '../contexts/EditableFieldDefinitionContext'; @@ -11,7 +12,6 @@ import { FieldDefinition } from '../types/FieldDefinition'; import { FieldNumberMetadata } from '../types/FieldMetadata'; import { EditableField } from './EditableField'; -import { FieldDisplayURL } from './FieldDisplayURL'; import { GenericEditableURLFieldEditMode } from './GenericEditableURLFieldEditMode'; export function GenericEditableURLField() { @@ -35,7 +35,7 @@ export function GenericEditableURLField() { useEditButton IconLabel={currentEditableFieldDefinition.Icon} editModeContent={} - displayModeContent={} + displayModeContent={} isDisplayModeContentEmpty={!fieldValue} isDisplayModeFixHeight /> diff --git a/front/src/modules/ui/editable-field/components/GenericEditableURLFieldEditMode.tsx b/front/src/modules/ui/editable-field/components/GenericEditableURLFieldEditMode.tsx index c3f9acc38..77c97a97b 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableURLFieldEditMode.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableURLFieldEditMode.tsx @@ -1,13 +1,14 @@ -import { useContext, useRef, useState } from 'react'; +import { useContext } from 'react'; import { useRecoilState } from 'recoil'; -import { TextInputEdit } from '@/ui/input/text/components/TextInputEdit'; +import { TextInput } from '@/ui/input/components/TextInput'; import { EditableFieldDefinitionContext } from '../contexts/EditableFieldDefinitionContext'; import { EditableFieldEntityIdContext } from '../contexts/EditableFieldEntityIdContext'; -import { useRegisterCloseFieldHandlers } from '../hooks/useRegisterCloseFieldHandlers'; +import { useFieldInputEventHandlers } from '../hooks/useFieldInputEventHandlers'; import { useUpdateGenericEntityField } from '../hooks/useUpdateGenericEntityField'; import { genericEntityFieldFamilySelector } from '../states/selectors/genericEntityFieldFamilySelector'; +import { EditableFieldHotkeyScope } from '../types/EditableFieldHotkeyScope'; import { FieldDefinition } from '../types/FieldDefinition'; import { FieldURLMetadata } from '../types/FieldMetadata'; @@ -29,46 +30,34 @@ export function GenericEditableURLFieldEditMode() { }), ); - const [internalValue, setInternalValue] = useState(fieldValue); - const updateField = useUpdateGenericEntityField(); - const wrapperRef = useRef(null); - - useRegisterCloseFieldHandlers(wrapperRef, handleSubmit, onCancel); - - function handleSubmit() { - if (internalValue === fieldValue) return; - - setFieldValue(internalValue); + function handleSubmit(newValue: string) { + setFieldValue(newValue); if (currentEditableFieldEntityId && updateField) { updateField( currentEditableFieldEntityId, currentEditableFieldDefinition, - internalValue, + newValue, ); } } - function onCancel() { - setFieldValue(fieldValue); - } - - function handleChange(newValue: string) { - setInternalValue(newValue); - } + const { handleEnter, handleEscape, handleClickOutside } = + useFieldInputEventHandlers({ + onSubmit: handleSubmit, + }); return ( -
- { - handleChange(newValue); - }} - /> -
+ ); } diff --git a/front/src/modules/ui/editable-field/hooks/useFieldInputEventHandlers.ts b/front/src/modules/ui/editable-field/hooks/useFieldInputEventHandlers.ts new file mode 100644 index 000000000..cd3e19424 --- /dev/null +++ b/front/src/modules/ui/editable-field/hooks/useFieldInputEventHandlers.ts @@ -0,0 +1,28 @@ +import { useEditableField } from './useEditableField'; + +export function useFieldInputEventHandlers({ + onSubmit, + onCancel, +}: { + onSubmit?: (newValue: T) => void; + onCancel?: () => void; +}) { + const { closeEditableField, isFieldInEditMode } = useEditableField(); + + return { + handleClickOutside: (_event: MouseEvent | TouchEvent, newValue: T) => { + if (isFieldInEditMode) { + onSubmit?.(newValue); + closeEditableField(); + } + }, + handleEscape: () => { + closeEditableField(); + onCancel?.(); + }, + handleEnter: (newValue: T) => { + onSubmit?.(newValue); + closeEditableField(); + }, + }; +} diff --git a/front/src/modules/ui/editable-field/variants/components/DateEditableField.tsx b/front/src/modules/ui/editable-field/variants/components/DateEditableField.tsx index 3fe2d3455..8842c9a32 100644 --- a/front/src/modules/ui/editable-field/variants/components/DateEditableField.tsx +++ b/front/src/modules/ui/editable-field/variants/components/DateEditableField.tsx @@ -1,7 +1,7 @@ import { EditableField } from '@/ui/editable-field/components/EditableField'; import { FieldRecoilScopeContext } from '@/ui/editable-field/states/recoil-scope-contexts/FieldRecoilScopeContext'; import { IconComponent } from '@/ui/icon/types/IconComponent'; -import { DateInputDisplay } from '@/ui/input/date/components/DateInputDisplay'; +import { DateInputDisplay } from '@/ui/input/components/DateInputDisplay'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; import { parseDate } from '~/utils/date-utils'; diff --git a/front/src/modules/ui/editable-field/variants/components/EditableFieldEditModeDate.tsx b/front/src/modules/ui/editable-field/variants/components/EditableFieldEditModeDate.tsx index f01df4b4b..ade7fa343 100644 --- a/front/src/modules/ui/editable-field/variants/components/EditableFieldEditModeDate.tsx +++ b/front/src/modules/ui/editable-field/variants/components/EditableFieldEditModeDate.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react'; -import { DateInputEdit } from '@/ui/input/date/components/DateInputEdit'; +import { DateInputEdit } from '@/ui/input/components/DateInputEdit'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; import { parseDate } from '~/utils/date-utils'; diff --git a/front/src/modules/ui/editable-field/variants/components/PhoneEditableField.tsx b/front/src/modules/ui/editable-field/variants/components/PhoneEditableField.tsx deleted file mode 100644 index e7e92d0fe..000000000 --- a/front/src/modules/ui/editable-field/variants/components/PhoneEditableField.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { useEffect, useState } from 'react'; - -import { EditableField } from '@/ui/editable-field/components/EditableField'; -import { FieldRecoilScopeContext } from '@/ui/editable-field/states/recoil-scope-contexts/FieldRecoilScopeContext'; -import { IconComponent } from '@/ui/icon/types/IconComponent'; -import { PhoneInputDisplay } from '@/ui/input/phone/components/PhoneInputDisplay'; -import { TextInputEdit } from '@/ui/input/text/components/TextInputEdit'; -import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; - -type OwnProps = { - Icon?: IconComponent; - placeholder?: string; - value: string | null | undefined; - onSubmit?: (newValue: string) => void; -}; - -export function PhoneEditableField({ - Icon, - placeholder, - value, - onSubmit, -}: OwnProps) { - const [internalValue, setInternalValue] = useState(value); - - useEffect(() => { - setInternalValue(value); - }, [value]); - - async function handleChange(newValue: string) { - setInternalValue(newValue); - } - - async function handleSubmit() { - if (!internalValue) return; - - onSubmit?.(internalValue); - } - - async function handleCancel() { - setInternalValue(value); - } - - return ( - - { - handleChange(newValue); - }} - /> - } - displayModeContent={} - isDisplayModeContentEmpty={!(internalValue !== '')} - useEditButton - /> - - ); -} diff --git a/front/src/modules/ui/editable-field/variants/components/__stories__/PhoneEditableField.stories.tsx b/front/src/modules/ui/editable-field/variants/components/__stories__/PhoneEditableField.stories.tsx deleted file mode 100644 index 78d09c094..000000000 --- a/front/src/modules/ui/editable-field/variants/components/__stories__/PhoneEditableField.stories.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; - -import { IconPhone } from '@/ui/icon'; -import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator'; - -import { PhoneEditableField } from '../PhoneEditableField'; - -const meta: Meta = { - title: 'UI/EditableField/PhoneEditableField', - component: PhoneEditableField, - decorators: [ComponentWithRouterDecorator], - argTypes: { - Icon: { - type: 'boolean', - mapping: { - true: IconPhone, - false: undefined, - }, - }, - }, - args: { - value: '+33714446494', - Icon: IconPhone, - placeholder: 'Phone', - }, -}; - -export default meta; -type Story = StoryObj; - -export const Default: Story = {}; diff --git a/front/src/modules/ui/input/autosize-text/components/AutosizeTextInput.tsx b/front/src/modules/ui/input/components/AutosizeTextInput.tsx similarity index 100% rename from front/src/modules/ui/input/autosize-text/components/AutosizeTextInput.tsx rename to front/src/modules/ui/input/components/AutosizeTextInput.tsx diff --git a/front/src/modules/ui/input/components/BooleanInput.tsx b/front/src/modules/ui/input/components/BooleanInput.tsx new file mode 100644 index 000000000..c0742f6a2 --- /dev/null +++ b/front/src/modules/ui/input/components/BooleanInput.tsx @@ -0,0 +1,48 @@ +import { useEffect, useState } from 'react'; +import { useTheme } from '@emotion/react'; +import styled from '@emotion/styled'; + +import { IconCheck, IconX } from '@/ui/icon'; + +const StyledEditableBooleanFieldContainer = styled.div` + align-items: center; + cursor: pointer; + display: flex; +`; + +const StyledEditableBooleanFieldValue = styled.div` + margin-left: ${({ theme }) => theme.spacing(1)}; +`; + +type OwnProps = { + value: boolean; + onToggle?: (newValue: boolean) => void; +}; + +export function BooleanInput({ value, onToggle }: OwnProps) { + const [internalValue, setInternalValue] = useState(value); + + useEffect(() => { + setInternalValue(value); + }, [value]); + + function handleClick() { + setInternalValue(!internalValue); + onToggle?.(!internalValue); + } + + const theme = useTheme(); + + return ( + + {internalValue ? ( + + ) : ( + + )} + + {internalValue ? 'True' : 'False'} + + + ); +} diff --git a/front/src/modules/ui/input/checkbox/components/Checkbox.tsx b/front/src/modules/ui/input/components/Checkbox.tsx similarity index 100% rename from front/src/modules/ui/input/checkbox/components/Checkbox.tsx rename to front/src/modules/ui/input/components/Checkbox.tsx diff --git a/front/src/modules/ui/input/date/components/DateInputDisplay.tsx b/front/src/modules/ui/input/components/DateInputDisplay.tsx similarity index 100% rename from front/src/modules/ui/input/date/components/DateInputDisplay.tsx rename to front/src/modules/ui/input/components/DateInputDisplay.tsx diff --git a/front/src/modules/ui/input/date/components/DateInputEdit.tsx b/front/src/modules/ui/input/components/DateInputEdit.tsx similarity index 100% rename from front/src/modules/ui/input/date/components/DateInputEdit.tsx rename to front/src/modules/ui/input/components/DateInputEdit.tsx diff --git a/front/src/modules/ui/input/date/components/DatePicker.tsx b/front/src/modules/ui/input/components/DatePicker.tsx similarity index 100% rename from front/src/modules/ui/input/date/components/DatePicker.tsx rename to front/src/modules/ui/input/components/DatePicker.tsx diff --git a/front/src/modules/ui/input/double-text/components/DoubleTextInputEdit.tsx b/front/src/modules/ui/input/components/DoubleTextInputEdit.tsx similarity index 96% rename from front/src/modules/ui/input/double-text/components/DoubleTextInputEdit.tsx rename to front/src/modules/ui/input/components/DoubleTextInputEdit.tsx index af0014ed2..c06464054 100644 --- a/front/src/modules/ui/input/double-text/components/DoubleTextInputEdit.tsx +++ b/front/src/modules/ui/input/components/DoubleTextInputEdit.tsx @@ -1,7 +1,7 @@ import { ChangeEvent } from 'react'; import styled from '@emotion/styled'; -import { StyledInput } from '@/ui/table/editable-cell/type/components/TextCellEdit'; +import { StyledInput } from '@/ui/input/components/TextInput'; import { ComputeNodeDimensionsEffect } from '@/ui/utilities/dimensions/components/ComputeNodeDimensionsEffect'; export type DoubleTextInputEditProps = { diff --git a/front/src/modules/ui/input/email/components/EmailInputDisplay.tsx b/front/src/modules/ui/input/components/EmailInputDisplay.tsx similarity index 100% rename from front/src/modules/ui/input/email/components/EmailInputDisplay.tsx rename to front/src/modules/ui/input/components/EmailInputDisplay.tsx diff --git a/front/src/modules/ui/table/editable-cell/type/components/PhoneCellEdit.tsx b/front/src/modules/ui/input/components/PhoneInput.tsx similarity index 72% rename from front/src/modules/ui/table/editable-cell/type/components/PhoneCellEdit.tsx rename to front/src/modules/ui/input/components/PhoneInput.tsx index 01bb50cf0..d14113f8c 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/PhoneCellEdit.tsx +++ b/front/src/modules/ui/input/components/PhoneInput.tsx @@ -1,8 +1,8 @@ -import { useRef, useState } from 'react'; -import PhoneInput, { isPossiblePhoneNumber } from 'react-phone-number-input'; +import { useEffect, useRef, useState } from 'react'; +import ReactPhoneNumberInput from 'react-phone-number-input'; import styled from '@emotion/styled'; -import { useRegisterCloseCellHandlers } from '../../hooks/useRegisterCloseCellHandlers'; +import { useRegisterInputEvents } from '../hooks/useRegisterInputEvents'; import 'react-phone-number-input/style.css'; @@ -16,14 +16,7 @@ const StyledContainer = styled.div` justify-content: center; `; -export type PhoneCellEditProps = { - placeholder?: string; - autoFocus?: boolean; - value: string; - onSubmit: (newText: string) => void; -}; - -const StyledCustomPhoneInput = styled(PhoneInput)` +const StyledCustomPhoneInput = styled(ReactPhoneNumberInput)` --PhoneInput-color--focus: transparent; --PhoneInputCountryFlag-borderColor--focus: transparent; --PhoneInputCountrySelect-marginRight: ${({ theme }) => theme.spacing(2)}; @@ -75,25 +68,46 @@ const StyledCustomPhoneInput = styled(PhoneInput)` } `; -export function PhoneCellEdit({ +export type PhoneCellEditProps = { + placeholder?: string; + autoFocus?: boolean; + value: string; + onEnter: (newText: string) => void; + onEscape: (newText: string) => void; + onTab?: (newText: string) => void; + onShiftTab?: (newText: string) => void; + onClickOutside: (event: MouseEvent | TouchEvent, inputValue: string) => void; + hotkeyScope: string; +}; + +export function PhoneInput({ autoFocus, value, - onSubmit, + onEnter, + onEscape, + onTab, + onShiftTab, + onClickOutside, + hotkeyScope, }: PhoneCellEditProps) { const [internalValue, setInternalValue] = useState(value); const wrapperRef = useRef(null); - function handleSubmit() { - if ( - internalValue === undefined || - isPossiblePhoneNumber(internalValue ?? '') - ) { - onSubmit(internalValue ?? ''); - } - } + useEffect(() => { + setInternalValue(value); + }, [value]); - useRegisterCloseCellHandlers(wrapperRef, handleSubmit); + useRegisterInputEvents({ + inputRef: wrapperRef, + inputValue: internalValue ?? '', + onEnter, + onEscape, + onClickOutside, + onTab, + onShiftTab, + hotkeyScope, + }); return ( diff --git a/front/src/modules/ui/input/radio/components/Radio.tsx b/front/src/modules/ui/input/components/Radio.tsx similarity index 100% rename from front/src/modules/ui/input/radio/components/Radio.tsx rename to front/src/modules/ui/input/components/Radio.tsx diff --git a/front/src/modules/ui/input/radio/components/RadioGroup.tsx b/front/src/modules/ui/input/components/RadioGroup.tsx similarity index 100% rename from front/src/modules/ui/input/radio/components/RadioGroup.tsx rename to front/src/modules/ui/input/components/RadioGroup.tsx diff --git a/front/src/modules/ui/table/editable-cell/type/components/TextCellEdit.tsx b/front/src/modules/ui/input/components/TextInput.tsx similarity index 58% rename from front/src/modules/ui/table/editable-cell/type/components/TextCellEdit.tsx rename to front/src/modules/ui/input/components/TextInput.tsx index cca2d17b7..2b5e1b0eb 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/TextCellEdit.tsx +++ b/front/src/modules/ui/input/components/TextInput.tsx @@ -3,7 +3,7 @@ import styled from '@emotion/styled'; import { textInputStyle } from '@/ui/theme/constants/effects'; -import { useRegisterCloseCellHandlers } from '../../hooks/useRegisterCloseCellHandlers'; +import { useRegisterInputEvents } from '../hooks/useRegisterInputEvents'; export const StyledInput = styled.input` margin: 0; @@ -15,27 +15,29 @@ type OwnProps = { placeholder?: string; autoFocus?: boolean; value: string; - onSubmit: (newText: string) => void; + onEnter: (newText: string) => void; + onEscape: (newText: string) => void; + onTab?: (newText: string) => void; + onShiftTab?: (newText: string) => void; + onClickOutside: (event: MouseEvent | TouchEvent, inputValue: string) => void; + hotkeyScope: string; }; -export function TextCellEdit({ +export function TextInput({ placeholder, autoFocus, value, - onSubmit, + hotkeyScope, + onEnter, + onEscape, + onTab, + onShiftTab, + onClickOutside, }: OwnProps) { const [internalText, setInternalText] = useState(value); const wrapperRef = useRef(null); - function handleSubmit() { - onSubmit(internalText); - } - - function handleCancel() { - setInternalText(value); - } - function handleChange(event: ChangeEvent) { setInternalText(event.target.value); } @@ -44,7 +46,16 @@ export function TextCellEdit({ setInternalText(value); }, [value]); - useRegisterCloseCellHandlers(wrapperRef, handleSubmit, handleCancel); + useRegisterInputEvents({ + inputRef: wrapperRef, + inputValue: internalText, + onEnter, + onEscape, + onClickOutside, + onTab, + onShiftTab, + hotkeyScope, + }); return ( ({ + inputRef, + inputValue, + onEscape, + onEnter, + onTab, + onShiftTab, + onClickOutside, + hotkeyScope, +}: { + inputRef: React.RefObject; + inputValue: T; + onEscape: (inputValue: T) => void; + onEnter: (inputValue: T) => void; + onTab?: (inputValue: T) => void; + onShiftTab?: (inputValue: T) => void; + onClickOutside?: (event: MouseEvent | TouchEvent, inputValue: T) => void; + hotkeyScope: string; +}) { + useListenClickOutside({ + refs: [inputRef], + callback: (event) => { + onClickOutside?.(event, inputValue); + }, + enabled: isDefined(onClickOutside), + }); + + useScopedHotkeys( + 'enter', + () => { + onEnter?.(inputValue); + }, + hotkeyScope, + [onEnter, inputValue], + ); + + useScopedHotkeys( + 'esc', + () => { + onEscape?.(inputValue); + }, + hotkeyScope, + [onEscape, inputValue], + ); + + useScopedHotkeys( + 'tab', + () => { + onTab?.(inputValue); + }, + hotkeyScope, + [onTab, inputValue], + ); + + useScopedHotkeys( + 'shift+tab', + () => { + onShiftTab?.(inputValue); + }, + hotkeyScope, + [onShiftTab, inputValue], + ); +} diff --git a/front/src/modules/ui/input/text/components/TextInputDisplay.tsx b/front/src/modules/ui/input/text/components/TextInputDisplay.tsx deleted file mode 100644 index a88132d55..000000000 --- a/front/src/modules/ui/input/text/components/TextInputDisplay.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import styled from '@emotion/styled'; - -const StyledTextInputDisplay = styled.div` - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - width: 100%; -`; - -export type TextInputDisplayProps = { - children: React.ReactNode; -}; - -export function TextInputDisplay({ children }: TextInputDisplayProps) { - return {children}; -} diff --git a/front/src/modules/ui/input/text/components/TextInput.tsx b/front/src/modules/ui/input/text/components/TextInputSettings.tsx similarity index 98% rename from front/src/modules/ui/input/text/components/TextInput.tsx rename to front/src/modules/ui/input/text/components/TextInputSettings.tsx index e8c375826..dcfe40ec0 100644 --- a/front/src/modules/ui/input/text/components/TextInput.tsx +++ b/front/src/modules/ui/input/text/components/TextInputSettings.tsx @@ -197,4 +197,4 @@ function TextInputComponent( ); } -export const TextInput = forwardRef(TextInputComponent); +export const TextInputSettings = forwardRef(TextInputComponent); diff --git a/front/src/modules/ui/input/text/components/__stories__/TextInput.stories.tsx b/front/src/modules/ui/input/text/components/__stories__/TextInput.stories.tsx index 2acf3ab44..573f791db 100644 --- a/front/src/modules/ui/input/text/components/__stories__/TextInput.stories.tsx +++ b/front/src/modules/ui/input/text/components/__stories__/TextInput.stories.tsx @@ -6,28 +6,28 @@ import { userEvent, within } from '@storybook/testing-library'; import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator'; -import { TextInput } from '../TextInput'; +import { TextInputSettings } from '../TextInputSettings'; const changeJestFn = jest.fn(); -const meta: Meta = { +const meta: Meta = { title: 'UI/Input/TextInput', - component: TextInput, + component: TextInputSettings, decorators: [ComponentDecorator], args: { value: '', onChange: changeJestFn, placeholder: 'Placeholder' }, }; export default meta; -type Story = StoryObj; +type Story = StoryObj; function FakeTextInput({ onChange, value: initialValue, ...props -}: React.ComponentProps) { +}: React.ComponentProps) { const [value, setValue] = useState(initialValue); return ( - { diff --git a/front/src/modules/ui/menu-item/components/MenuItemMultiSelect.tsx b/front/src/modules/ui/menu-item/components/MenuItemMultiSelect.tsx index c8940ff11..be7ba1551 100644 --- a/front/src/modules/ui/menu-item/components/MenuItemMultiSelect.tsx +++ b/front/src/modules/ui/menu-item/components/MenuItemMultiSelect.tsx @@ -1,7 +1,7 @@ import styled from '@emotion/styled'; import { IconComponent } from '@/ui/icon/types/IconComponent'; -import { Checkbox } from '@/ui/input/checkbox/components/Checkbox'; +import { Checkbox } from '@/ui/input/components/Checkbox'; import { MenuItemLeftContent } from '../internals/components/MenuItemLeftContent'; import { StyledMenuItemBase } from '../internals/components/StyledMenuItemBase'; diff --git a/front/src/modules/ui/menu-item/components/MenuItemMultiSelectAvatar.tsx b/front/src/modules/ui/menu-item/components/MenuItemMultiSelectAvatar.tsx index 03f09e9b7..44a4e40cd 100644 --- a/front/src/modules/ui/menu-item/components/MenuItemMultiSelectAvatar.tsx +++ b/front/src/modules/ui/menu-item/components/MenuItemMultiSelectAvatar.tsx @@ -1,7 +1,7 @@ import { ReactNode } from 'react'; import styled from '@emotion/styled'; -import { Checkbox } from '@/ui/input/checkbox/components/Checkbox'; +import { Checkbox } from '@/ui/input/components/Checkbox'; import { StyledMenuItemBase, diff --git a/front/src/modules/ui/menu-item/components/MenuItemToggle.tsx b/front/src/modules/ui/menu-item/components/MenuItemToggle.tsx index b742edb87..be09bbc83 100644 --- a/front/src/modules/ui/menu-item/components/MenuItemToggle.tsx +++ b/front/src/modules/ui/menu-item/components/MenuItemToggle.tsx @@ -1,5 +1,5 @@ import { IconComponent } from '@/ui/icon/types/IconComponent'; -import { Toggle } from '@/ui/input/toggle/components/Toggle'; +import { Toggle } from '@/ui/input/components/Toggle'; import { MenuItemLeftContent } from '../internals/components/MenuItemLeftContent'; import { StyledMenuItemBase } from '../internals/components/StyledMenuItemBase'; diff --git a/front/src/modules/ui/modal/components/ConfirmationModal.tsx b/front/src/modules/ui/modal/components/ConfirmationModal.tsx index e8936ba3c..33a817220 100644 --- a/front/src/modules/ui/modal/components/ConfirmationModal.tsx +++ b/front/src/modules/ui/modal/components/ConfirmationModal.tsx @@ -4,7 +4,7 @@ import { AnimatePresence, LayoutGroup } from 'framer-motion'; import debounce from 'lodash.debounce'; import { Button } from '@/ui/button/components/Button'; -import { TextInput } from '@/ui/input/text/components/TextInput'; +import { TextInputSettings } from '@/ui/input/text/components/TextInputSettings'; import { Modal } from '@/ui/modal/components/Modal'; import { Section, @@ -99,7 +99,7 @@ export function ConfirmationModal({ {confirmationValue && (
- ; diff --git a/front/src/modules/ui/table/editable-cell/type/components/DateCellEdit.tsx b/front/src/modules/ui/table/editable-cell/type/components/DateCellEdit.tsx index 9efd263ee..80d43e16b 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/DateCellEdit.tsx +++ b/front/src/modules/ui/table/editable-cell/type/components/DateCellEdit.tsx @@ -2,7 +2,7 @@ import { useRef } from 'react'; import styled from '@emotion/styled'; import { Key } from 'ts-key-enum'; -import { DateInputEdit } from '@/ui/input/date/components/DateInputEdit'; +import { DateInputEdit } from '@/ui/input/components/DateInputEdit'; import { TableHotkeyScope } from '@/ui/table/types/TableHotkeyScope'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; diff --git a/front/src/modules/ui/table/editable-cell/type/components/DoubleTextCellEdit.tsx b/front/src/modules/ui/table/editable-cell/type/components/DoubleTextCellEdit.tsx index 036b641c1..daffb83ea 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/DoubleTextCellEdit.tsx +++ b/front/src/modules/ui/table/editable-cell/type/components/DoubleTextCellEdit.tsx @@ -6,11 +6,10 @@ import { useMoveSoftFocus } from '@/ui/table/hooks/useMoveSoftFocus'; import { TableHotkeyScope } from '@/ui/table/types/TableHotkeyScope'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; +import { StyledInput } from '../../../../input/components/TextInput'; import { useEditableCell } from '../../hooks/useEditableCell'; import { useRegisterCloseCellHandlers } from '../../hooks/useRegisterCloseCellHandlers'; -import { StyledInput } from './TextCellEdit'; - type OwnProps = { firstValue: string; secondValue: string; diff --git a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableBooleanCell.tsx b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableBooleanCell.tsx index e31401e25..d77c54968 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableBooleanCell.tsx +++ b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableBooleanCell.tsx @@ -2,13 +2,13 @@ import styled from '@emotion/styled'; import { useRecoilState } from 'recoil'; import type { ViewFieldBooleanMetadata } from '@/ui/editable-field/types/ViewField'; -import { IconCheck, IconX } from '@/ui/icon'; +import { BooleanInput } from '@/ui/input/components/BooleanInput'; import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId'; import { useUpdateEntityField } from '@/ui/table/hooks/useUpdateEntityField'; import { tableEntityFieldFamilySelector } from '@/ui/table/states/selectors/tableEntityFieldFamilySelector'; import type { ColumnDefinition } from '../../../types/ColumnDefinition'; -import { EditableCellDisplayContainer } from '../../components/EditableCellContainer'; +import { EditableCellDisplayContainer } from '../../components/EditableCellDisplayContainer'; type OwnProps = { columnDefinition: ColumnDefinition; @@ -26,14 +26,6 @@ const StyledCellBaseContainer = styled.div` width: 100%; `; -const StyledCellBooleancontainer = styled.div` - margin-left: 5px; -`; - -function capitalizeFirstLetter(value: string) { - return value.charAt(0).toUpperCase() + value.slice(1); -} - export function GenericEditableBooleanCell({ columnDefinition }: OwnProps) { const currentRowEntityId = useCurrentRowEntityId(); @@ -48,6 +40,7 @@ export function GenericEditableBooleanCell({ columnDefinition }: OwnProps) { function handleClick() { const newValue = !fieldValue; + try { setFieldValue(newValue); @@ -64,11 +57,7 @@ export function GenericEditableBooleanCell({ columnDefinition }: OwnProps) { return ( - {fieldValue ? : } - - {fieldValue !== undefined && - capitalizeFirstLetter(fieldValue.toString())} - + ); diff --git a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableChipCellEditMode.tsx b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableChipCellEditMode.tsx index 10937a8c3..62e02762e 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableChipCellEditMode.tsx +++ b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableChipCellEditMode.tsx @@ -1,14 +1,15 @@ import { useRecoilState } from 'recoil'; import type { ViewFieldChipMetadata } from '@/ui/editable-field/types/ViewField'; +import { useCellInputEventHandlers } from '@/ui/table/hooks/useCellInputEventHandlers'; import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId'; import { useUpdateEntityField } from '@/ui/table/hooks/useUpdateEntityField'; import { tableEntityFieldFamilySelector } from '@/ui/table/states/selectors/tableEntityFieldFamilySelector'; +import { TableHotkeyScope } from '@/ui/table/types/TableHotkeyScope'; +import { TextInput } from '../../../../input/components/TextInput'; import type { ColumnDefinition } from '../../../types/ColumnDefinition'; -import { TextCellEdit } from './TextCellEdit'; - type OwnProps = { columnDefinition: ColumnDefinition; }; @@ -38,12 +39,27 @@ export function GenericEditableChipCellEditMode({ } } + const { + handleEnter, + handleEscape, + handleTab, + handleShiftTab, + handleClickOutside, + } = useCellInputEventHandlers({ + onSubmit: handleSubmit, + }); + return ( - ); } diff --git a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableDateCell.tsx b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableDateCell.tsx index f33b1d5e3..33dc1ee51 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableDateCell.tsx +++ b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableDateCell.tsx @@ -1,7 +1,7 @@ import { useRecoilValue } from 'recoil'; import type { ViewFieldDateMetadata } from '@/ui/editable-field/types/ViewField'; -import { DateInputDisplay } from '@/ui/input/date/components/DateInputDisplay'; +import { DateInputDisplay } from '@/ui/input/components/DateInputDisplay'; import { EditableCell } from '@/ui/table/editable-cell/components/EditableCell'; import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId'; import { tableEntityFieldFamilySelector } from '@/ui/table/states/selectors/tableEntityFieldFamilySelector'; diff --git a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableDoubleTextCell.tsx b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableDoubleTextCell.tsx index 23a78101d..0d051f24e 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableDoubleTextCell.tsx +++ b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableDoubleTextCell.tsx @@ -1,7 +1,7 @@ import { useRecoilValue } from 'recoil'; +import { TextDisplay } from '@/ui/content-display/components/TextDisplay'; import type { ViewFieldDoubleTextMetadata } from '@/ui/editable-field/types/ViewField'; -import { TextInputDisplay } from '@/ui/input/text/components/TextInputDisplay'; import { EditableCell } from '@/ui/table/editable-cell/components/EditableCell'; import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId'; import { tableEntityFieldFamilySelector } from '@/ui/table/states/selectors/tableEntityFieldFamilySelector'; @@ -40,7 +40,7 @@ export function GenericEditableDoubleTextCell({ columnDefinition }: OwnProps) { columnDefinition={columnDefinition} /> } - nonEditModeContent={{displayName}} + nonEditModeContent={} > ); } diff --git a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableEmailCell.tsx b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableEmailCell.tsx index 239245295..7d2ce4541 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableEmailCell.tsx +++ b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableEmailCell.tsx @@ -1,7 +1,7 @@ import { useRecoilValue } from 'recoil'; import type { ViewFieldEmailMetadata } from '@/ui/editable-field/types/ViewField'; -import { EmailInputDisplay } from '@/ui/input/email/components/EmailInputDisplay'; +import { EmailInputDisplay } from '@/ui/input/components/EmailInputDisplay'; import { EditableCell } from '@/ui/table/editable-cell/components/EditableCell'; import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId'; import { tableEntityFieldFamilySelector } from '@/ui/table/states/selectors/tableEntityFieldFamilySelector'; diff --git a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableEmailCellEditMode.tsx b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableEmailCellEditMode.tsx index 3458f8bd6..bdaef73b8 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableEmailCellEditMode.tsx +++ b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableEmailCellEditMode.tsx @@ -1,14 +1,15 @@ import { useRecoilState } from 'recoil'; import type { ViewFieldEmailMetadata } from '@/ui/editable-field/types/ViewField'; +import { useCellInputEventHandlers } from '@/ui/table/hooks/useCellInputEventHandlers'; import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId'; import { useUpdateEntityField } from '@/ui/table/hooks/useUpdateEntityField'; import { tableEntityFieldFamilySelector } from '@/ui/table/states/selectors/tableEntityFieldFamilySelector'; +import { TableHotkeyScope } from '@/ui/table/types/TableHotkeyScope'; +import { TextInput } from '../../../../input/components/TextInput'; import type { ColumnDefinition } from '../../../types/ColumnDefinition'; -import { TextCellEdit } from './TextCellEdit'; - type OwnProps = { columnDefinition: ColumnDefinition; }; @@ -38,12 +39,27 @@ export function GenericEditableEmailCellEditMode({ } } + const { + handleEnter, + handleEscape, + handleTab, + handleShiftTab, + handleClickOutside, + } = useCellInputEventHandlers({ + onSubmit: handleSubmit, + }); + return ( - ); } diff --git a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableMoneyCellEditMode.tsx b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableMoneyCellEditMode.tsx index d136f4b20..e523bcbfe 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableMoneyCellEditMode.tsx +++ b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableMoneyCellEditMode.tsx @@ -1,14 +1,15 @@ import { useRecoilState } from 'recoil'; import type { ViewFieldMoneyMetadata } from '@/ui/editable-field/types/ViewField'; +import { useCellInputEventHandlers } from '@/ui/table/hooks/useCellInputEventHandlers'; import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId'; import { useUpdateEntityField } from '@/ui/table/hooks/useUpdateEntityField'; import { tableEntityFieldFamilySelector } from '@/ui/table/states/selectors/tableEntityFieldFamilySelector'; +import { TableHotkeyScope } from '@/ui/table/types/TableHotkeyScope'; +import { TextInput } from '../../../../input/components/TextInput'; import type { ColumnDefinition } from '../../../types/ColumnDefinition'; -import { TextCellEdit } from './TextCellEdit'; - type OwnProps = { columnDefinition: ColumnDefinition; }; @@ -53,7 +54,26 @@ export function GenericEditableMoneyCellEditMode({ } } + const { + handleEnter, + handleEscape, + handleTab, + handleShiftTab, + handleClickOutside, + } = useCellInputEventHandlers({ + onSubmit: handleSubmit, + }); + return ( - + ); } diff --git a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableNumberCellEditMode.tsx b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableNumberCellEditMode.tsx index 38bb8b501..2093bc969 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableNumberCellEditMode.tsx +++ b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableNumberCellEditMode.tsx @@ -1,18 +1,19 @@ import { useRecoilState } from 'recoil'; import type { ViewFieldNumberMetadata } from '@/ui/editable-field/types/ViewField'; +import { useCellInputEventHandlers } from '@/ui/table/hooks/useCellInputEventHandlers'; import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId'; import { useUpdateEntityField } from '@/ui/table/hooks/useUpdateEntityField'; import { tableEntityFieldFamilySelector } from '@/ui/table/states/selectors/tableEntityFieldFamilySelector'; +import { TableHotkeyScope } from '@/ui/table/types/TableHotkeyScope'; import { canBeCastAsPositiveIntegerOrNull, castAsPositiveIntegerOrNull, } from '~/utils/cast-as-positive-integer-or-null'; +import { TextInput } from '../../../../input/components/TextInput'; import type { ColumnDefinition } from '../../../types/ColumnDefinition'; -import { TextCellEdit } from './TextCellEdit'; - type OwnProps = { columnDefinition: ColumnDefinition; }; @@ -74,7 +75,26 @@ export function GenericEditableNumberCellEditMode({ } } + const { + handleEnter, + handleEscape, + handleTab, + handleShiftTab, + handleClickOutside, + } = useCellInputEventHandlers({ + onSubmit: handleSubmit, + }); + return ( - + ); } diff --git a/front/src/modules/ui/table/editable-cell/type/components/GenericEditablePhoneCell.tsx b/front/src/modules/ui/table/editable-cell/type/components/GenericEditablePhoneCell.tsx index cbc8af6f5..0a3658e38 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/GenericEditablePhoneCell.tsx +++ b/front/src/modules/ui/table/editable-cell/type/components/GenericEditablePhoneCell.tsx @@ -1,7 +1,7 @@ import { useRecoilValue } from 'recoil'; -import type { ViewFieldPhoneMetadata } from '@/ui/editable-field/types/ViewField'; -import { PhoneInputDisplay } from '@/ui/input/phone/components/PhoneInputDisplay'; +import { PhoneDisplay } from '@/ui/content-display/components/PhoneDisplay'; +import { ViewFieldPhoneMetadata } from '@/ui/editable-field/types/ViewField'; import { EditableCell } from '@/ui/table/editable-cell/components/EditableCell'; import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId'; import { tableEntityFieldFamilySelector } from '@/ui/table/states/selectors/tableEntityFieldFamilySelector'; @@ -35,7 +35,7 @@ export function GenericEditablePhoneCell({ editModeContent={ } - nonEditModeContent={} + nonEditModeContent={} > ); } diff --git a/front/src/modules/ui/table/editable-cell/type/components/GenericEditablePhoneCellEditMode.tsx b/front/src/modules/ui/table/editable-cell/type/components/GenericEditablePhoneCellEditMode.tsx index 071cd42b7..9c3700b8c 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/GenericEditablePhoneCellEditMode.tsx +++ b/front/src/modules/ui/table/editable-cell/type/components/GenericEditablePhoneCellEditMode.tsx @@ -1,14 +1,16 @@ +import { isPossiblePhoneNumber } from 'libphonenumber-js'; import { useRecoilState } from 'recoil'; import type { ViewFieldPhoneMetadata } from '@/ui/editable-field/types/ViewField'; +import { useCellInputEventHandlers } from '@/ui/table/hooks/useCellInputEventHandlers'; import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId'; import { useUpdateEntityField } from '@/ui/table/hooks/useUpdateEntityField'; import { tableEntityFieldFamilySelector } from '@/ui/table/states/selectors/tableEntityFieldFamilySelector'; +import { TableHotkeyScope } from '@/ui/table/types/TableHotkeyScope'; +import { PhoneInput } from '../../../../input/components/PhoneInput'; import type { ColumnDefinition } from '../../../types/ColumnDefinition'; -import { PhoneCellEdit } from './PhoneCellEdit'; - type OwnProps = { columnDefinition: ColumnDefinition; }; @@ -28,22 +30,39 @@ export function GenericEditablePhoneCellEditMode({ const updateField = useUpdateEntityField(); - function handleSubmit(newText: string) { - if (newText === fieldValue) return; + function handleSubmit(newValue: string) { + if (!isPossiblePhoneNumber(newValue)) return; - setFieldValue(newText); + if (newValue === fieldValue) return; + + setFieldValue(newValue); if (currentRowEntityId && updateField) { - updateField(currentRowEntityId, columnDefinition, newText); + updateField(currentRowEntityId, columnDefinition, newValue); } } + const { + handleEnter, + handleEscape, + handleTab, + handleShiftTab, + handleClickOutside, + } = useCellInputEventHandlers({ + onSubmit: handleSubmit, + }); + return ( - ); } diff --git a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableTextCell.tsx b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableTextCell.tsx index 50d3ea35b..34f471240 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableTextCell.tsx +++ b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableTextCell.tsx @@ -1,7 +1,7 @@ import { useRecoilValue } from 'recoil'; +import { TextDisplay } from '@/ui/content-display/components/TextDisplay'; import type { ViewFieldTextMetadata } from '@/ui/editable-field/types/ViewField'; -import { TextInputDisplay } from '@/ui/input/text/components/TextInputDisplay'; import { EditableCell } from '@/ui/table/editable-cell/components/EditableCell'; import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId'; import { tableEntityFieldFamilySelector } from '@/ui/table/states/selectors/tableEntityFieldFamilySelector'; @@ -34,7 +34,7 @@ export function GenericEditableTextCell({ editModeContent={ } - nonEditModeContent={{fieldValue}} + nonEditModeContent={} > ); } diff --git a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableTextCellEditMode.tsx b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableTextCellEditMode.tsx index 9e000375e..70f6c3568 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableTextCellEditMode.tsx +++ b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableTextCellEditMode.tsx @@ -1,14 +1,15 @@ import { useRecoilState } from 'recoil'; import type { ViewFieldTextMetadata } from '@/ui/editable-field/types/ViewField'; +import { useCellInputEventHandlers } from '@/ui/table/hooks/useCellInputEventHandlers'; import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId'; import { useUpdateEntityField } from '@/ui/table/hooks/useUpdateEntityField'; import { tableEntityFieldFamilySelector } from '@/ui/table/states/selectors/tableEntityFieldFamilySelector'; +import { TableHotkeyScope } from '@/ui/table/types/TableHotkeyScope'; +import { TextInput } from '../../../../input/components/TextInput'; import type { ColumnDefinition } from '../../../types/ColumnDefinition'; -import { TextCellEdit } from './TextCellEdit'; - type OwnProps = { columnDefinition: ColumnDefinition; }; @@ -38,12 +39,27 @@ export function GenericEditableTextCellEditMode({ } } + const { + handleEnter, + handleEscape, + handleTab, + handleShiftTab, + handleClickOutside, + } = useCellInputEventHandlers({ + onSubmit: handleSubmit, + }); + return ( - ); } diff --git a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableURLCell.tsx b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableURLCell.tsx index 90ddb1325..fdd7a0e6d 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableURLCell.tsx +++ b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableURLCell.tsx @@ -1,7 +1,7 @@ import { useRecoilValue } from 'recoil'; +import { URLDisplay } from '@/ui/content-display/components/URLDisplay'; import type { ViewFieldURLMetadata } from '@/ui/editable-field/types/ViewField'; -import { InplaceInputURLDisplayMode } from '@/ui/input/url/components/URLTextInputDisplay'; import { EditableCell } from '@/ui/table/editable-cell/components/EditableCell'; import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId'; import { tableEntityFieldFamilySelector } from '@/ui/table/states/selectors/tableEntityFieldFamilySelector'; @@ -36,9 +36,7 @@ export function GenericEditableURLCell({ editModeContent={ } - nonEditModeContent={ - - } + nonEditModeContent={} > ); } diff --git a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableURLCellEditMode.tsx b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableURLCellEditMode.tsx index 6803202d0..4e807a133 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableURLCellEditMode.tsx +++ b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableURLCellEditMode.tsx @@ -1,15 +1,16 @@ import { useRecoilState } from 'recoil'; import type { ViewFieldURLMetadata } from '@/ui/editable-field/types/ViewField'; +import { useCellInputEventHandlers } from '@/ui/table/hooks/useCellInputEventHandlers'; import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId'; import { useUpdateEntityField } from '@/ui/table/hooks/useUpdateEntityField'; import { tableEntityFieldFamilySelector } from '@/ui/table/states/selectors/tableEntityFieldFamilySelector'; +import { TableHotkeyScope } from '@/ui/table/types/TableHotkeyScope'; import { isURL } from '~/utils/is-url'; +import { TextInput } from '../../../../input/components/TextInput'; import type { ColumnDefinition } from '../../../types/ColumnDefinition'; -import { TextCellEdit } from './TextCellEdit'; - type OwnProps = { columnDefinition: ColumnDefinition; }; @@ -39,12 +40,27 @@ export function GenericEditableURLCellEditMode({ columnDefinition }: OwnProps) { } } + const { + handleEnter, + handleEscape, + handleTab, + handleShiftTab, + handleClickOutside, + } = useCellInputEventHandlers({ + onSubmit: handleSubmit, + }); + return ( - ); } diff --git a/front/src/modules/ui/table/editable-cell/type/components/__stories__/PhoneCellEdit.stories.tsx b/front/src/modules/ui/table/editable-cell/type/components/__stories__/PhoneCellEdit.stories.tsx index d7a223d36..30e0d33be 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/__stories__/PhoneCellEdit.stories.tsx +++ b/front/src/modules/ui/table/editable-cell/type/components/__stories__/PhoneCellEdit.stories.tsx @@ -1,12 +1,12 @@ import type { Meta, StoryObj } from '@storybook/react'; -import { PhoneCellEdit } from '@/ui/table/editable-cell/type/components/PhoneCellEdit'; +import { PhoneInput } from '@/ui/input/components/PhoneInput'; import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext'; import { ComponentWithRecoilScopeDecorator } from '~/testing/decorators/ComponentWithRecoilScopeDecorator'; -const meta: Meta = { +const meta: Meta = { title: 'UI/Table/EditableCell/PhoneCellEdit', - component: PhoneCellEdit, + component: PhoneInput, decorators: [ComponentWithRecoilScopeDecorator], args: { value: '+33714446494', @@ -18,6 +18,6 @@ const meta: Meta = { }; export default meta; -type Story = StoryObj; +type Story = StoryObj; export const Default: Story = {}; diff --git a/front/src/modules/ui/table/hooks/useCellInputEventHandlers.ts b/front/src/modules/ui/table/hooks/useCellInputEventHandlers.ts new file mode 100644 index 000000000..739058601 --- /dev/null +++ b/front/src/modules/ui/table/hooks/useCellInputEventHandlers.ts @@ -0,0 +1,47 @@ +import { useCurrentCellEditMode } from '../editable-cell/hooks/useCurrentCellEditMode'; +import { useEditableCell } from '../editable-cell/hooks/useEditableCell'; + +import { useMoveSoftFocus } from './useMoveSoftFocus'; + +export function useCellInputEventHandlers({ + onSubmit, + onCancel, +}: { + onSubmit?: (newValue: T) => void; + onCancel?: () => void; +}) { + const { closeEditableCell } = useEditableCell(); + const { isCurrentCellInEditMode } = useCurrentCellEditMode(); + const { moveRight, moveLeft, moveDown } = useMoveSoftFocus(); + + return { + handleClickOutside: (event: MouseEvent | TouchEvent, newValue: T) => { + if (isCurrentCellInEditMode) { + event.stopImmediatePropagation(); + + onSubmit?.(newValue); + + closeEditableCell(); + } + }, + handleEscape: () => { + closeEditableCell(); + onCancel?.(); + }, + handleEnter: (newValue: T) => { + onSubmit?.(newValue); + closeEditableCell(); + moveDown(); + }, + handleTab: (newValue: T) => { + onSubmit?.(newValue); + closeEditableCell(); + moveRight(); + }, + handleShiftTab: (newValue: T) => { + onSubmit?.(newValue); + closeEditableCell(); + moveLeft(); + }, + }; +} diff --git a/front/src/modules/ui/utilities/pointer-event/hooks/useListenClickOutside.ts b/front/src/modules/ui/utilities/pointer-event/hooks/useListenClickOutside.ts index f53bbf365..951162aa0 100644 --- a/front/src/modules/ui/utilities/pointer-event/hooks/useListenClickOutside.ts +++ b/front/src/modules/ui/utilities/pointer-event/hooks/useListenClickOutside.ts @@ -9,10 +9,12 @@ export function useListenClickOutside({ refs, callback, mode = ClickOutsideMode.dom, + enabled = true, }: { refs: Array>; callback: (event: MouseEvent | TouchEvent) => void; mode?: ClickOutsideMode; + enabled?: boolean; }) { useEffect(() => { function handleClickOutside(event: MouseEvent | TouchEvent) { @@ -61,20 +63,22 @@ export function useListenClickOutside({ } } - document.addEventListener('click', handleClickOutside, { capture: true }); - document.addEventListener('touchend', handleClickOutside, { - capture: true, - }); + if (enabled) { + document.addEventListener('click', handleClickOutside, { capture: true }); + document.addEventListener('touchend', handleClickOutside, { + capture: true, + }); - return () => { - document.removeEventListener('click', handleClickOutside, { - capture: true, - }); - document.removeEventListener('touchend', handleClickOutside, { - capture: true, - }); - }; - }, [refs, callback, mode]); + return () => { + document.removeEventListener('click', handleClickOutside, { + capture: true, + }); + document.removeEventListener('touchend', handleClickOutside, { + capture: true, + }); + }; + } + }, [refs, callback, mode, enabled]); } export const useListenClickOutsideByClassName = ({ classNames, diff --git a/front/src/modules/ui/view-bar/components/FilterDropdownDateSearchInput.tsx b/front/src/modules/ui/view-bar/components/FilterDropdownDateSearchInput.tsx index 00d1abf04..88682ffd2 100644 --- a/front/src/modules/ui/view-bar/components/FilterDropdownDateSearchInput.tsx +++ b/front/src/modules/ui/view-bar/components/FilterDropdownDateSearchInput.tsx @@ -1,7 +1,7 @@ import { Context } from 'react'; import styled from '@emotion/styled'; -import DatePicker from '@/ui/input/date/components/DatePicker'; +import DatePicker from '@/ui/input/components/DatePicker'; import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; import { useUpsertFilter } from '@/ui/view-bar/hooks/useUpsertFilter'; import { filterDefinitionUsedInDropdownScopedState } from '@/ui/view-bar/states/filterDefinitionUsedInDropdownScopedState'; diff --git a/front/src/modules/workspace/components/WorkspaceInviteLink.tsx b/front/src/modules/workspace/components/WorkspaceInviteLink.tsx index 023d5dd4c..56c54b41e 100644 --- a/front/src/modules/workspace/components/WorkspaceInviteLink.tsx +++ b/front/src/modules/workspace/components/WorkspaceInviteLink.tsx @@ -3,7 +3,7 @@ import styled from '@emotion/styled'; import { Button } from '@/ui/button/components/Button'; import { IconCopy, IconLink } from '@/ui/icon'; -import { TextInput } from '@/ui/input/text/components/TextInput'; +import { TextInputSettings } from '@/ui/input/text/components/TextInputSettings'; import { useSnackBar } from '@/ui/snack-bar/hooks/useSnackBar'; const StyledContainer = styled.div` @@ -29,7 +29,7 @@ export function WorkspaceInviteLink({ inviteLink }: OwnProps) { return ( - +