Rework tel input (#1316)

* Rework tel input

* Fix lint
This commit is contained in:
Charles Bochet
2023-08-25 20:54:00 +02:00
committed by GitHub
parent 4f7e1fb60e
commit 67cf6cd7e2
10 changed files with 127 additions and 226 deletions

View File

@ -1,22 +1,14 @@
import { BrowserRouter } from 'react-router-dom';
import type { Meta, StoryObj } from '@storybook/react';
import { IconPhone } from '@tabler/icons-react';
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
import { PhoneEditableField } from '../PhoneEditableField';
const meta: Meta<typeof PhoneEditableField> = {
title: 'UI/EditableField/PhoneEditableField',
component: PhoneEditableField,
decorators: [
(Story) => (
<BrowserRouter>
<Story />
</BrowserRouter>
),
ComponentDecorator,
],
decorators: [ComponentWithRouterDecorator],
argTypes: {
icon: {
type: 'boolean',

View File

@ -1,25 +1,13 @@
import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import styled from '@emotion/styled';
import { Meta, StoryObj } from '@storybook/react';
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
import { EmailInputDisplay } from '../EmailInputDisplay';
const meta: Meta = {
title: 'Modules/People/EmailInputDisplay',
title: 'UI/Input/EmailInputDisplay',
component: EmailInputDisplay,
decorators: [
(Story) => (
<StyledTestEmailContainer>
<BrowserRouter>
<Story />
</BrowserRouter>
</StyledTestEmailContainer>
),
ComponentDecorator,
],
decorators: [ComponentWithRouterDecorator],
args: {
value: 'mustajab.ikram@google.com',
},
@ -29,9 +17,4 @@ export default meta;
type Story = StoryObj<typeof EmailInputDisplay>;
const StyledTestEmailContainer = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.primary};
display: flex;
`;
export const Default: Story = {};

View File

@ -1,25 +1,13 @@
import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import styled from '@emotion/styled';
import { Meta, StoryObj } from '@storybook/react';
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
import { PhoneInputDisplay } from '../PhoneInputDisplay'; // Adjust the import path as needed
const meta: Meta = {
title: 'Modules/People/PhoneInputDisplay',
title: 'UI/Input/PhoneInputDisplay',
component: PhoneInputDisplay,
decorators: [
(Story) => (
<StyledTestPhoneContainer>
<BrowserRouter>
<Story />
</BrowserRouter>
</StyledTestPhoneContainer>
),
ComponentDecorator,
],
decorators: [ComponentWithRouterDecorator],
args: {
value: '+33788901234',
},
@ -29,10 +17,4 @@ export default meta;
type Story = StoryObj<typeof PhoneInputDisplay>;
const StyledTestPhoneContainer = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.primary};
display: flex;
`;
export const Default: Story = {};

View File

@ -1,13 +1,10 @@
import { ChangeEvent, useEffect, useRef, useState } from 'react';
import { useRef, useState } from 'react';
import PhoneInput, { isPossiblePhoneNumber } from 'react-phone-number-input';
import styled from '@emotion/styled';
import intlTelInput from 'intl-tel-input';
import { hoverBackground } from '@/ui/theme/constants/effects';
import countries from '../../../constants/countries.json';
import { useRegisterCloseCellHandlers } from '../../hooks/useRegisterCloseCellHandlers';
import 'intl-tel-input/build/css/intlTelInput.css';
import 'react-phone-number-input/style.css';
const StyledContainer = styled.div`
align-items: center;
@ -17,113 +14,91 @@ const StyledContainer = styled.div`
display: flex;
justify-content: center;
.iti__country-list {
background: ${({ theme }) => theme.background.secondary};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: ${({ theme }) => theme.border.radius.md};
box-shadow: ${({ theme }) => theme.boxShadow.strong};
.iti__country {
--horizontal-padding: ${({ theme }) => theme.spacing(1)};
--vertical-padding: ${({ theme }) => theme.spacing(3)};
border-radius: ${({ theme }) => theme.border.radius.sm};
color: ${({ theme }) => theme.font.color.secondary};
cursor: pointer;
font-size: ${({ theme }) => theme.font.size.sm};
gap: ${({ theme }) => theme.spacing(1)};
height: calc(32px - 2 * var(--vertical-padding));
padding: var(--vertical-padding) var(--horizontal-padding);
${hoverBackground};
width: calc(100% - 2 * var(--horizontal-padding));
}
}
.iti__flag {
background-color: ${({ theme }) => theme.background.secondary};
}
.iti__arrow {
align-items: center;
display: flex;
justify-content: center;
}
`;
const StyledInput = styled.input`
background: ${({ theme }) => theme.background.primary};
border: none;
border-radius: ${({ theme }) => theme.border.radius.md};
color: ${({ theme }) => theme.font.color.primary};
margin: 0;
outline: none;
padding: ${({ theme }) => theme.spacing(2)};
width: ${({ theme }) => theme.spacing(48)};
`;
type OwnProps = {
export type PhoneCellEditProps = {
placeholder?: string;
autoFocus?: boolean;
value: string;
onSubmit: (newText: string) => void;
};
export function PhoneCellEdit({ autoFocus, value, onSubmit }: OwnProps) {
const [internalText, setInternalText] = useState(value);
const phoneInputRef = useRef<HTMLInputElement | null>(null);
const StyledCustomPhoneInput = styled(PhoneInput)`
--PhoneInput-color--focus: transparent;
--PhoneInputCountryFlag-borderColor--focus: transparent;
--PhoneInputCountrySelect-marginRight: ${({ theme }) => theme.spacing(2)};
--PhoneInputCountrySelectArrow-color: ${({ theme }) =>
theme.font.color.tertiary};
--PhoneInputCountrySelectArrow-opacity: 1;
font-family: ${({ theme }) => theme.font.family};
height: 32px;
.PhoneInputCountry {
--PhoneInputCountryFlag-height: 12px;
--PhoneInputCountryFlag-width: 16px;
border-right: 1px solid ${({ theme }) => theme.border.color.light};
display: flex;
justify-content: center;
margin-left: ${({ theme }) => theme.spacing(2)};
}
.PhoneInputCountryIcon {
background: none;
border-radius: ${({ theme }) => theme.border.radius.xs};
box-shadow: none;
margin-right: 1px;
overflow: hidden;
&:focus {
box-shadow: none !important;
}
}
.PhoneInputCountrySelectArrow {
margin-right: ${({ theme }) => theme.spacing(2)};
}
.PhoneInputInput {
background: ${({ theme }) => theme.background.transparent.secondary};
border: none;
color: ${({ theme }) => theme.font.color.primary};
&::placeholder,
&::-webkit-input-placeholder {
color: ${({ theme }) => theme.font.color.light};
font-family: ${({ theme }) => theme.font.family};
font-weight: ${({ theme }) => theme.font.weight.medium};
}
:focus {
outline: none;
}
}
`;
export function PhoneCellEdit({
autoFocus,
value,
onSubmit,
}: PhoneCellEditProps) {
const [internalValue, setInternalValue] = useState<string | undefined>(value);
const wrapperRef = useRef<HTMLDivElement | null>(null);
function handleSubmit() {
onSubmit(internalText);
}
function handleCancel() {
setInternalText(value);
}
function handleChange(event: ChangeEvent<HTMLInputElement>) {
setInternalText(event.target.value);
}
useEffect(() => {
setInternalText(value);
}, [value]);
useEffect(() => {
if (phoneInputRef.current) {
intlTelInput(phoneInputRef.current, {
utilsScript:
'https://cdnjs.cloudflare.com/ajax/libs/intl-tel-input/8.4.6/js/utils.js',
initialCountry: 'auto',
formatOnDisplay: true,
localizedCountries: countries,
onlyCountries: Object.keys(countries),
preferredCountries: [],
});
if (isPossiblePhoneNumber(internalValue ?? '')) {
onSubmit(internalValue ?? '');
}
}, [value]);
}
useRegisterCloseCellHandlers(wrapperRef, handleSubmit, handleCancel);
useRegisterCloseCellHandlers(wrapperRef, handleSubmit);
return (
<StyledContainer ref={wrapperRef}>
<StyledInput
type="tel"
<StyledCustomPhoneInput
autoFocus={autoFocus}
ref={phoneInputRef}
onChange={handleChange}
value={internalText}
placeholder="Phone number"
value={value}
onChange={setInternalValue}
/>
</StyledContainer>
);

View File

@ -0,0 +1,23 @@
import type { Meta, StoryObj } from '@storybook/react';
import { PhoneCellEdit } from '@/ui/table/editable-cell/type/components/PhoneCellEdit';
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { ComponentWithRecoilScopeDecorator } from '~/testing/decorators/ComponentWithRecoilScopeDecorator';
const meta: Meta<typeof PhoneCellEdit> = {
title: 'UI/Table/EditableCell/PhoneCellEdit',
component: PhoneCellEdit,
decorators: [ComponentWithRecoilScopeDecorator],
args: {
value: '+33714446494',
autoFocus: true,
},
parameters: {
recoilScopeContext: TableRecoilScopeContext,
},
};
export default meta;
type Story = StoryObj<typeof PhoneCellEdit>;
export const Default: Story = {};