Migrate to a monorepo structure (#2909)

This commit is contained in:
Charles Bochet
2023-12-10 18:10:54 +01:00
committed by GitHub
parent a70a9281eb
commit 5bdca9de6c
2304 changed files with 37152 additions and 25869 deletions

View File

@ -0,0 +1,10 @@
import { EllipsisDisplay } from './EllipsisDisplay';
type CurrencyDisplayProps = {
amount?: number | null;
};
// TODO: convert currencyCode to currency symbol
export const CurrencyDisplay = ({ amount }: CurrencyDisplayProps) => {
return <EllipsisDisplay>{amount}</EllipsisDisplay>;
};

View File

@ -0,0 +1,11 @@
import { formatToHumanReadableDate } from '~/utils';
import { EllipsisDisplay } from './EllipsisDisplay';
type DateDisplayProps = {
value: Date | string | null | undefined;
};
export const DateDisplay = ({ value }: DateDisplayProps) => (
<EllipsisDisplay>{value && formatToHumanReadableDate(value)}</EllipsisDisplay>
);

View File

@ -0,0 +1,3 @@
import { TextDisplay } from './TextDisplay';
export const DoubleTextDisplay = TextDisplay;

View File

@ -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 };

View File

@ -0,0 +1,31 @@
import { MouseEvent } from 'react';
import { ContactLink } from '@/ui/navigation/link/components/ContactLink';
import { EllipsisDisplay } from './EllipsisDisplay';
const validateEmail = (email: string) => {
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailPattern.test(email.trim());
};
type EmailDisplayProps = {
value: string | null;
};
export const EmailDisplay = ({ value }: EmailDisplayProps) => (
<EllipsisDisplay>
{value && validateEmail(value) ? (
<ContactLink
href={`mailto:${value}`}
onClick={(event: MouseEvent<HTMLElement>) => {
event.stopPropagation();
}}
>
{value}
</ContactLink>
) : (
<ContactLink href="#">{value}</ContactLink>
)}
</EllipsisDisplay>
);

View File

@ -0,0 +1,73 @@
import { MouseEvent } from 'react';
import styled from '@emotion/styled';
import { FieldLinkValue } from '@/object-record/field/types/FieldMetadata';
import { RoundedLink } from '@/ui/navigation/link/components/RoundedLink';
import {
LinkType,
SocialLink,
} from '@/ui/navigation/link/components/SocialLink';
import { EllipsisDisplay } from './EllipsisDisplay';
const StyledRawLink = styled(RoundedLink)`
overflow: hidden;
a {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
`;
type LinkDisplayProps = {
value?: FieldLinkValue;
};
const checkUrlType = (url: string) => {
if (
/^(http|https):\/\/(?:www\.)?linkedin.com(\w+:{0,1}\w*@)?(\S+)(:([0-9])+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/.test(
url,
)
) {
return LinkType.LinkedIn;
}
if (url.match(/^((http|https):\/\/)?(?:www\.)?twitter\.com\/(\w+)?/i)) {
return LinkType.Twitter;
}
return LinkType.Url;
};
export const LinkDisplay = ({ value }: LinkDisplayProps) => {
const handleClick = (event: MouseEvent<HTMLElement>) => {
event.stopPropagation();
};
const absoluteUrl = value?.url
? value.url.startsWith('http')
? value.url
: 'https://' + value.url
: '';
const displayedValue = value?.label || value?.url || '';
const type = checkUrlType(absoluteUrl);
if (type === LinkType.LinkedIn || type === LinkType.Twitter) {
return (
<EllipsisDisplay>
<SocialLink href={absoluteUrl} onClick={handleClick} type={type}>
{displayedValue}
</SocialLink>
</EllipsisDisplay>
);
}
return (
<EllipsisDisplay>
<StyledRawLink href={absoluteUrl} onClick={handleClick}>
{displayedValue}
</StyledRawLink>
</EllipsisDisplay>
);
};

View File

@ -0,0 +1,11 @@
import { formatNumber } from '~/utils/format/number';
import { EllipsisDisplay } from './EllipsisDisplay';
type MoneyDisplayProps = {
value: number | null;
};
export const MoneyDisplay = ({ value }: MoneyDisplayProps) => (
<EllipsisDisplay>{value ? `$${formatNumber(value)}` : ''}</EllipsisDisplay>
);

View File

@ -0,0 +1,11 @@
import { formatNumber } from '~/utils/format/number';
import { EllipsisDisplay } from './EllipsisDisplay';
type NumberDisplayProps = {
value: string | number | null;
};
export const NumberDisplay = ({ value }: NumberDisplayProps) => (
<EllipsisDisplay>{value && formatNumber(Number(value))}</EllipsisDisplay>
);

View File

@ -0,0 +1,27 @@
import { MouseEvent } from 'react';
import { isValidPhoneNumber, parsePhoneNumber } from 'libphonenumber-js';
import { ContactLink } from '@/ui/navigation/link/components/ContactLink';
import { EllipsisDisplay } from './EllipsisDisplay';
type PhoneDisplayProps = {
value: string | null;
};
export const PhoneDisplay = ({ value }: PhoneDisplayProps) => (
<EllipsisDisplay>
{value && isValidPhoneNumber(value) ? (
<ContactLink
href={parsePhoneNumber(value, 'FR')?.getURI()}
onClick={(event: MouseEvent<HTMLElement>) => {
event.stopPropagation();
}}
>
{parsePhoneNumber(value, 'FR')?.formatInternational() || value}
</ContactLink>
) : (
<ContactLink href="#">{value}</ContactLink>
)}
</EllipsisDisplay>
);

View File

@ -0,0 +1,9 @@
import { EllipsisDisplay } from './EllipsisDisplay';
type TextDisplayProps = {
text: string;
};
export const TextDisplay = ({ text }: TextDisplayProps) => (
<EllipsisDisplay>{text}</EllipsisDisplay>
);

View File

@ -0,0 +1,72 @@
import { MouseEvent } from 'react';
import styled from '@emotion/styled';
import { RoundedLink } from '@/ui/navigation/link/components/RoundedLink';
import {
LinkType,
SocialLink,
} from '@/ui/navigation/link/components/SocialLink';
import { EllipsisDisplay } from './EllipsisDisplay';
const StyledRawLink = styled(RoundedLink)`
overflow: hidden;
a {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
`;
type URLDisplayProps = {
value: string | null;
};
const checkUrlType = (url: string) => {
if (
/^(http|https):\/\/(?:www\.)?linkedin.com(\w+:{0,1}\w*@)?(\S+)(:([0-9])+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/.test(
url,
)
) {
return LinkType.LinkedIn;
}
if (url.match(/^((http|https):\/\/)?(?:www\.)?twitter\.com\/(\w+)?/i)) {
return LinkType.Twitter;
}
return LinkType.Url;
};
export const URLDisplay = ({ value }: URLDisplayProps) => {
const handleClick = (event: MouseEvent<HTMLElement>) => {
event.stopPropagation();
};
const absoluteUrl = value
? value.startsWith('http')
? value
: 'https://' + value
: '';
const displayedValue = value ?? '';
const type = checkUrlType(absoluteUrl);
if (type === LinkType.LinkedIn || type === LinkType.Twitter) {
return (
<EllipsisDisplay>
<SocialLink href={absoluteUrl} onClick={handleClick} type={type}>
{displayedValue}
</SocialLink>
</EllipsisDisplay>
);
}
return (
<EllipsisDisplay>
<StyledRawLink href={absoluteUrl} onClick={handleClick}>
{displayedValue}
</StyledRawLink>
</EllipsisDisplay>
);
};

View File

@ -0,0 +1,20 @@
import { Meta, StoryObj } from '@storybook/react';
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
import { PhoneDisplay } from '../PhoneDisplay'; // Adjust the import path as needed
const meta: Meta = {
title: 'UI/Input/PhoneInputDisplay/PhoneInputDisplay',
component: PhoneDisplay,
decorators: [ComponentWithRouterDecorator],
args: {
value: '+33788901234',
},
};
export default meta;
type Story = StoryObj<typeof PhoneDisplay>;
export const Default: Story = {};