Write Storybook tests for front/src/modules/ui/field/meta-types/display components (#1932)
* Write Storybook tests for front/src/modules/ui/field/meta-types/display components Co-authored-by: v1b3m <vibenjamin6@gmail.com> Co-authored-by: FellipeMTX <fellipefacdir@gmail.com> * Write Storybook tests for front/src/modules/ui/field/meta-types/display components Co-authored-by: FellipeMTX <fellipefacdir@gmail.com> Co-authored-by: v1b3m <vibenjamin6@gmail.com> * Write Storybook tests for front/src/modules/ui/field/meta-types/display components Co-authored-by: v1b3m <vibenjamin6@gmail.com> Co-authored-by: FellipeMTX <fellipefacdir@gmail.com> * add EllipsisDisplay component * add EllipsisDisplay component * modified ComponentDecorator to pass a minWidth parameter to test ellipsis * add ellipsis test to all components * add ellipsis to links * removed minWidth and set it to 'unset' if the width is not defined --------- Co-authored-by: v1b3m <vibenjamin6@gmail.com> Co-authored-by: FellipeMTX <fellipefacdir@gmail.com> Co-authored-by: bosiraphael <raphael.bosi@gmail.com>
This commit is contained in:
@ -0,0 +1,78 @@
|
|||||||
|
import { useEffect } from 'react';
|
||||||
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
|
|
||||||
|
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||||
|
|
||||||
|
import { useDateField } from '../../../hooks/useDateField';
|
||||||
|
import { DateFieldDisplay } from '../DateFieldDisplay';
|
||||||
|
|
||||||
|
import { FieldDisplayContextProvider } from './FieldDisplayContextProvider';
|
||||||
|
|
||||||
|
const formattedDate = new Date();
|
||||||
|
|
||||||
|
const DateFieldValueSetterEffect = ({ value }: { value: string }) => {
|
||||||
|
const { setFieldValue } = useDateField();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setFieldValue(value);
|
||||||
|
}, [setFieldValue, value]);
|
||||||
|
|
||||||
|
return <></>;
|
||||||
|
};
|
||||||
|
|
||||||
|
type DateFieldDisplayWithContextProps = {
|
||||||
|
value: string;
|
||||||
|
entityId?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DateFieldDisplayWithContext = ({
|
||||||
|
value,
|
||||||
|
entityId,
|
||||||
|
}: DateFieldDisplayWithContextProps) => {
|
||||||
|
return (
|
||||||
|
<FieldDisplayContextProvider
|
||||||
|
fieldDefinition={{
|
||||||
|
key: 'date',
|
||||||
|
name: 'Date',
|
||||||
|
type: 'date',
|
||||||
|
metadata: {
|
||||||
|
fieldName: 'Date',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
entityId={entityId}
|
||||||
|
>
|
||||||
|
<DateFieldValueSetterEffect value={value} />
|
||||||
|
<DateFieldDisplay />
|
||||||
|
</FieldDisplayContextProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const meta: Meta = {
|
||||||
|
title: 'UI/Field/DateFieldDisplay',
|
||||||
|
component: DateFieldDisplayWithContext,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof DateFieldDisplayWithContext>;
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {
|
||||||
|
value: formattedDate.toISOString(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Elipsis: Story = {
|
||||||
|
args: {
|
||||||
|
value: formattedDate.toISOString(),
|
||||||
|
},
|
||||||
|
argTypes: {
|
||||||
|
value: { control: false },
|
||||||
|
},
|
||||||
|
parameters: {
|
||||||
|
container: {
|
||||||
|
width: 50,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
decorators: [ComponentDecorator],
|
||||||
|
};
|
||||||
@ -0,0 +1,102 @@
|
|||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
|
|
||||||
|
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||||
|
|
||||||
|
import { useDoubleTextField } from '../../../hooks/useDoubleTextField';
|
||||||
|
import { DoubleTextFieldDisplay } from '../DoubleTextFieldDisplay'; // Import your component
|
||||||
|
|
||||||
|
import { FieldDisplayContextProvider } from './FieldDisplayContextProvider';
|
||||||
|
|
||||||
|
const DoubleTextFieldDisplayValueSetterEffect = ({
|
||||||
|
firstValue,
|
||||||
|
secondValue,
|
||||||
|
}: {
|
||||||
|
firstValue: string;
|
||||||
|
secondValue: string;
|
||||||
|
}) => {
|
||||||
|
const { setFirstValue, setSecondValue } = useDoubleTextField();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setFirstValue(firstValue);
|
||||||
|
setSecondValue(secondValue);
|
||||||
|
}, [setFirstValue, setSecondValue, firstValue, secondValue]);
|
||||||
|
|
||||||
|
return <></>;
|
||||||
|
};
|
||||||
|
|
||||||
|
type DoubleTextFieldDisplayWithContextProps = {
|
||||||
|
firstValue: string;
|
||||||
|
secondValue: string;
|
||||||
|
entityId?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DoubleTextFieldDisplayWithContext = ({
|
||||||
|
firstValue,
|
||||||
|
secondValue,
|
||||||
|
entityId,
|
||||||
|
}: DoubleTextFieldDisplayWithContextProps) => {
|
||||||
|
return (
|
||||||
|
<FieldDisplayContextProvider
|
||||||
|
fieldDefinition={{
|
||||||
|
key: 'double-text',
|
||||||
|
name: 'Double-Text',
|
||||||
|
type: 'double-text',
|
||||||
|
metadata: {
|
||||||
|
firstValueFieldName: 'First-text',
|
||||||
|
firstValuePlaceholder: 'First-text',
|
||||||
|
secondValueFieldName: 'Second-text',
|
||||||
|
secondValuePlaceholder: 'Second-text',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
entityId={entityId}
|
||||||
|
>
|
||||||
|
<DoubleTextFieldDisplayValueSetterEffect
|
||||||
|
firstValue={firstValue}
|
||||||
|
secondValue={secondValue}
|
||||||
|
/>
|
||||||
|
<DoubleTextFieldDisplay />
|
||||||
|
</FieldDisplayContextProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const meta: Meta = {
|
||||||
|
title: 'UI/Field/DoubleTextFieldDisplay',
|
||||||
|
component: DoubleTextFieldDisplayWithContext,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof DoubleTextFieldDisplayWithContext>;
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {
|
||||||
|
firstValue: 'Lorem',
|
||||||
|
secondValue: 'ipsum',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CustomValues: Story = {
|
||||||
|
args: {
|
||||||
|
firstValue: 'Lorem',
|
||||||
|
secondValue: 'ipsum',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Elipsis: Story = {
|
||||||
|
args: {
|
||||||
|
firstValue:
|
||||||
|
'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
|
||||||
|
secondValue: 'ipsum dolor sit amet, consectetur adipiscing elit.',
|
||||||
|
},
|
||||||
|
argTypes: {
|
||||||
|
firstValue: { control: true },
|
||||||
|
secondValue: { control: true },
|
||||||
|
},
|
||||||
|
parameters: {
|
||||||
|
container: {
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
decorators: [ComponentDecorator],
|
||||||
|
};
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
import { useEffect } from 'react';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
|
|
||||||
|
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||||
|
|
||||||
|
import { useEmailField } from '../../../hooks/useEmailField';
|
||||||
|
import { EmailFieldDisplay } from '../EmailFieldDisplay';
|
||||||
|
|
||||||
|
import { FieldDisplayContextProvider } from './FieldDisplayContextProvider';
|
||||||
|
|
||||||
|
const EmailFieldValueSetterEffect = ({ value }: { value: string }) => {
|
||||||
|
const { setFieldValue } = useEmailField();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setFieldValue(value);
|
||||||
|
}, [setFieldValue, value]);
|
||||||
|
|
||||||
|
return <></>;
|
||||||
|
};
|
||||||
|
|
||||||
|
type EmailFieldDisplayWithContextProps = {
|
||||||
|
value: string;
|
||||||
|
entityId?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const EmailFieldDisplayWithContext = ({
|
||||||
|
value,
|
||||||
|
entityId,
|
||||||
|
}: EmailFieldDisplayWithContextProps) => {
|
||||||
|
return (
|
||||||
|
<FieldDisplayContextProvider
|
||||||
|
fieldDefinition={{
|
||||||
|
key: 'email',
|
||||||
|
name: 'Email',
|
||||||
|
type: 'email',
|
||||||
|
metadata: {
|
||||||
|
fieldName: 'Email',
|
||||||
|
placeHolder: 'Email',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
entityId={entityId}
|
||||||
|
>
|
||||||
|
<MemoryRouter>
|
||||||
|
<EmailFieldValueSetterEffect value={value} />
|
||||||
|
<EmailFieldDisplay />
|
||||||
|
</MemoryRouter>
|
||||||
|
</FieldDisplayContextProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const meta: Meta = {
|
||||||
|
title: 'UI/Field/EmailFieldDisplay',
|
||||||
|
component: EmailFieldDisplayWithContext,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof EmailFieldDisplayWithContext>;
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {
|
||||||
|
value: 'Test@Test.test',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Elipsis: Story = {
|
||||||
|
args: {
|
||||||
|
value: 'Test@Test.test',
|
||||||
|
},
|
||||||
|
argTypes: {
|
||||||
|
value: { control: false },
|
||||||
|
},
|
||||||
|
parameters: {
|
||||||
|
container: {
|
||||||
|
width: 50,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
decorators: [ComponentDecorator],
|
||||||
|
};
|
||||||
@ -0,0 +1,109 @@
|
|||||||
|
import { useEffect } from 'react';
|
||||||
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
|
import { CatalogDecorator } from '~/testing/decorators/CatalogDecorator';
|
||||||
|
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||||
|
import { CatalogStory } from '~/testing/types';
|
||||||
|
|
||||||
|
import { useNumberField } from '../../../hooks/useNumberField';
|
||||||
|
import { NumberFieldDisplay } from '../NumberFieldDisplay';
|
||||||
|
|
||||||
|
import { FieldDisplayContextProvider } from './FieldDisplayContextProvider';
|
||||||
|
|
||||||
|
const NumberFieldValueSetterEffect = ({ value }: { value: number }) => {
|
||||||
|
const { setFieldValue } = useNumberField();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setFieldValue(value);
|
||||||
|
}, [setFieldValue, value]);
|
||||||
|
|
||||||
|
return <></>;
|
||||||
|
};
|
||||||
|
|
||||||
|
type NumberFieldDisplayWithContextProps = {
|
||||||
|
value: number;
|
||||||
|
entityId?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const NumberFieldDisplayWithContext = ({
|
||||||
|
value,
|
||||||
|
entityId,
|
||||||
|
}: NumberFieldDisplayWithContextProps) => {
|
||||||
|
return (
|
||||||
|
<FieldDisplayContextProvider
|
||||||
|
fieldDefinition={{
|
||||||
|
key: 'number',
|
||||||
|
name: 'Number',
|
||||||
|
type: 'number',
|
||||||
|
metadata: {
|
||||||
|
fieldName: 'Number',
|
||||||
|
placeHolder: 'Number',
|
||||||
|
isPositive: true,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
entityId={entityId}
|
||||||
|
>
|
||||||
|
<NumberFieldValueSetterEffect value={value} />
|
||||||
|
<NumberFieldDisplay />
|
||||||
|
</FieldDisplayContextProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const meta: Meta = {
|
||||||
|
title: 'UI/Field/NumberFieldDisplay',
|
||||||
|
component: NumberFieldDisplayWithContext,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof NumberFieldDisplayWithContext>;
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {
|
||||||
|
value: 100,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Elipsis: Story = {
|
||||||
|
args: {
|
||||||
|
value: 1e100,
|
||||||
|
},
|
||||||
|
argTypes: {
|
||||||
|
value: { control: false },
|
||||||
|
},
|
||||||
|
parameters: {
|
||||||
|
container: {
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
decorators: [ComponentDecorator],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Catalog: CatalogStory<
|
||||||
|
Story,
|
||||||
|
typeof NumberFieldDisplayWithContext
|
||||||
|
> = {
|
||||||
|
argTypes: {
|
||||||
|
value: { control: false },
|
||||||
|
},
|
||||||
|
parameters: {
|
||||||
|
catalog: {
|
||||||
|
dimensions: [
|
||||||
|
{
|
||||||
|
name: 'value',
|
||||||
|
values: [
|
||||||
|
100, 1000, -1000, 1e10, 1.357802, -1.283, 0,
|
||||||
|
] satisfies number[],
|
||||||
|
props: (value: number) => ({ value, entityId: v4() }),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
options: {
|
||||||
|
elementContainer: {
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
decorators: [CatalogDecorator],
|
||||||
|
};
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
import { useEffect } from 'react';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
|
|
||||||
|
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||||
|
|
||||||
|
import { usePhoneField } from '../../../hooks/usePhoneField';
|
||||||
|
import { PhoneFieldDisplay } from '../PhoneFieldDisplay';
|
||||||
|
|
||||||
|
import { FieldDisplayContextProvider } from './FieldDisplayContextProvider';
|
||||||
|
|
||||||
|
const PhoneFieldValueSetterEffect = ({ value }: { value: string }) => {
|
||||||
|
const { setFieldValue } = usePhoneField();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setFieldValue(value);
|
||||||
|
}, [setFieldValue, value]);
|
||||||
|
|
||||||
|
return <></>;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PhoneFieldDisplayWithContextProps = {
|
||||||
|
value: string;
|
||||||
|
entityId?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const PhoneFieldDisplayWithContext = ({
|
||||||
|
value,
|
||||||
|
entityId,
|
||||||
|
}: PhoneFieldDisplayWithContextProps) => {
|
||||||
|
return (
|
||||||
|
<FieldDisplayContextProvider
|
||||||
|
fieldDefinition={{
|
||||||
|
key: 'phone',
|
||||||
|
name: 'Phone',
|
||||||
|
type: 'phone',
|
||||||
|
metadata: {
|
||||||
|
fieldName: 'Phone',
|
||||||
|
placeHolder: 'Phone',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
entityId={entityId}
|
||||||
|
>
|
||||||
|
<MemoryRouter>
|
||||||
|
<PhoneFieldValueSetterEffect value={value} />
|
||||||
|
<PhoneFieldDisplay />
|
||||||
|
</MemoryRouter>
|
||||||
|
</FieldDisplayContextProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const meta: Meta = {
|
||||||
|
title: 'UI/Field/PhoneFieldDisplay',
|
||||||
|
component: PhoneFieldDisplayWithContext,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof PhoneFieldDisplayWithContext>;
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {
|
||||||
|
value: '362763872687362',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Elipsis: Story = {
|
||||||
|
args: {
|
||||||
|
value: '362763872687362',
|
||||||
|
},
|
||||||
|
argTypes: {
|
||||||
|
value: { control: false },
|
||||||
|
},
|
||||||
|
parameters: {
|
||||||
|
container: {
|
||||||
|
width: 50,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
decorators: [ComponentDecorator],
|
||||||
|
};
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
import { useEffect } from 'react';
|
||||||
|
import { MemoryRouter } from 'react-router';
|
||||||
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
|
|
||||||
|
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||||
|
|
||||||
|
import { useURLField } from '../../../hooks/useURLField';
|
||||||
|
import { URLFieldDisplay } from '../URLFieldDisplay';
|
||||||
|
|
||||||
|
import { FieldDisplayContextProvider } from './FieldDisplayContextProvider';
|
||||||
|
|
||||||
|
const URLFieldValueSetterEffect = ({ value }: { value: string }) => {
|
||||||
|
const { setFieldValue } = useURLField();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setFieldValue(value);
|
||||||
|
}, [setFieldValue, value]);
|
||||||
|
|
||||||
|
return <></>;
|
||||||
|
};
|
||||||
|
|
||||||
|
type URLFieldDisplayWithContextProps = {
|
||||||
|
value: string;
|
||||||
|
entityId?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const URLFieldDisplayWithContext = ({
|
||||||
|
value,
|
||||||
|
entityId,
|
||||||
|
}: URLFieldDisplayWithContextProps) => {
|
||||||
|
return (
|
||||||
|
<FieldDisplayContextProvider
|
||||||
|
fieldDefinition={{
|
||||||
|
key: 'URL',
|
||||||
|
name: 'URL',
|
||||||
|
type: 'url',
|
||||||
|
metadata: {
|
||||||
|
fieldName: 'URL',
|
||||||
|
placeHolder: 'URL',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
entityId={entityId}
|
||||||
|
>
|
||||||
|
<MemoryRouter>
|
||||||
|
<URLFieldValueSetterEffect value={value} />
|
||||||
|
<URLFieldDisplay />
|
||||||
|
</MemoryRouter>
|
||||||
|
</FieldDisplayContextProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const meta: Meta = {
|
||||||
|
title: 'UI/Field/URLFieldDisplay',
|
||||||
|
component: URLFieldDisplayWithContext,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof URLFieldDisplayWithContext>;
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {
|
||||||
|
value: 'https://github.com/GitStartHQ',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Elipsis: Story = {
|
||||||
|
args: {
|
||||||
|
value: 'https://www.instagram.com/gitstart/',
|
||||||
|
},
|
||||||
|
argTypes: {
|
||||||
|
value: { control: true },
|
||||||
|
},
|
||||||
|
parameters: {
|
||||||
|
container: {
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
decorators: [ComponentDecorator],
|
||||||
|
};
|
||||||
@ -1,9 +1,11 @@
|
|||||||
import { formatToHumanReadableDate } from '~/utils';
|
import { formatToHumanReadableDate } from '~/utils';
|
||||||
|
|
||||||
|
import { EllipsisDisplay } from './EllipsisDisplay';
|
||||||
|
|
||||||
type DateDisplayProps = {
|
type DateDisplayProps = {
|
||||||
value: Date | string | null | undefined;
|
value: Date | string | null | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DateDisplay = ({ value }: DateDisplayProps) => (
|
export const DateDisplay = ({ value }: DateDisplayProps) => (
|
||||||
<div>{value && formatToHumanReadableDate(value)}</div>
|
<EllipsisDisplay>{value && formatToHumanReadableDate(value)}</EllipsisDisplay>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -0,0 +1,10 @@
|
|||||||
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
const StyledEllipsisDisplay = styled.div`
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export { StyledEllipsisDisplay as EllipsisDisplay };
|
||||||
@ -2,6 +2,8 @@ import { MouseEvent } from 'react';
|
|||||||
|
|
||||||
import { ContactLink } from '@/ui/link/components/ContactLink';
|
import { ContactLink } from '@/ui/link/components/ContactLink';
|
||||||
|
|
||||||
|
import { EllipsisDisplay } from './EllipsisDisplay';
|
||||||
|
|
||||||
const validateEmail = (email: string) => {
|
const validateEmail = (email: string) => {
|
||||||
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
return emailPattern.test(email.trim());
|
return emailPattern.test(email.trim());
|
||||||
@ -11,16 +13,19 @@ type EmailDisplayProps = {
|
|||||||
value: string | null;
|
value: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EmailDisplay = ({ value }: EmailDisplayProps) =>
|
export const EmailDisplay = ({ value }: EmailDisplayProps) => (
|
||||||
value && validateEmail(value) ? (
|
<EllipsisDisplay>
|
||||||
<ContactLink
|
{value && validateEmail(value) ? (
|
||||||
href={`mailto:${value}`}
|
<ContactLink
|
||||||
onClick={(event: MouseEvent<HTMLElement>) => {
|
href={`mailto:${value}`}
|
||||||
event.stopPropagation();
|
onClick={(event: MouseEvent<HTMLElement>) => {
|
||||||
}}
|
event.stopPropagation();
|
||||||
>
|
}}
|
||||||
{value}
|
>
|
||||||
</ContactLink>
|
{value}
|
||||||
) : (
|
</ContactLink>
|
||||||
<ContactLink href="#">{value}</ContactLink>
|
) : (
|
||||||
);
|
<ContactLink href="#">{value}</ContactLink>
|
||||||
|
)}
|
||||||
|
</EllipsisDisplay>
|
||||||
|
);
|
||||||
|
|||||||
@ -1,20 +1,11 @@
|
|||||||
import styled from '@emotion/styled';
|
|
||||||
|
|
||||||
import { formatNumber } from '~/utils/format/number';
|
import { formatNumber } from '~/utils/format/number';
|
||||||
|
|
||||||
const StyledTextInputDisplay = styled.div`
|
import { EllipsisDisplay } from './EllipsisDisplay';
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
width: 100%;
|
|
||||||
`;
|
|
||||||
|
|
||||||
type MoneyDisplayProps = {
|
type MoneyDisplayProps = {
|
||||||
value: number | null;
|
value: number | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MoneyDisplay = ({ value }: MoneyDisplayProps) => (
|
export const MoneyDisplay = ({ value }: MoneyDisplayProps) => (
|
||||||
<StyledTextInputDisplay>
|
<EllipsisDisplay>{value ? `$${formatNumber(value)}` : ''}</EllipsisDisplay>
|
||||||
{value ? `$${formatNumber(value)}` : ''}
|
|
||||||
</StyledTextInputDisplay>
|
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,20 +1,11 @@
|
|||||||
import styled from '@emotion/styled';
|
|
||||||
|
|
||||||
import { formatNumber } from '~/utils/format/number';
|
import { formatNumber } from '~/utils/format/number';
|
||||||
|
|
||||||
const StyledNumberDisplay = styled.div`
|
import { EllipsisDisplay } from './EllipsisDisplay';
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
width: 100%;
|
|
||||||
`;
|
|
||||||
|
|
||||||
type NumberDisplayProps = {
|
type NumberDisplayProps = {
|
||||||
value: string | number | null;
|
value: string | number | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const NumberDisplay = ({ value }: NumberDisplayProps) => (
|
export const NumberDisplay = ({ value }: NumberDisplayProps) => (
|
||||||
<StyledNumberDisplay>
|
<EllipsisDisplay>{value && formatNumber(Number(value))}</EllipsisDisplay>
|
||||||
{value && formatNumber(Number(value))}
|
|
||||||
</StyledNumberDisplay>
|
|
||||||
);
|
);
|
||||||
|
|||||||
@ -3,20 +3,25 @@ import { isValidPhoneNumber, parsePhoneNumber } from 'libphonenumber-js';
|
|||||||
|
|
||||||
import { ContactLink } from '@/ui/link/components/ContactLink';
|
import { ContactLink } from '@/ui/link/components/ContactLink';
|
||||||
|
|
||||||
|
import { EllipsisDisplay } from './EllipsisDisplay';
|
||||||
|
|
||||||
type PhoneDisplayProps = {
|
type PhoneDisplayProps = {
|
||||||
value: string | null;
|
value: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PhoneDisplay = ({ value }: PhoneDisplayProps) =>
|
export const PhoneDisplay = ({ value }: PhoneDisplayProps) => (
|
||||||
value && isValidPhoneNumber(value) ? (
|
<EllipsisDisplay>
|
||||||
<ContactLink
|
{value && isValidPhoneNumber(value) ? (
|
||||||
href={parsePhoneNumber(value, 'FR')?.getURI()}
|
<ContactLink
|
||||||
onClick={(event: MouseEvent<HTMLElement>) => {
|
href={parsePhoneNumber(value, 'FR')?.getURI()}
|
||||||
event.stopPropagation();
|
onClick={(event: MouseEvent<HTMLElement>) => {
|
||||||
}}
|
event.stopPropagation();
|
||||||
>
|
}}
|
||||||
{parsePhoneNumber(value, 'FR')?.formatInternational() || value}
|
>
|
||||||
</ContactLink>
|
{parsePhoneNumber(value, 'FR')?.formatInternational() || value}
|
||||||
) : (
|
</ContactLink>
|
||||||
<ContactLink href="#">{value}</ContactLink>
|
) : (
|
||||||
);
|
<ContactLink href="#">{value}</ContactLink>
|
||||||
|
)}
|
||||||
|
</EllipsisDisplay>
|
||||||
|
);
|
||||||
|
|||||||
@ -1,16 +1,9 @@
|
|||||||
import styled from '@emotion/styled';
|
import { EllipsisDisplay } from './EllipsisDisplay';
|
||||||
|
|
||||||
const StyledTextInputDisplay = styled.div`
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
width: 100%;
|
|
||||||
`;
|
|
||||||
|
|
||||||
type TextDisplayProps = {
|
type TextDisplayProps = {
|
||||||
text: string;
|
text: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TextDisplay = ({ text }: TextDisplayProps) => (
|
export const TextDisplay = ({ text }: TextDisplayProps) => (
|
||||||
<StyledTextInputDisplay>{text}</StyledTextInputDisplay>
|
<EllipsisDisplay>{text}</EllipsisDisplay>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -4,6 +4,8 @@ import styled from '@emotion/styled';
|
|||||||
import { RoundedLink } from '@/ui/link/components/RoundedLink';
|
import { RoundedLink } from '@/ui/link/components/RoundedLink';
|
||||||
import { LinkType, SocialLink } from '@/ui/link/components/SocialLink';
|
import { LinkType, SocialLink } from '@/ui/link/components/SocialLink';
|
||||||
|
|
||||||
|
import { EllipsisDisplay } from './EllipsisDisplay';
|
||||||
|
|
||||||
const StyledRawLink = styled(RoundedLink)`
|
const StyledRawLink = styled(RoundedLink)`
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
@ -50,14 +52,18 @@ export const URLDisplay = ({ value }: URLDisplayProps) => {
|
|||||||
|
|
||||||
if (type === LinkType.LinkedIn || type === LinkType.Twitter) {
|
if (type === LinkType.LinkedIn || type === LinkType.Twitter) {
|
||||||
return (
|
return (
|
||||||
<SocialLink href={absoluteUrl} onClick={handleClick} type={type}>
|
<EllipsisDisplay>
|
||||||
{displayedValue}
|
<SocialLink href={absoluteUrl} onClick={handleClick} type={type}>
|
||||||
</SocialLink>
|
{displayedValue}
|
||||||
|
</SocialLink>
|
||||||
|
</EllipsisDisplay>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<StyledRawLink href={absoluteUrl} onClick={handleClick}>
|
<EllipsisDisplay>
|
||||||
{displayedValue}
|
<StyledRawLink href={absoluteUrl} onClick={handleClick}>
|
||||||
</StyledRawLink>
|
{displayedValue}
|
||||||
|
</StyledRawLink>
|
||||||
|
</EllipsisDisplay>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -16,8 +16,10 @@ const StyledClickable = styled.div`
|
|||||||
|
|
||||||
a {
|
a {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
|
overflow: hidden;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
text-decoration-color: ${({ theme }) => theme.border.color.strong};
|
text-decoration-color: ${({ theme }) => theme.border.color.strong};
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
text-decoration-color: ${({ theme }) => theme.font.color.primary};
|
text-decoration-color: ${({ theme }) => theme.font.color.primary};
|
||||||
|
|||||||
@ -14,7 +14,9 @@ const StyledClickable = styled.div`
|
|||||||
a {
|
a {
|
||||||
color: ${({ theme }) => theme.font.color.tertiary};
|
color: ${({ theme }) => theme.font.color.tertiary};
|
||||||
font-size: ${({ theme }) => theme.font.size.sm};
|
font-size: ${({ theme }) => theme.font.size.sm};
|
||||||
|
overflow: hidden;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@ -16,6 +16,8 @@ const StyledClickable = styled.div`
|
|||||||
|
|
||||||
a {
|
a {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,9 @@ const StyledClickable = styled.div`
|
|||||||
|
|
||||||
a {
|
a {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
|
overflow: hidden;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@ const StyledLayout = styled.div<{ width?: number }>`
|
|||||||
|
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
max-width: calc(100% - 40px);
|
max-width: calc(100% - 40px);
|
||||||
min-width: 300px;
|
min-width: ${({ width }) => (width ? 'unset' : '300px')};
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
width: ${({ width }) => (width ? width + 'px' : 'fit-content')};
|
width: ${({ width }) => (width ? width + 'px' : 'fit-content')};
|
||||||
`;
|
`;
|
||||||
|
|||||||
Reference in New Issue
Block a user