diff --git a/package.json b/package.json
index 90a056159b..ac7ff68ae5 100644
--- a/package.json
+++ b/package.json
@@ -23,6 +23,8 @@
"@hello-pangea/dnd": "^16.2.0",
"@hookform/resolvers": "^3.1.1",
"@jsdevtools/rehype-toc": "^3.0.2",
+ "@linaria/core": "^6.2.0",
+ "@linaria/react": "^6.2.1",
"@mdx-js/react": "^3.0.0",
"@nestjs/apollo": "^11.0.5",
"@nestjs/axios": "^3.0.1",
@@ -61,6 +63,7 @@
"@types/lodash.pick": "^4.3.7",
"@types/nodemailer": "^6.4.14",
"@types/passport-microsoft": "^1.0.3",
+ "@wyw-in-js/vite": "^0.5.3",
"add": "^2.0.6",
"addressparser": "^1.0.1",
"afterframe": "^1.0.2",
@@ -192,6 +195,7 @@
"devDependencies": {
"@babel/core": "^7.14.5",
"@babel/preset-react": "^7.14.5",
+ "@babel/preset-typescript": "^7.24.6",
"@crxjs/vite-plugin": "^1.0.14",
"@docusaurus/module-type-aliases": "^3.1.0",
"@docusaurus/tsconfig": "3.1.0",
diff --git a/packages/twenty-front/nyc.config.cjs b/packages/twenty-front/nyc.config.cjs
index 6155752651..3fbf2dfd62 100644
--- a/packages/twenty-front/nyc.config.cjs
+++ b/packages/twenty-front/nyc.config.cjs
@@ -8,7 +8,7 @@ const globalCoverage = {
const modulesCoverage = {
branches: 25,
- statements: 50,
+ statements: 49,
lines: 50,
functions: 40,
include: ['src/modules/**/*'],
diff --git a/packages/twenty-front/src/modules/companies/types/Company.ts b/packages/twenty-front/src/modules/companies/types/Company.ts
index f6fa70de63..43f2cfbc1a 100644
--- a/packages/twenty-front/src/modules/companies/types/Company.ts
+++ b/packages/twenty-front/src/modules/companies/types/Company.ts
@@ -2,15 +2,20 @@ export type Company = {
__typename: 'Company';
id: string;
createdAt: string;
- updatedAt: string;
- deletedAt: string | null;
+ updatedAt?: string;
+ deletedAt?: string | null;
name: string;
domainName: string;
address: string;
- accountOwnerId: string | null;
- linkedinLink: { url: string; label: string };
- xLink: { url: string; label: string };
- annualRecurringRevenue: { amountMicros: number | null; currencyCode: string };
+ accountOwnerId?: string | null;
+ position?: number;
+ linkedinLink: { __typename?: 'Link'; url: string; label: string };
+ xLink?: { __typename?: 'Link'; url: string; label: string };
+ annualRecurringRevenue: {
+ __typename?: 'Currency';
+ amountMicros: number | null;
+ currencyCode: string;
+ };
employees: number | null;
- idealCustomerProfile: boolean;
+ idealCustomerProfile?: boolean;
};
diff --git a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx
index b374d13e1d..8071b00b65 100644
--- a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx
+++ b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx
@@ -1,9 +1,11 @@
-import React from 'react';
+import React, { useMemo } from 'react';
import { useRecoilValue } from 'recoil';
import { ObjectMetadataItemsLoadEffect } from '@/object-metadata/components/ObjectMetadataItemsLoadEffect';
+import { PreComputedChipGeneratorsContext } from '@/object-metadata/context/PreComputedChipGeneratorsContext';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { RelationPickerScope } from '@/object-record/relation-picker/scopes/RelationPickerScope';
+import { getRecordChipGeneratorPerObjectPerField } from '@/object-record/utils/getRecordChipGeneratorPerObjectPerField';
import { UserOrMetadataLoader } from '~/loading/components/UserOrMetadataLoader';
export const ObjectMetadataItemsProvider = ({
@@ -13,13 +15,23 @@ export const ObjectMetadataItemsProvider = ({
const shouldDisplayChildren = objectMetadataItems.length > 0;
+ const chipGeneratorPerObjectPerField = useMemo(() => {
+ return getRecordChipGeneratorPerObjectPerField(objectMetadataItems);
+ }, [objectMetadataItems]);
+
return (
<>
{shouldDisplayChildren ? (
-
- {children}
-
+
+
+ {children}
+
+
) : (
)}
diff --git a/packages/twenty-front/src/modules/object-metadata/context/PreComputedChipGeneratorsContext.ts b/packages/twenty-front/src/modules/object-metadata/context/PreComputedChipGeneratorsContext.ts
new file mode 100644
index 0000000000..fcb5b7d46b
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-metadata/context/PreComputedChipGeneratorsContext.ts
@@ -0,0 +1,18 @@
+import { createContext } from 'react';
+
+import { RecordChipData } from '@/object-record/record-field/types/RecordChipData';
+import { ObjectRecord } from '@/object-record/types/ObjectRecord';
+
+export type ChipGeneratorPerObjectPerField = Record<
+ string,
+ Record RecordChipData>
+>;
+
+export type PreComputedChipGeneratorsContextProps = {
+ chipGeneratorPerObjectPerField: ChipGeneratorPerObjectPerField;
+};
+
+export const PreComputedChipGeneratorsContext =
+ createContext(
+ {} as PreComputedChipGeneratorsContextProps,
+ );
diff --git a/packages/twenty-front/src/modules/object-record/record-field/components/FieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-field/components/FieldDisplay.tsx
index 454cdb949e..31a7692f21 100644
--- a/packages/twenty-front/src/modules/object-record/record-field/components/FieldDisplay.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-field/components/FieldDisplay.tsx
@@ -5,6 +5,7 @@ import { LinksFieldDisplay } from '@/object-record/record-field/meta-types/displ
import { isFieldBoolean } from '@/object-record/record-field/types/guards/isFieldBoolean';
import { isFieldDisplayedAsPhone } from '@/object-record/record-field/types/guards/isFieldDisplayedAsPhone';
import { isFieldLinks } from '@/object-record/record-field/types/guards/isFieldLinks';
+import { isFieldChipDisplay } from '@/object-record/utils/getRecordChipGeneratorPerObjectPerField';
import { FieldContext } from '../contexts/FieldContext';
import { AddressFieldDisplay } from '../meta-types/display/components/AddressFieldDisplay';
@@ -42,11 +43,7 @@ import { isFieldUuid } from '../types/guards/isFieldUuid';
export const FieldDisplay = () => {
const { fieldDefinition, isLabelIdentifier } = useContext(FieldContext);
- const isChipDisplay =
- isLabelIdentifier &&
- (isFieldText(fieldDefinition) ||
- isFieldFullName(fieldDefinition) ||
- isFieldNumber(fieldDefinition));
+ const isChipDisplay = isFieldChipDisplay(fieldDefinition, isLabelIdentifier);
return isChipDisplay ? (
diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/ChipFieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/ChipFieldDisplay.tsx
index f810590051..30fdcb7a77 100644
--- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/ChipFieldDisplay.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/ChipFieldDisplay.tsx
@@ -1,12 +1,24 @@
-import { RecordChip } from '@/object-record/components/RecordChip';
-import { useChipField } from '@/object-record/record-field/meta-types/hooks/useChipField';
+import { EntityChip } from 'twenty-ui';
+
+import { useChipFieldDisplay } from '@/object-record/record-field/meta-types/hooks/useChipFieldDisplay';
+import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64';
export const ChipFieldDisplay = () => {
- const { objectNameSingular, record } = useChipField();
+ const { recordValue, generateRecordChipData } = useChipFieldDisplay();
- if (!record) return null;
+ if (!recordValue) {
+ return null;
+ }
+
+ const recordChipData = generateRecordChipData(recordValue);
return (
-
+
);
};
diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/PhoneFieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/PhoneFieldDisplay.tsx
index 4fff5669bb..acfd141a32 100644
--- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/PhoneFieldDisplay.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/PhoneFieldDisplay.tsx
@@ -1,9 +1,8 @@
+import { usePhoneFieldDisplay } from '@/object-record/record-field/meta-types/hooks/usePhoneFieldDisplay';
import { PhoneDisplay } from '@/ui/field/display/components/PhoneDisplay';
-import { usePhoneField } from '../../hooks/usePhoneField';
-
export const PhoneFieldDisplay = () => {
- const { fieldValue } = usePhoneField();
+ const { fieldValue } = usePhoneFieldDisplay();
return ;
};
diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/RelationFromManyFieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/RelationFromManyFieldDisplay.tsx
index d498faaa29..808565a5a9 100644
--- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/RelationFromManyFieldDisplay.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/RelationFromManyFieldDisplay.tsx
@@ -23,8 +23,8 @@ export const RelationFromManyFieldDisplay = ({
{recordChipsData.map((record) => {
return (
{
- const setEntityFields = useSetRecoilState(recordStoreFamilyState('123'));
-
- useEffect(() => {
- setEntityFields({
- id: 'henry',
- name: {
- firstName: 'Henry',
- lastName: 'Cavill',
- },
- __typename: 'Person',
- });
- }, [setEntityFields]);
-
- return null;
-};
-
-const meta: Meta = {
- title: 'UI/Data/Field/Display/ChipFieldDisplay',
- decorators: [
- MemoryRouterDecorator,
- (Story) => (
-
-
-
-
- ),
- ComponentDecorator,
- ],
- component: ChipFieldDisplay,
- argTypes: { value: { control: 'date' } },
- args: {},
-};
-
-export default meta;
-
-type Story = StoryObj;
-
-export const Default: Story = {};
diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/PhoneFieldDisplay.stories.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/PhoneFieldDisplay.stories.tsx
deleted file mode 100644
index 0d4d07d71b..0000000000
--- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/PhoneFieldDisplay.stories.tsx
+++ /dev/null
@@ -1,68 +0,0 @@
-import { useEffect } from 'react';
-import { Meta, StoryObj } from '@storybook/react';
-import { ComponentDecorator } from 'twenty-ui';
-
-import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
-import { usePhoneField } from '@/object-record/record-field/meta-types/hooks/usePhoneField';
-import { FieldMetadataType } from '~/generated/graphql';
-import { MemoryRouterDecorator } from '~/testing/decorators/MemoryRouterDecorator';
-
-import { PhoneFieldDisplay } from '../PhoneFieldDisplay';
-
-const PhoneFieldValueSetterEffect = ({ value }: { value: string }) => {
- const { setFieldValue } = usePhoneField();
-
- useEffect(() => {
- setFieldValue(value);
- }, [setFieldValue, value]);
-
- return null;
-};
-
-const meta: Meta = {
- title: 'UI/Data/Field/Display/PhoneFieldDisplay',
- decorators: [
- MemoryRouterDecorator,
- (Story, { args }) => (
- [() => undefined, {}],
- }}
- >
-
-
-
- ),
- ComponentDecorator,
- ],
- component: PhoneFieldDisplay,
- args: {
- value: '362763872687362',
- },
-};
-
-export default meta;
-
-type Story = StoryObj;
-
-export const Default: Story = {};
-
-export const Elipsis: Story = {
- parameters: {
- container: { width: 50 },
- },
-};
diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/ChipFieldDisplay.perf.stories.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/ChipFieldDisplay.perf.stories.tsx
new file mode 100644
index 0000000000..ad1235d241
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/ChipFieldDisplay.perf.stories.tsx
@@ -0,0 +1,36 @@
+import { Meta, StoryObj } from '@storybook/react';
+import { ComponentDecorator } from 'twenty-ui';
+
+import { ChipFieldDisplay } from '@/object-record/record-field/meta-types/display/components/ChipFieldDisplay';
+import { ChipGeneratorsDecorator } from '~/testing/decorators/ChipGeneratorsDecorator';
+import { getFieldDecorator } from '~/testing/decorators/getFieldDecorator';
+import { MemoryRouterDecorator } from '~/testing/decorators/MemoryRouterDecorator';
+import { getProfilingStory } from '~/testing/profiling/utils/getProfilingStory';
+
+const meta: Meta = {
+ title: 'UI/Data/Field/Display/ChipFieldDisplay',
+ decorators: [
+ MemoryRouterDecorator,
+ ChipGeneratorsDecorator,
+ getFieldDecorator('person', 'name'),
+ ComponentDecorator,
+ ],
+ component: ChipFieldDisplay,
+ args: {},
+ parameters: {
+ chromatic: { disableSnapshot: true },
+ },
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {};
+
+export const Performance = getProfilingStory({
+ componentName: 'ChipFieldDisplay',
+ averageThresholdInMs: 0.2,
+ numberOfRuns: 20,
+ numberOfTestsPerRun: 100,
+});
diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/PhoneFieldDisplay.perf.stories.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/PhoneFieldDisplay.perf.stories.tsx
new file mode 100644
index 0000000000..ccccf51695
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/PhoneFieldDisplay.perf.stories.tsx
@@ -0,0 +1,47 @@
+import { Meta, StoryObj } from '@storybook/react';
+import { ComponentDecorator } from 'twenty-ui';
+
+import { PhoneFieldDisplay } from '@/object-record/record-field/meta-types/display/components/PhoneFieldDisplay';
+import { getFieldDecorator } from '~/testing/decorators/getFieldDecorator';
+import { MemoryRouterDecorator } from '~/testing/decorators/MemoryRouterDecorator';
+import { getProfilingStory } from '~/testing/profiling/utils/getProfilingStory';
+
+const meta: Meta = {
+ title: 'UI/Data/Field/Display/PhoneFieldDisplay',
+ decorators: [
+ MemoryRouterDecorator,
+ getFieldDecorator('person', 'phone'),
+ ComponentDecorator,
+ ],
+ component: PhoneFieldDisplay,
+ args: {},
+ parameters: {
+ chromatic: { disableSnapshot: true },
+ },
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {};
+
+export const Elipsis: Story = {
+ parameters: {
+ container: { width: 50 },
+ },
+};
+
+export const WrongNumber: Story = {
+ parameters: {
+ container: { width: 50 },
+ },
+ decorators: [getFieldDecorator('person', 'phone', 'sdklaskdj')],
+};
+
+export const Performance = getProfilingStory({
+ componentName: 'PhoneFieldDisplay',
+ averageThresholdInMs: 0.5,
+ numberOfRuns: 20,
+ numberOfTestsPerRun: 100,
+});
diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/RelationFieldDisplay.perf.stories.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/RelationFieldDisplay.perf.stories.tsx
index f12a1716ee..6c985926d9 100644
--- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/RelationFieldDisplay.perf.stories.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/RelationFieldDisplay.perf.stories.tsx
@@ -1,74 +1,21 @@
-import { useEffect } from 'react';
import { Meta, StoryObj } from '@storybook/react';
-import { useSetRecoilState } from 'recoil';
import { ComponentDecorator } from 'twenty-ui';
-import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
import { RelationFieldDisplay } from '@/object-record/record-field/meta-types/display/components/RelationFieldDisplay';
-import {
- RecordFieldValueSelectorContextProvider,
- useSetRecordValue,
-} from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
-import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
+import { ChipGeneratorsDecorator } from '~/testing/decorators/ChipGeneratorsDecorator';
+import { getFieldDecorator } from '~/testing/decorators/getFieldDecorator';
import { MemoryRouterDecorator } from '~/testing/decorators/MemoryRouterDecorator';
import { getProfilingStory } from '~/testing/profiling/utils/getProfilingStory';
-import { relationFieldDisplayMock } from './mock';
-
-const RelationFieldValueSetterEffect = () => {
- const setEntity = useSetRecoilState(
- recordStoreFamilyState(relationFieldDisplayMock.entityId),
- );
-
- const setRelationEntity = useSetRecoilState(
- recordStoreFamilyState(relationFieldDisplayMock.relationEntityId),
- );
-
- const setRecordValue = useSetRecordValue();
-
- useEffect(() => {
- setEntity(relationFieldDisplayMock.entityValue);
- setRelationEntity(relationFieldDisplayMock.relationFieldValue);
-
- setRecordValue(
- relationFieldDisplayMock.entityValue.id,
- relationFieldDisplayMock.entityValue,
- );
- setRecordValue(
- relationFieldDisplayMock.relationFieldValue.id,
- relationFieldDisplayMock.relationFieldValue,
- );
- }, [setEntity, setRelationEntity, setRecordValue]);
-
- return null;
-};
-
const meta: Meta = {
title: 'UI/Data/Field/Display/RelationFieldDisplay',
decorators: [
MemoryRouterDecorator,
- (Story) => (
-
-
-
-
-
-
- ),
+ ChipGeneratorsDecorator,
+ getFieldDecorator('person', 'company'),
ComponentDecorator,
],
component: RelationFieldDisplay,
- argTypes: { value: { control: 'date' } },
args: {},
parameters: {
chromatic: { disableSnapshot: true },
@@ -83,7 +30,7 @@ export const Default: Story = {};
export const Performance = getProfilingStory({
componentName: 'RelationFieldDisplay',
- averageThresholdInMs: 0.4,
+ averageThresholdInMs: 0.2,
numberOfRuns: 20,
numberOfTestsPerRun: 100,
});
diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/RelationFromManyFieldDisplay.perf.stories.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/RelationFromManyFieldDisplay.perf.stories.tsx
index 360abcf4c3..7c9ce09da8 100644
--- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/RelationFromManyFieldDisplay.perf.stories.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/RelationFromManyFieldDisplay.perf.stories.tsx
@@ -12,6 +12,7 @@ import {
useSetRecordValue,
} from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
+import { ChipGeneratorsDecorator } from '~/testing/decorators/ChipGeneratorsDecorator';
import { MemoryRouterDecorator } from '~/testing/decorators/MemoryRouterDecorator';
import { getProfilingStory } from '~/testing/profiling/utils/getProfilingStory';
@@ -52,6 +53,7 @@ const meta: Meta = {
title: 'UI/Data/Field/Display/RelationFromManyFieldDisplay',
decorators: [
MemoryRouterDecorator,
+ ChipGeneratorsDecorator,
(Story) => (
{
+ const { entityId, fieldDefinition } = useContext(FieldContext);
+
+ const { chipGeneratorPerObjectPerField } = useContext(
+ PreComputedChipGeneratorsContext,
+ );
+
+ if (!isDefined(chipGeneratorPerObjectPerField)) {
+ throw new Error('Chip generator per object per field is not defined');
+ }
+
+ const objectNameSingular =
+ isFieldText(fieldDefinition) ||
+ isFieldFullName(fieldDefinition) ||
+ isFieldNumber(fieldDefinition)
+ ? fieldDefinition.metadata.objectMetadataNameSingular
+ : undefined;
+
+ const recordValue = useRecordValue(entityId);
+
+ if (!isNonEmptyString(fieldDefinition.metadata.objectMetadataNameSingular)) {
+ throw new Error('Object metadata name singular is not a non-empty string');
+ }
+
+ const generateRecordChipData =
+ chipGeneratorPerObjectPerField[
+ fieldDefinition.metadata.objectMetadataNameSingular
+ ][fieldDefinition.metadata.fieldName];
+
+ return {
+ objectNameSingular,
+ recordValue,
+ generateRecordChipData,
+ };
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/usePhoneFieldDisplay.ts b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/usePhoneFieldDisplay.ts
new file mode 100644
index 0000000000..e96a81f3cf
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/usePhoneFieldDisplay.ts
@@ -0,0 +1,19 @@
+import { useContext } from 'react';
+
+import { useRecordFieldValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
+
+import { FieldContext } from '../../contexts/FieldContext';
+
+export const usePhoneFieldDisplay = () => {
+ const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
+
+ const fieldName = fieldDefinition.metadata.fieldName;
+
+ const fieldValue = useRecordFieldValue(entityId, fieldName);
+
+ return {
+ fieldDefinition,
+ fieldValue,
+ hotkeyScope,
+ };
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useRelationFieldDisplay.ts b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useRelationFieldDisplay.ts
index d51f7980bc..546a6ba43c 100644
--- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useRelationFieldDisplay.ts
+++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useRelationFieldDisplay.ts
@@ -1,9 +1,8 @@
import { useContext } from 'react';
+import { isNonEmptyString } from '@sniptt/guards';
-import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
-import { getObjectRecordIdentifier } from '@/object-metadata/utils/getObjectRecordIdentifier';
+import { PreComputedChipGeneratorsContext } from '@/object-metadata/context/PreComputedChipGeneratorsContext';
import { useRecordFieldValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
-import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { FIELD_EDIT_BUTTON_WIDTH } from '@/ui/field/display/constants/FieldEditButtonWidth';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { isDefined } from '~/utils/isDefined';
@@ -15,6 +14,14 @@ import { isFieldRelation } from '../../types/guards/isFieldRelation';
export const useRelationFieldDisplay = () => {
const { entityId, fieldDefinition, maxWidth } = useContext(FieldContext);
+ const { chipGeneratorPerObjectPerField } = useContext(
+ PreComputedChipGeneratorsContext,
+ );
+
+ if (!isDefined(chipGeneratorPerObjectPerField)) {
+ throw new Error('Chip generator per object per field is not defined');
+ }
+
assertFieldMetadata(
FieldMetadataType.Relation,
isFieldRelation,
@@ -32,18 +39,14 @@ export const useRelationFieldDisplay = () => {
? maxWidth - FIELD_EDIT_BUTTON_WIDTH
: maxWidth;
- const { objectMetadataItem: relationObjectMetadataItem } =
- useObjectMetadataItem({
- objectNameSingular:
- fieldDefinition.metadata.relationObjectMetadataNameSingular,
- });
+ if (!isNonEmptyString(fieldDefinition.metadata.objectMetadataNameSingular)) {
+ throw new Error('Object metadata name singular is not a non-empty string');
+ }
- const generateRecordChipData = (record: ObjectRecord) => {
- return getObjectRecordIdentifier({
- objectMetadataItem: relationObjectMetadataItem,
- record,
- });
- };
+ const generateRecordChipData =
+ chipGeneratorPerObjectPerField[
+ fieldDefinition.metadata.objectMetadataNameSingular
+ ][fieldDefinition.metadata.fieldName];
return {
fieldDefinition,
diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/RecordChipData.ts b/packages/twenty-front/src/modules/object-record/record-field/types/RecordChipData.ts
index 77c80b6098..13eb99f84c 100644
--- a/packages/twenty-front/src/modules/object-record/record-field/types/RecordChipData.ts
+++ b/packages/twenty-front/src/modules/object-record/record-field/types/RecordChipData.ts
@@ -1,6 +1,7 @@
import { AvatarType } from 'twenty-ui';
export type RecordChipData = {
+ recordId: string;
name: string | number;
avatarType: AvatarType;
avatarUrl: string;
diff --git a/packages/twenty-front/src/modules/object-record/record-store/contexts/RecordFieldValueSelectorContext.tsx b/packages/twenty-front/src/modules/object-record/record-store/contexts/RecordFieldValueSelectorContext.tsx
index d3d9b7a32d..3f7c074142 100644
--- a/packages/twenty-front/src/modules/object-record/record-store/contexts/RecordFieldValueSelectorContext.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-store/contexts/RecordFieldValueSelectorContext.tsx
@@ -1,6 +1,8 @@
import { Dispatch, SetStateAction, useState } from 'react';
import { createContext, useContextSelector } from 'use-context-selector';
+import { ObjectRecord } from '@/object-record/types/ObjectRecord';
+
export type RecordFieldValue = {
[recordId: string]: {
[fieldName: string]: any;
@@ -31,7 +33,7 @@ export const useRecordValue = (recordId: string) => {
(value) => value[0],
);
- return tableValue?.[recordId];
+ return tableValue?.[recordId] as ObjectRecord | undefined;
};
export const useRecordFieldValue = (recordId: string, fieldName: string) => {
diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx
index 9c0bf8b7ba..487465b609 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx
@@ -17,6 +17,7 @@ import { RecordTableCellContext } from '@/object-record/record-table/contexts/Re
import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext';
import { RecordTableRowContext } from '@/object-record/record-table/contexts/RecordTableRowContext';
import { RecordTableScope } from '@/object-record/record-table/scopes/RecordTableScope';
+import { ChipGeneratorsDecorator } from '~/testing/decorators/ChipGeneratorsDecorator';
import { MemoryRouterDecorator } from '~/testing/decorators/MemoryRouterDecorator';
import { getProfilingStory } from '~/testing/profiling/utils/getProfilingStory';
@@ -57,6 +58,7 @@ const meta: Meta = {
title: 'RecordIndex/Table/RecordTableCell',
decorators: [
MemoryRouterDecorator,
+ ChipGeneratorsDecorator,
(Story) => {
return (
@@ -143,7 +145,7 @@ export const Default: Story = {};
export const Performance = getProfilingStory({
componentName: 'RecordTableCell',
- averageThresholdInMs: 0.6,
+ averageThresholdInMs: 0.3,
numberOfRuns: 50,
numberOfTestsPerRun: 200,
warmUpRounds: 20,
diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordChipDataGenerator.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordChipDataGenerator.ts
deleted file mode 100644
index dd8cd1c58a..0000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordChipDataGenerator.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-import { useMemo } from 'react';
-
-import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
-import { getAvatarType } from '@/object-metadata/utils/getAvatarType';
-import { getAvatarUrl } from '@/object-metadata/utils/getAvatarUrl';
-import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem';
-import { getLabelIdentifierFieldValue } from '@/object-metadata/utils/getLabelIdentifierFieldValue';
-import { getLinkToShowPage } from '@/object-metadata/utils/getLinkToShowPage';
-import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
-import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation';
-import { RecordChipData } from '@/object-record/record-field/types/RecordChipData';
-import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
-import { ObjectRecord } from '@/object-record/types/ObjectRecord';
-import { FieldMetadataType } from '~/generated-metadata/graphql';
-import { isDefined } from '~/utils/isDefined';
-
-export const useRecordChipDataGenerator = ({
- objectNameSingular,
- visibleTableColumns,
-}: {
- objectNameSingular: string;
- visibleTableColumns: ColumnDefinition[];
-}) => {
- const { objectMetadataItems } = useObjectMetadataItems();
-
- return useMemo(() => {
- return Object.fromEntries<(record: ObjectRecord) => RecordChipData>(
- visibleTableColumns
- .filter(
- (tableColumn) =>
- tableColumn.isLabelIdentifier ||
- tableColumn.type === FieldMetadataType.Relation,
- )
- .map((tableColumn) => {
- const objectNameSingularToFind = tableColumn.isLabelIdentifier
- ? objectNameSingular
- : isFieldRelation(tableColumn)
- ? tableColumn.metadata.relationObjectMetadataNameSingular
- : undefined;
-
- const objectMetadataItem = objectMetadataItems.find(
- (objectMetadataItem) =>
- objectMetadataItem.nameSingular === objectNameSingularToFind,
- );
-
- if (
- !isDefined(objectMetadataItem) ||
- !isDefined(objectNameSingularToFind)
- ) {
- return ['', () => ({}) as any];
- }
-
- const labelIdentifierFieldMetadataItem =
- getLabelIdentifierFieldMetadataItem(objectMetadataItem);
-
- const imageIdentifierFieldMetadata = objectMetadataItem.fields.find(
- (field) =>
- field.id === objectMetadataItem.imageIdentifierFieldMetadataId,
- );
-
- const avatarType = getAvatarType(objectNameSingularToFind);
-
- return [
- tableColumn.metadata.fieldName,
- (record: ObjectRecord) => ({
- name: getLabelIdentifierFieldValue(
- record,
- labelIdentifierFieldMetadataItem,
- objectMetadataItem.nameSingular,
- ),
- avatarUrl: getAvatarUrl(
- objectMetadataItem.nameSingular,
- record,
- imageIdentifierFieldMetadata,
- ),
- avatarType,
- linkToShowPage: getLinkToShowPage(
- objectMetadataItem.nameSingular,
- record,
- ),
- }),
- ];
- }),
- );
- }, [objectNameSingular, visibleTableColumns, objectMetadataItems]);
-};
diff --git a/packages/twenty-front/src/modules/object-record/utils/getRecordChipGeneratorPerObjectPerField.ts b/packages/twenty-front/src/modules/object-record/utils/getRecordChipGeneratorPerObjectPerField.ts
new file mode 100644
index 0000000000..f127e275ec
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/utils/getRecordChipGeneratorPerObjectPerField.ts
@@ -0,0 +1,116 @@
+import { ChipGeneratorPerObjectPerField } from '@/object-metadata/context/PreComputedChipGeneratorsContext';
+import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
+import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
+import { getAvatarType } from '@/object-metadata/utils/getAvatarType';
+import { getAvatarUrl } from '@/object-metadata/utils/getAvatarUrl';
+import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem';
+import { getLabelIdentifierFieldValue } from '@/object-metadata/utils/getLabelIdentifierFieldValue';
+import { getLinkToShowPage } from '@/object-metadata/utils/getLinkToShowPage';
+import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField';
+import { isFieldFullName } from '@/object-record/record-field/types/guards/isFieldFullName';
+import { isFieldNumber } from '@/object-record/record-field/types/guards/isFieldNumber';
+import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation';
+import { isFieldText } from '@/object-record/record-field/types/guards/isFieldText';
+import { RecordChipData } from '@/object-record/record-field/types/RecordChipData';
+import { ObjectRecord } from '@/object-record/types/ObjectRecord';
+import { FieldMetadataType } from '~/generated-metadata/graphql';
+import { isDefined } from '~/utils/isDefined';
+
+export const isFieldChipDisplay = (
+ field: Pick,
+ isLabelIdentifier: boolean,
+) =>
+ isLabelIdentifier &&
+ (isFieldText(field) || isFieldFullName(field) || isFieldNumber(field));
+
+export const getRecordChipGeneratorPerObjectPerField = (
+ objectMetadataItems: ObjectMetadataItem[],
+) => {
+ const recordChipGeneratorPerObjectPerField: ChipGeneratorPerObjectPerField =
+ {};
+
+ for (const objectMetadataItem of objectMetadataItems) {
+ const generatorPerField = Object.fromEntries<
+ (record: ObjectRecord) => RecordChipData
+ >(
+ objectMetadataItem.fields
+ .filter(
+ (fieldMetadataItem) =>
+ isLabelIdentifierField({
+ fieldMetadataItem: fieldMetadataItem,
+ objectMetadataItem,
+ }) ||
+ fieldMetadataItem.type === FieldMetadataType.Relation ||
+ isFieldChipDisplay(
+ fieldMetadataItem,
+ isLabelIdentifierField({
+ fieldMetadataItem: fieldMetadataItem,
+ objectMetadataItem,
+ }),
+ ),
+ )
+ .map((fieldMetadataItem) => {
+ const objectNameSingularToFind = isLabelIdentifierField({
+ fieldMetadataItem: fieldMetadataItem,
+ objectMetadataItem: objectMetadataItem,
+ })
+ ? objectMetadataItem.nameSingular
+ : isFieldRelation(fieldMetadataItem)
+ ? fieldMetadataItem.relationDefinition?.targetObjectMetadata
+ .nameSingular ?? undefined
+ : undefined;
+
+ const objectMetadataItemToUse = objectMetadataItems.find(
+ (objectMetadataItem) =>
+ objectMetadataItem.nameSingular === objectNameSingularToFind,
+ );
+
+ if (
+ !isDefined(objectMetadataItemToUse) ||
+ !isDefined(objectNameSingularToFind)
+ ) {
+ return ['', () => ({}) as any];
+ }
+
+ const labelIdentifierFieldMetadataItem =
+ getLabelIdentifierFieldMetadataItem(objectMetadataItemToUse);
+
+ const imageIdentifierFieldMetadata =
+ objectMetadataItemToUse.fields.find(
+ (field) =>
+ field.id ===
+ objectMetadataItemToUse.imageIdentifierFieldMetadataId,
+ );
+
+ const avatarType = getAvatarType(objectNameSingularToFind);
+
+ return [
+ fieldMetadataItem.name,
+ (record: ObjectRecord) => ({
+ recordId: record.id,
+ name: getLabelIdentifierFieldValue(
+ record,
+ labelIdentifierFieldMetadataItem,
+ objectMetadataItemToUse.nameSingular,
+ ),
+ avatarUrl: getAvatarUrl(
+ objectMetadataItemToUse.nameSingular,
+ record,
+ imageIdentifierFieldMetadata,
+ ),
+ avatarType,
+ linkToShowPage: getLinkToShowPage(
+ objectMetadataItemToUse.nameSingular,
+ record,
+ ),
+ }),
+ ];
+ }),
+ );
+
+ recordChipGeneratorPerObjectPerField[objectMetadataItem.nameSingular] =
+ generatorPerField;
+ }
+
+ return recordChipGeneratorPerObjectPerField;
+};
diff --git a/packages/twenty-front/src/modules/people/types/Person.ts b/packages/twenty-front/src/modules/people/types/Person.ts
index fd5b75ad84..eef68681e2 100644
--- a/packages/twenty-front/src/modules/people/types/Person.ts
+++ b/packages/twenty-front/src/modules/people/types/Person.ts
@@ -2,24 +2,39 @@ export type Person = {
__typename: 'Person';
id: string;
createdAt: string;
- updatedAt: string;
- deletedAt: string | null;
+ updatedAt?: string;
+ deletedAt?: string | null;
name: {
+ __typename?: 'FullName';
firstName: string;
lastName: string;
};
- avatarUrl: string;
+ avatarUrl?: string;
jobTitle: string;
linkedinLink: {
+ __typename?: 'Link';
url: string;
label: string;
};
xLink: {
+ __typename?: 'Link';
url: string;
label: string;
};
city: string;
email: string;
phone: string;
- companyId: string;
+ companyId?: string;
+ position?: number;
+ links?: {
+ __typename: 'Links';
+ primaryLinkUrl: string;
+ primaryLinkLabel: '';
+ secondaryLinks?:
+ | {
+ url: string;
+ label: string;
+ }[]
+ | null;
+ };
};
diff --git a/packages/twenty-front/src/modules/ui/field/display/components/EllipsisDisplay.tsx b/packages/twenty-front/src/modules/ui/field/display/components/EllipsisDisplay.tsx
index 608019e93c..d5c336005f 100644
--- a/packages/twenty-front/src/modules/ui/field/display/components/EllipsisDisplay.tsx
+++ b/packages/twenty-front/src/modules/ui/field/display/components/EllipsisDisplay.tsx
@@ -1,4 +1,4 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
const StyledEllipsisDisplay = styled.div<{ maxWidth?: number }>`
max-width: ${({ maxWidth }) => maxWidth ?? '100%'};
@@ -19,7 +19,7 @@ export const EllipsisDisplay = ({
maxWidth,
className,
}: EllipsisDisplayProps) => (
-
+
{children}
);
diff --git a/packages/twenty-front/src/modules/ui/field/display/components/PhoneDisplay.tsx b/packages/twenty-front/src/modules/ui/field/display/components/PhoneDisplay.tsx
index b9e73c45da..f4cdc8519d 100644
--- a/packages/twenty-front/src/modules/ui/field/display/components/PhoneDisplay.tsx
+++ b/packages/twenty-front/src/modules/ui/field/display/components/PhoneDisplay.tsx
@@ -1,27 +1,39 @@
import { MouseEvent } from 'react';
-import { isValidPhoneNumber, parsePhoneNumber } from 'libphonenumber-js';
+import { parsePhoneNumber, PhoneNumber } from 'libphonenumber-js';
import { ContactLink } from '@/ui/navigation/link/components/ContactLink';
-
-import { EllipsisDisplay } from './EllipsisDisplay';
+import { isDefined } from '~/utils/isDefined';
type PhoneDisplayProps = {
value: string | null;
};
-export const PhoneDisplay = ({ value }: PhoneDisplayProps) => (
-
- {value && isValidPhoneNumber(value) ? (
- ) => {
- event.stopPropagation();
- }}
- >
- {parsePhoneNumber(value, 'FR')?.formatNational() || value}
-
- ) : (
- {value}
- )}
-
-);
+// TODO: see if we can find a faster way to format the phone number
+export const PhoneDisplay = ({ value }: PhoneDisplayProps) => {
+ if (!isDefined(value)) {
+ return {value};
+ }
+
+ let parsedPhoneNumber: PhoneNumber | null = null;
+
+ try {
+ // TODO: parse according to locale not hard coded FR
+ parsedPhoneNumber = parsePhoneNumber(value, 'FR');
+ } catch (error) {
+ return {value};
+ }
+
+ const URI = parsedPhoneNumber.getURI();
+ const formattedNational = parsedPhoneNumber?.formatNational();
+
+ return (
+ ) => {
+ event.stopPropagation();
+ }}
+ >
+ {formattedNational || value}
+
+ );
+};
diff --git a/packages/twenty-front/src/modules/ui/field/display/components/__stories__/EllipsisDisplay.stories.tsx b/packages/twenty-front/src/modules/ui/field/display/components/__stories__/EllipsisDisplay.stories.tsx
deleted file mode 100644
index d331c13145..0000000000
--- a/packages/twenty-front/src/modules/ui/field/display/components/__stories__/EllipsisDisplay.stories.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import { Meta, StoryObj } from '@storybook/react';
-import { ComponentDecorator } from 'twenty-ui';
-
-import { EllipsisDisplay } from '@/ui/field/display/components/EllipsisDisplay';
-
-const meta: Meta = {
- title: 'UI/Input/EllipsisDisplay/EllipsisDisplay',
- component: EllipsisDisplay,
- decorators: [ComponentDecorator],
- args: {
- maxWidth: 100,
- children: 'This is a long text that should be truncated',
- },
-};
-
-export default meta;
-
-type Story = StoryObj;
-
-export const Default: Story = {};
diff --git a/packages/twenty-front/src/modules/ui/field/display/components/__stories__/perf/EllipsisDisplay.perf.stories.tsx b/packages/twenty-front/src/modules/ui/field/display/components/__stories__/perf/EllipsisDisplay.perf.stories.tsx
index 7bc88fff54..98d66dc2d2 100644
--- a/packages/twenty-front/src/modules/ui/field/display/components/__stories__/perf/EllipsisDisplay.perf.stories.tsx
+++ b/packages/twenty-front/src/modules/ui/field/display/components/__stories__/perf/EllipsisDisplay.perf.stories.tsx
@@ -1,4 +1,4 @@
-import { Meta } from '@storybook/react';
+import { Meta, StoryObj } from '@storybook/react';
import { ComponentDecorator } from 'twenty-ui';
import { EllipsisDisplay } from '@/ui/field/display/components/EllipsisDisplay';
@@ -19,6 +19,10 @@ const meta: Meta = {
export default meta;
+type Story = StoryObj;
+
+export const Default: Story = {};
+
export const Performance = getProfilingStory({
componentName: 'EllipsisDisplay',
averageThresholdInMs: 0.1,
diff --git a/packages/twenty-front/src/modules/ui/navigation/link/components/ContactLink.tsx b/packages/twenty-front/src/modules/ui/navigation/link/components/ContactLink.tsx
index 4afea7333b..6508c0dc56 100644
--- a/packages/twenty-front/src/modules/ui/navigation/link/components/ContactLink.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/link/components/ContactLink.tsx
@@ -1,43 +1,47 @@
import * as React from 'react';
-import { Link as ReactLink } from 'react-router-dom';
-import styled from '@emotion/styled';
+import { Theme, withTheme } from '@emotion/react';
+import { styled } from '@linaria/react';
+
+const StyledClickableLink = withTheme(styled.a<{
+ theme: Theme;
+ maxWidth?: number;
+}>`
+ color: inherit;
+ overflow: hidden;
+ text-decoration: underline;
+ text-decoration-color: ${({ theme }) => theme.border.color.strong};
+ text-overflow: ellipsis;
+
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ width: 100%;
+
+ max-width: ${({ maxWidth }) => maxWidth ?? '100%'};
+
+ &:hover {
+ text-decoration-color: ${({ theme }) => theme.font.color.primary};
+ }
+`);
type ContactLinkProps = {
- className?: string;
href: string;
children?: React.ReactNode;
onClick?: (event: React.MouseEvent) => void;
+ maxWidth?: number;
};
-const StyledClickable = styled.div`
- display: flex;
- overflow: hidden;
- white-space: nowrap;
-
- a {
- color: inherit;
- overflow: hidden;
- text-decoration: underline;
- text-decoration-color: ${({ theme }) => theme.border.color.strong};
- text-overflow: ellipsis;
-
- &:hover {
- text-decoration-color: ${({ theme }) => theme.font.color.primary};
- }
- }
-`;
-
export const ContactLink = ({
- className,
href,
children,
onClick,
+ maxWidth,
}: ContactLinkProps) => (
-
-
-
- {children}
-
-
-
+
+ {children}
+
);
diff --git a/packages/twenty-front/src/modules/ui/navigation/link/components/__stories__/ContactLink.stories.tsx b/packages/twenty-front/src/modules/ui/navigation/link/components/__stories__/ContactLink.stories.tsx
index c139f409fa..f4bcf867b5 100644
--- a/packages/twenty-front/src/modules/ui/navigation/link/components/__stories__/ContactLink.stories.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/link/components/__stories__/ContactLink.stories.tsx
@@ -10,7 +10,6 @@ const meta: Meta = {
component: ContactLink,
decorators: [ComponentWithRouterDecorator],
args: {
- className: 'ContactLink',
href: '/test',
children: 'Contact Link',
},
diff --git a/packages/twenty-front/src/modules/workspace-member/types/WorkspaceMember.ts b/packages/twenty-front/src/modules/workspace-member/types/WorkspaceMember.ts
index fffbc97e90..83f029206a 100644
--- a/packages/twenty-front/src/modules/workspace-member/types/WorkspaceMember.ts
+++ b/packages/twenty-front/src/modules/workspace-member/types/WorkspaceMember.ts
@@ -4,6 +4,7 @@ export type WorkspaceMember = {
__typename: 'WorkspaceMember';
id: string;
name: {
+ __typename?: 'FullName';
firstName: string;
lastName: string;
};
diff --git a/packages/twenty-front/src/testing/decorators/ChipGeneratorsDecorator.tsx b/packages/twenty-front/src/testing/decorators/ChipGeneratorsDecorator.tsx
new file mode 100644
index 0000000000..6f9ac5d305
--- /dev/null
+++ b/packages/twenty-front/src/testing/decorators/ChipGeneratorsDecorator.tsx
@@ -0,0 +1,24 @@
+import { useMemo } from 'react';
+import { Decorator } from '@storybook/react';
+
+import { PreComputedChipGeneratorsContext } from '@/object-metadata/context/PreComputedChipGeneratorsContext';
+import { getRecordChipGeneratorPerObjectPerField } from '@/object-record/utils/getRecordChipGeneratorPerObjectPerField';
+import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems';
+
+export const ChipGeneratorsDecorator: Decorator = (Story) => {
+ const chipGeneratorPerObjectPerField = useMemo(() => {
+ return getRecordChipGeneratorPerObjectPerField(
+ generatedMockObjectMetadataItems,
+ );
+ }, []);
+
+ return (
+
+
+
+ );
+};
diff --git a/packages/twenty-front/src/testing/decorators/ObjectMetadataItemsDecorator.tsx b/packages/twenty-front/src/testing/decorators/ObjectMetadataItemsDecorator.tsx
index c54ff5dd13..9c27a82e35 100644
--- a/packages/twenty-front/src/testing/decorators/ObjectMetadataItemsDecorator.tsx
+++ b/packages/twenty-front/src/testing/decorators/ObjectMetadataItemsDecorator.tsx
@@ -1,11 +1,13 @@
-import { useEffect } from 'react';
+import { useEffect, useMemo } from 'react';
import { Decorator } from '@storybook/react';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { currentUserState } from '@/auth/states/currentUserState';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { ObjectMetadataItemsLoadEffect } from '@/object-metadata/components/ObjectMetadataItemsLoadEffect';
+import { PreComputedChipGeneratorsContext } from '@/object-metadata/context/PreComputedChipGeneratorsContext';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
+import { getRecordChipGeneratorPerObjectPerField } from '@/object-record/utils/getRecordChipGeneratorPerObjectPerField';
import { mockedUsersData } from '~/testing/mock-data/users';
import { mockWorkspaceMembers } from '~/testing/mock-data/workspace-members';
@@ -21,10 +23,20 @@ export const ObjectMetadataItemsDecorator: Decorator = (Story) => {
setCurrentUser(mockedUsersData[0]);
}, [setCurrentUser, setCurrentWorkspaceMember]);
+ const chipGeneratorPerObjectPerField = useMemo(() => {
+ return getRecordChipGeneratorPerObjectPerField(objectMetadataItems);
+ }, [objectMetadataItems]);
+
return (
<>
- {!!objectMetadataItems.length && }
+
+ {!!objectMetadataItems.length && }
+
>
);
};
diff --git a/packages/twenty-front/src/testing/decorators/getFieldDecorator.tsx b/packages/twenty-front/src/testing/decorators/getFieldDecorator.tsx
new file mode 100644
index 0000000000..b0de8bcefb
--- /dev/null
+++ b/packages/twenty-front/src/testing/decorators/getFieldDecorator.tsx
@@ -0,0 +1,125 @@
+import { useEffect } from 'react';
+import { Decorator } from '@storybook/react';
+import { useRecoilCallback } from 'recoil';
+
+import { Company } from '@/companies/types/Company';
+import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition';
+import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField';
+import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
+import {
+ RecordFieldValueSelectorContextProvider,
+ useSetRecordValue,
+} from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
+import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
+import { ObjectRecord } from '@/object-record/types/ObjectRecord';
+import { Person } from '@/people/types/Person';
+import { mockedCompaniesDataV2 } from '~/testing/mock-data/companiesV2';
+import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems';
+import { mockPeopleDataV2 } from '~/testing/mock-data/peopleV2';
+import { isDefined } from '~/utils/isDefined';
+
+const RecordMockSetterEffect = ({
+ companies,
+ people,
+}: {
+ companies: Company[];
+ people: Person[];
+}) => {
+ const setRecordValue = useSetRecordValue();
+
+ const setRecordInBothStores = useRecoilCallback(
+ ({ set }) =>
+ (record: ObjectRecord) => {
+ set(recordStoreFamilyState(record.id), record);
+ setRecordValue(record.id, record);
+ },
+ [setRecordValue],
+ );
+
+ useEffect(() => {
+ for (const company of companies) {
+ setRecordInBothStores(company);
+ }
+
+ for (const person of people) {
+ setRecordInBothStores(person);
+ }
+ }, [setRecordInBothStores, companies, people]);
+
+ return null;
+};
+
+export const getFieldDecorator =
+ (
+ objectNameSingular: 'company' | 'person',
+ fieldName: string,
+ fieldValue?: any,
+ ): Decorator =>
+ (Story) => {
+ const companies =
+ objectNameSingular === 'company' && isDefined(fieldValue)
+ ? [
+ { ...mockedCompaniesDataV2[0], [fieldName]: fieldValue },
+ ...mockedCompaniesDataV2.slice(1),
+ ]
+ : mockedCompaniesDataV2;
+
+ const people =
+ objectNameSingular === 'person' && isDefined(fieldValue)
+ ? [
+ { ...mockPeopleDataV2[0], [fieldName]: fieldValue },
+ ...mockPeopleDataV2.slice(1),
+ ]
+ : mockPeopleDataV2;
+
+ const record = objectNameSingular === 'company' ? companies[0] : people[0];
+
+ if (isDefined(fieldValue)) {
+ (record as any)[fieldName] = fieldValue;
+ }
+
+ const objectMetadataItem = generatedMockObjectMetadataItems.find(
+ (objectMetadataItem) =>
+ objectMetadataItem.nameSingular === objectNameSingular,
+ );
+
+ const fieldMetadataItem = objectMetadataItem?.fields.find(
+ (field) => field.name === fieldName,
+ );
+
+ if (!isDefined(objectMetadataItem)) {
+ throw new Error(`Object ${objectNameSingular} not found`);
+ }
+
+ if (!isDefined(fieldMetadataItem)) {
+ throw new Error(
+ `Field ${fieldName} not found in object ${objectNameSingular}`,
+ );
+ }
+
+ const isLabelIdentifier = isLabelIdentifierField({
+ fieldMetadataItem,
+ objectMetadataItem,
+ });
+
+ return (
+
+
+
+
+
+
+ );
+ };
diff --git a/packages/twenty-front/src/testing/hooks/useMockFieldContext.tsx b/packages/twenty-front/src/testing/hooks/useMockFieldContext.tsx
new file mode 100644
index 0000000000..278b5004f0
--- /dev/null
+++ b/packages/twenty-front/src/testing/hooks/useMockFieldContext.tsx
@@ -0,0 +1,78 @@
+import { ReactNode } from 'react';
+
+import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
+import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition';
+import { getBasePathToShowPage } from '@/object-metadata/utils/getBasePathToShowPage';
+import {
+ FieldContext,
+ RecordUpdateHook,
+} from '@/object-record/record-field/contexts/FieldContext';
+import { InlineCellHotkeyScope } from '@/object-record/record-inline-cell/types/InlineCellHotkeyScope';
+
+export const useMockFieldContext = ({
+ clearable,
+ fieldMetadataName,
+ fieldPosition,
+ isLabelIdentifier = false,
+ objectNameSingular,
+ objectRecordId,
+ customHotkeyScope,
+}: {
+ clearable?: boolean;
+ fieldMetadataName: string;
+ fieldPosition: number;
+ isLabelIdentifier?: boolean;
+ objectNameSingular: string;
+ objectRecordId: string;
+ customHotkeyScope?: string;
+}) => {
+ const { objectMetadataItem } = useObjectMetadataItem({
+ objectNameSingular,
+ });
+
+ const basePathToShowPage = getBasePathToShowPage({
+ objectNameSingular,
+ });
+
+ const fieldMetadataItem = objectMetadataItem?.fields.find(
+ (field) => field.name === fieldMetadataName,
+ );
+
+ const useUpdateOneObjectMutation: RecordUpdateHook = () => {
+ const updateEntity = () => {};
+
+ return [updateEntity, { loading: false }];
+ };
+
+ const FieldContextProvider =
+ fieldMetadataItem && objectMetadataItem
+ ? ({ children }: { children: ReactNode }) => (
+
+ {children}
+
+ )
+ : undefined;
+
+ return {
+ FieldContextProvider,
+ };
+};
diff --git a/packages/twenty-front/src/testing/mock-data/companiesV2.ts b/packages/twenty-front/src/testing/mock-data/companiesV2.ts
new file mode 100644
index 0000000000..ad19e3f4ea
--- /dev/null
+++ b/packages/twenty-front/src/testing/mock-data/companiesV2.ts
@@ -0,0 +1,493 @@
+import { Company } from '@/companies/types/Company';
+import { Favorite } from '@/favorites/types/Favorite';
+import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
+import { mockedCompaniesData } from '~/testing/mock-data/companies';
+
+type MockedCompanyV2 = Omit & {
+ accountOwner: WorkspaceMember | null;
+ Favorite?: Pick | null;
+};
+
+export const mockedCompaniesDataV2: Array = [
+ {
+ __typename: 'Company',
+ domainName: 'paris.com',
+ name: 'Test',
+ employees: null,
+ address: 'Paris France',
+ createdAt: '2024-05-27T11:23:05.954Z',
+ id: 'd55c240e-e4e0-4248-b56d-8004d1218a9c',
+ position: 6.109375,
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: 1000000000,
+ currencyCode: 'USD',
+ },
+ linkedinLink: {
+ __typename: 'Link',
+ label: '',
+ url: 'paris.com',
+ },
+ accountOwner: {
+ __typename: 'WorkspaceMember',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-1553-45c6-a028-5a9064cce07f',
+ colorScheme: 'Light',
+ updatedAt: '2024-05-01T13:16:29.046Z',
+ locale: 'en',
+ avatarUrl: '',
+ userId: '20202020-7169-42cf-bc47-1cfef15264b8',
+ userEmail: 'phil.schiler@apple.dev',
+ name: {
+ __typename: 'FullName',
+ firstName: 'Phil',
+ lastName: 'Shiler',
+ },
+ },
+ },
+ {
+ __typename: 'Company',
+ domainName: 'google.com',
+ name: 'Google',
+ employees: 10202,
+ address: 'Paris France',
+ createdAt: '2024-05-21T13:16:29.000Z',
+ id: '20202020-c21e-4ec2-873b-de4264d89025',
+ position: 7.5,
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: 1001000000,
+ currencyCode: 'USD',
+ },
+ linkedinLink: {
+ __typename: 'Link',
+ label: '',
+ url: '',
+ },
+ accountOwner: {
+ __typename: 'WorkspaceMember',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-0687-4c41-b707-ed1bfca972a7',
+ colorScheme: 'Light',
+ updatedAt: '2024-05-30T09:00:31.127Z',
+ locale: 'en',
+ avatarUrl: '',
+ userId: '20202020-9e3b-46d4-a556-88b9ddc2b034',
+ userEmail: 'tim@apple.dev',
+ name: {
+ __typename: 'FullName',
+ firstName: 'Tim',
+ lastName: 'Apple',
+ },
+ },
+ },
+ {
+ __typename: 'Company',
+ domainName: 'hasura.io',
+ name: 'Hasura',
+ employees: 102938102938,
+ address: '',
+ createdAt: '2024-05-16T13:16:29.000Z',
+ id: '20202020-f86b-419f-b794-02319abe8637',
+ position: 10,
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: null,
+ currencyCode: '',
+ },
+ linkedinLink: {
+ __typename: 'Link',
+ label: '',
+ url: '',
+ },
+ accountOwner: {
+ __typename: 'WorkspaceMember',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-77d5-4cb6-b60a-f4a835a85d61',
+ colorScheme: 'Light',
+ updatedAt: '2024-05-01T13:16:29.046Z',
+ locale: 'en',
+ avatarUrl: '',
+ userId: '20202020-3957-4908-9c36-2929a23f8357',
+ userEmail: 'jony.ive@apple.dev',
+ name: {
+ __typename: 'FullName',
+ firstName: 'Jony',
+ lastName: 'Ive',
+ },
+ },
+ },
+ {
+ __typename: 'Company',
+ domainName: 'netflix.com',
+ name: 'Netflix',
+ employees: null,
+ address: '',
+ createdAt: '2024-05-15T13:16:29.000Z',
+ id: '20202020-707e-44dc-a1d2-30030bf1a944',
+ position: 7,
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: 2000000000,
+ currencyCode: 'USD',
+ },
+ linkedinLink: {
+ __typename: 'Link',
+ label: '',
+ url: '',
+ },
+ accountOwner: {
+ __typename: 'WorkspaceMember',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-1553-45c6-a028-5a9064cce07f',
+ colorScheme: 'Light',
+ updatedAt: '2024-05-01T13:16:29.046Z',
+ locale: 'en',
+ avatarUrl: '',
+ userId: '20202020-7169-42cf-bc47-1cfef15264b8',
+ userEmail: 'phil.schiler@apple.dev',
+ name: {
+ __typename: 'FullName',
+ firstName: 'Phil',
+ lastName: 'Shiler',
+ },
+ },
+ },
+ {
+ __typename: 'Company',
+ domainName: 'claap.io',
+ name: 'Claap',
+ employees: 2131920,
+ address: 'asdasd',
+ createdAt: '2024-05-10T13:16:29.000Z',
+ id: '20202020-cfbf-4156-a790-e39854dcd4eb',
+ position: 9,
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: null,
+ currencyCode: '',
+ },
+ linkedinLink: {
+ __typename: 'Link',
+ label: '',
+ url: 'asmdlkasd',
+ },
+ accountOwner: {
+ __typename: 'WorkspaceMember',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-0687-4c41-b707-ed1bfca972a7',
+ colorScheme: 'Light',
+ updatedAt: '2024-05-30T09:00:31.127Z',
+ locale: 'en',
+ avatarUrl: '',
+ userId: '20202020-9e3b-46d4-a556-88b9ddc2b034',
+ userEmail: 'tim@apple.dev',
+ name: {
+ __typename: 'FullName',
+ firstName: 'Tim',
+ lastName: 'Apple',
+ },
+ },
+ },
+ {
+ __typename: 'Company',
+ domainName: 'libeo.io',
+ name: 'Libeo',
+ employees: 1239819238,
+ address: '',
+ createdAt: '2024-05-09T13:16:29.000Z',
+ id: '20202020-3f74-492d-a101-2a70f50a1645',
+ position: 8,
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: null,
+ currencyCode: '',
+ },
+ linkedinLink: {
+ __typename: 'Link',
+ label: '',
+ url: '',
+ },
+ accountOwner: {
+ __typename: 'WorkspaceMember',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-1553-45c6-a028-5a9064cce07f',
+ colorScheme: 'Light',
+ updatedAt: '2024-05-01T13:16:29.046Z',
+ locale: 'en',
+ avatarUrl: '',
+ userId: '20202020-7169-42cf-bc47-1cfef15264b8',
+ userEmail: 'phil.schiler@apple.dev',
+ name: {
+ __typename: 'FullName',
+ firstName: 'Phil',
+ lastName: 'Shiler',
+ },
+ },
+ },
+ {
+ __typename: 'Company',
+ domainName: 'qonto.com',
+ name: 'Qonto',
+ employees: 123123123,
+ address: '',
+ createdAt: '2024-05-08T13:16:29.000Z',
+ id: '20202020-0713-40a5-8216-82802401d33e',
+ position: 9.5,
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: null,
+ currencyCode: '',
+ },
+ linkedinLink: {
+ __typename: 'Link',
+ label: '',
+ url: '',
+ },
+ accountOwner: {
+ __typename: 'WorkspaceMember',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-1553-45c6-a028-5a9064cce07f',
+ colorScheme: 'Light',
+ updatedAt: '2024-05-01T13:16:29.046Z',
+ locale: 'en',
+ avatarUrl: '',
+ userId: '20202020-7169-42cf-bc47-1cfef15264b8',
+ userEmail: 'phil.schiler@apple.dev',
+ name: {
+ __typename: 'FullName',
+ firstName: 'Phil',
+ lastName: 'Shiler',
+ },
+ },
+ },
+ {
+ __typename: 'Company',
+ domainName: 'wework.com',
+ name: 'Wework',
+ employees: 123123123,
+ address: '',
+ createdAt: '2024-05-08T13:16:29.000Z',
+ id: '20202020-5518-4553-9433-42d8eb82834b',
+ position: 11,
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: null,
+ currencyCode: '',
+ },
+ linkedinLink: {
+ __typename: 'Link',
+ label: '',
+ url: '',
+ },
+ accountOwner: {
+ __typename: 'WorkspaceMember',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-0687-4c41-b707-ed1bfca972a7',
+ colorScheme: 'Light',
+ updatedAt: '2024-05-30T09:00:31.127Z',
+ locale: 'en',
+ avatarUrl: '',
+ userId: '20202020-9e3b-46d4-a556-88b9ddc2b034',
+ userEmail: 'tim@apple.dev',
+ name: {
+ __typename: 'FullName',
+ firstName: 'Tim',
+ lastName: 'Apple',
+ },
+ },
+ },
+ {
+ __typename: 'Company',
+ domainName: 'linkedin.com',
+ name: 'Linkedin',
+ employees: 10102,
+ accountOwner: null,
+ address: '',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-3ec3-4fe3-8997-b76aa0bfa408',
+ position: 1,
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: null,
+ currencyCode: '',
+ },
+ linkedinLink: {
+ __typename: 'Link',
+ label: 'adasd',
+ url: 'adasd',
+ },
+ },
+ {
+ __typename: 'Company',
+ domainName: 'airbnb.com',
+ name: 'Airbnb',
+ employees: 123333,
+ accountOwner: null,
+ address: '',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-171e-4bcc-9cf7-43448d6fb278',
+ position: 5,
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: null,
+ currencyCode: '',
+ },
+ linkedinLink: {
+ __typename: 'Link',
+ label: '',
+ url: '',
+ },
+ },
+ {
+ __typename: 'Company',
+ domainName: 'samsung.com',
+ name: 'Samsung',
+ employees: 10000,
+ address: '',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-f79e-40dd-bd06-c36e6abb4678',
+ position: 12,
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: null,
+ currencyCode: '',
+ },
+ linkedinLink: {
+ __typename: 'Link',
+ label: '',
+ url: '',
+ },
+ accountOwner: {
+ __typename: 'WorkspaceMember',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-1553-45c6-a028-5a9064cce07f',
+ colorScheme: 'Light',
+ updatedAt: '2024-05-01T13:16:29.046Z',
+ locale: 'en',
+ avatarUrl: '',
+ userId: '20202020-7169-42cf-bc47-1cfef15264b8',
+ userEmail: 'phil.schiler@apple.dev',
+ name: {
+ __typename: 'FullName',
+ firstName: 'Phil',
+ lastName: 'Shiler',
+ },
+ },
+ },
+ {
+ __typename: 'Company',
+ domainName: 'algolia.com',
+ name: 'Algolia',
+ employees: 10000,
+ address: '',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-1455-4c57-afaf-dd5dc086361d',
+ position: 13,
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: null,
+ currencyCode: '',
+ },
+ linkedinLink: {
+ __typename: 'Link',
+ label: '',
+ url: '',
+ },
+ accountOwner: {
+ __typename: 'WorkspaceMember',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-77d5-4cb6-b60a-f4a835a85d61',
+ colorScheme: 'Light',
+ updatedAt: '2024-05-01T13:16:29.046Z',
+ locale: 'en',
+ avatarUrl: '',
+ userId: '20202020-3957-4908-9c36-2929a23f8357',
+ userEmail: 'jony.ive@apple.dev',
+ name: {
+ __typename: 'FullName',
+ firstName: 'Jony',
+ lastName: 'Ive',
+ },
+ },
+ },
+ {
+ __typename: 'Company',
+ domainName: 'facebook.com',
+ name: 'Facebook',
+ employees: 220323,
+ accountOwner: null,
+ address: '',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-5d81-46d6-bf83-f7fd33ea6102',
+ position: 6.0625,
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: null,
+ currencyCode: '',
+ },
+ linkedinLink: {
+ __typename: 'Link',
+ label: '',
+ url: 'asdasd',
+ },
+ },
+ {
+ __typename: 'Company',
+ domainName: 'microsoft.com',
+ name: 'Microsoft',
+ employees: 10000,
+ address: '',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-ed89-413a-b31a-962986e67bb4',
+ position: 6.09375,
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: 10000000000,
+ currencyCode: 'USD',
+ },
+ linkedinLink: {
+ __typename: 'Link',
+ label: '',
+ url: '',
+ },
+ accountOwner: {
+ __typename: 'WorkspaceMember',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-0687-4c41-b707-ed1bfca972a7',
+ colorScheme: 'Light',
+ updatedAt: '2024-05-30T09:00:31.127Z',
+ locale: 'en',
+ avatarUrl: '',
+ userId: '20202020-9e3b-46d4-a556-88b9ddc2b034',
+ userEmail: 'tim@apple.dev',
+ name: {
+ __typename: 'FullName',
+ firstName: 'Tim',
+ lastName: 'Apple',
+ },
+ },
+ },
+];
+
+export const mockedDuplicateCompanyData: MockedCompanyV2 = {
+ ...mockedCompaniesData[0],
+ id: '8b40856a-2ec9-4c03-8bc0-c032c89e1824',
+};
+
+export const mockedEmptyCompanyData = {
+ id: '9231e6ee-4cc2-4c7b-8c55-dff16f4d968a',
+ name: '',
+ domainName: '',
+ address: '',
+ accountOwner: null,
+ annualRecurringRevenue: null,
+ createdAt: null,
+ updatedAt: null,
+ employees: null,
+ idealCustomerProfile: null,
+ linkedinLink: null,
+ xLink: null,
+ _activityCount: null,
+ __typename: 'Company',
+};
diff --git a/packages/twenty-front/src/testing/mock-data/generated/standard-metadata-query-result.ts b/packages/twenty-front/src/testing/mock-data/generated/standard-metadata-query-result.ts
index 85c091ded4..7adbd67f30 100644
--- a/packages/twenty-front/src/testing/mock-data/generated/standard-metadata-query-result.ts
+++ b/packages/twenty-front/src/testing/mock-data/generated/standard-metadata-query-result.ts
@@ -13249,3 +13249,4 @@ export const mockedStandardObjectMetadataQueryResult: ObjectMetadataItemsQuery =
] as ObjectEdge[],
},
} as ObjectMetadataItemsQuery;
+
diff --git a/packages/twenty-front/src/testing/mock-data/objectMetadataItems.ts b/packages/twenty-front/src/testing/mock-data/objectMetadataItems.ts
index b0de8f389d..e49af452c5 100644
--- a/packages/twenty-front/src/testing/mock-data/objectMetadataItems.ts
+++ b/packages/twenty-front/src/testing/mock-data/objectMetadataItems.ts
@@ -3,6 +3,13 @@ import {
FieldMetadataType,
RelationMetadataType,
} from '~/generated-metadata/graphql';
+import { mockedStandardObjectMetadataQueryResult } from '~/testing/mock-data/generated/standard-metadata-query-result';
+
+export const generatedMockObjectMetadataItems: ObjectMetadataItem[] =
+ mockedStandardObjectMetadataQueryResult.objects.edges.map((edge) => ({
+ ...edge.node,
+ fields: edge.node.fields.edges.map((edge) => edge.node),
+ }));
export const mockObjectMetadataItem: ObjectMetadataItem = {
__typename: 'object',
diff --git a/packages/twenty-front/src/testing/mock-data/people.ts b/packages/twenty-front/src/testing/mock-data/people.ts
index 9db0b32ead..1baec770db 100644
--- a/packages/twenty-front/src/testing/mock-data/people.ts
+++ b/packages/twenty-front/src/testing/mock-data/people.ts
@@ -1,11 +1,11 @@
import { Company } from '@/companies/types/Company';
import { Person } from '@/people/types/Person';
-type RequiredAndNotNull = {
+export type RequiredAndNotNull = {
[P in keyof T]-?: Exclude;
};
-type MockedPerson = RequiredAndNotNull<
+export type MockedPerson = RequiredAndNotNull<
Pick<
Person,
| '__typename'
diff --git a/packages/twenty-front/src/testing/mock-data/peopleV2.ts b/packages/twenty-front/src/testing/mock-data/peopleV2.ts
new file mode 100644
index 0000000000..066910f635
--- /dev/null
+++ b/packages/twenty-front/src/testing/mock-data/peopleV2.ts
@@ -0,0 +1,533 @@
+import { Company } from '@/companies/types/Company';
+import { Person } from '@/people/types/Person';
+
+export type MockedPersonV2 = Pick<
+ Person,
+ | '__typename'
+ | 'id'
+ | 'name'
+ | 'linkedinLink'
+ | 'xLink'
+ | 'links'
+ | 'jobTitle'
+ | 'email'
+ | 'phone'
+ | 'city'
+ | 'avatarUrl'
+ | 'createdAt'
+ | 'updatedAt'
+ | 'companyId'
+ | 'position'
+> & {
+ company?: Company;
+};
+
+export const mockPeopleDataV2: MockedPersonV2[] = [
+ {
+ __typename: 'Person',
+ city: 'Seattle',
+ jobTitle: '',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-1c0e-494c-a1b6-85b1c6fefaa5',
+ email: 'christoph.calisto@linkedin.com',
+ phone: '+33789012345',
+ position: 1,
+ name: {
+ __typename: 'FullName',
+ firstName: 'Christoph',
+ lastName: 'Callisto',
+ },
+ linkedinLink: { __typename: 'Link', label: '', url: 'asd' },
+ xLink: { __typename: 'Link', label: '', url: 'asd' },
+ company: {
+ __typename: 'Company',
+ domainName: 'linkedin.com',
+ name: 'Linkedin',
+ employees: 10102,
+ accountOwnerId: null,
+ address: '',
+ idealCustomerProfile: false,
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-3ec3-4fe3-8997-b76aa0bfa408',
+ position: 1,
+ updatedAt: '2024-05-23T13:21:41.159Z',
+ xLink: { __typename: 'Link', label: '', url: '' },
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: null,
+ currencyCode: '',
+ },
+ linkedinLink: { __typename: 'Link', label: 'adasd', url: 'adasd' },
+ },
+ },
+ {
+ __typename: 'Person',
+ city: 'Los Angeles',
+ jobTitle: '@',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-ac73-4797-824e-87a1f5aea9e0',
+ email: 'sylvie.palmer@linkedin.com',
+ phone: '+33780123456',
+ position: 2,
+ name: { __typename: 'FullName', firstName: 'Sylvie', lastName: 'Palmer' },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ xLink: { __typename: 'Link', label: '', url: '' },
+ company: {
+ __typename: 'Company',
+ domainName: 'algolia.com',
+ name: 'Algolia',
+ employees: 10000,
+ accountOwnerId: '20202020-77d5-4cb6-b60a-f4a835a85d61',
+ address: '',
+ idealCustomerProfile: false,
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-1455-4c57-afaf-dd5dc086361d',
+ position: 13,
+ updatedAt: '2024-05-28T15:52:31.839Z',
+ xLink: { __typename: 'Link', label: '', url: '' },
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: null,
+ currencyCode: '',
+ },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ },
+ },
+ {
+ __typename: 'Person',
+ city: 'Seattle',
+ jobTitle: '',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-f517-42fd-80ae-14173b3b70ae',
+ email: 'christopher.gonzalez@qonto.com',
+ phone: '+33789012345',
+ position: 3,
+ name: {
+ __typename: 'FullName',
+ firstName: 'Christopher',
+ lastName: 'Gonzalez',
+ },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ xLink: { __typename: 'Link', label: '', url: '' },
+ company: {
+ __typename: 'Company',
+ domainName: 'qonto.com',
+ name: 'Qonto',
+ employees: 123123123,
+ accountOwnerId: '20202020-1553-45c6-a028-5a9064cce07f',
+ address: '',
+ idealCustomerProfile: false,
+ createdAt: '2024-05-08T13:16:29.000Z',
+ id: '20202020-0713-40a5-8216-82802401d33e',
+ position: 9.5,
+ updatedAt: '2024-05-28T15:52:46.961Z',
+ xLink: { __typename: 'Link', label: '', url: '' },
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: null,
+ currencyCode: '',
+ },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ },
+ },
+ {
+ __typename: 'Person',
+ city: 'Los Angeles',
+ jobTitle: '',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-eee1-4690-ad2c-8619e5b56a2e',
+ email: 'ashley.parker@qonto.com',
+ phone: '+33780123456',
+ position: 4,
+ name: { __typename: 'FullName', firstName: 'Ashley', lastName: 'Parker' },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ xLink: { __typename: 'Link', label: '', url: '' },
+ company: {
+ __typename: 'Company',
+ domainName: 'qonto.com',
+ name: 'Qonto',
+ employees: 123123123,
+ accountOwnerId: '20202020-1553-45c6-a028-5a9064cce07f',
+ address: '',
+ idealCustomerProfile: false,
+ createdAt: '2024-05-08T13:16:29.000Z',
+ id: '20202020-0713-40a5-8216-82802401d33e',
+ position: 9.5,
+ updatedAt: '2024-05-28T15:52:46.961Z',
+ xLink: { __typename: 'Link', label: '', url: '' },
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: null,
+ currencyCode: '',
+ },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ },
+ },
+ {
+ __typename: 'Person',
+ city: 'Seattle',
+ jobTitle: '',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-6784-4449-afdf-dc62cb8702f2',
+ email: 'nicholas.wright@microsoft.com',
+ phone: '+33781234567',
+ position: 5,
+ name: { __typename: 'FullName', firstName: 'Nicholas', lastName: 'Wright' },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ xLink: { __typename: 'Link', label: '', url: '' },
+ company: {
+ __typename: 'Company',
+ domainName: 'microsoft.com',
+ name: 'Microsoft',
+ employees: 10000,
+ accountOwnerId: '20202020-0687-4c41-b707-ed1bfca972a7',
+ address: '',
+ idealCustomerProfile: false,
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-ed89-413a-b31a-962986e67bb4',
+ position: 6.09375,
+ updatedAt: '2024-05-28T15:52:35.621Z',
+ xLink: { __typename: 'Link', label: '', url: '' },
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: 10000000000,
+ currencyCode: 'USD',
+ },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ },
+ },
+ {
+ __typename: 'Person',
+ city: 'New York',
+ jobTitle: '',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-490f-4466-8391-733cfd66a0c8',
+ email: 'isabella.scott@microsoft.com',
+ phone: '+33782345678',
+ position: 6,
+ name: { __typename: 'FullName', firstName: 'Isabella', lastName: 'Scott' },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ xLink: { __typename: 'Link', label: '', url: '' },
+ company: {
+ __typename: 'Company',
+ domainName: 'microsoft.com',
+ name: 'Microsoft',
+ employees: 10000,
+ accountOwnerId: '20202020-0687-4c41-b707-ed1bfca972a7',
+ address: '',
+ idealCustomerProfile: false,
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-ed89-413a-b31a-962986e67bb4',
+ position: 6.09375,
+ updatedAt: '2024-05-28T15:52:35.621Z',
+ xLink: { __typename: 'Link', label: '', url: '' },
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: 10000000000,
+ currencyCode: 'USD',
+ },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ },
+ },
+ {
+ __typename: 'Person',
+ city: 'Seattle',
+ jobTitle: '',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-80f1-4dff-b570-a74942528de3',
+ email: 'matthew.green@microsoft.com',
+ phone: '+33783456789',
+ position: 7,
+ name: { __typename: 'FullName', firstName: 'Matthew', lastName: 'Green' },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ xLink: { __typename: 'Link', label: '', url: '' },
+ company: {
+ __typename: 'Company',
+ domainName: 'microsoft.com',
+ name: 'Microsoft',
+ employees: 10000,
+ accountOwnerId: '20202020-0687-4c41-b707-ed1bfca972a7',
+ address: '',
+ idealCustomerProfile: false,
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-ed89-413a-b31a-962986e67bb4',
+ position: 6.09375,
+ updatedAt: '2024-05-28T15:52:35.621Z',
+ xLink: { __typename: 'Link', label: '', url: '' },
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: 10000000000,
+ currencyCode: 'USD',
+ },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ },
+ },
+ {
+ __typename: 'Person',
+ city: 'New York',
+ jobTitle: '',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-338b-46df-8811-fa08c7d19d35',
+ email: 'elizabeth.baker@airbnb.com',
+ phone: '+33784567890',
+ position: 8,
+ name: { __typename: 'FullName', firstName: 'Elizabeth', lastName: 'Baker' },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ xLink: { __typename: 'Link', label: '', url: '' },
+ company: {
+ __typename: 'Company',
+ domainName: 'airbnb.com',
+ name: 'Airbnb',
+ employees: 123333,
+ accountOwnerId: null,
+ address: '',
+ idealCustomerProfile: false,
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-171e-4bcc-9cf7-43448d6fb278',
+ position: 5,
+ updatedAt: '2024-05-28T15:52:27.902Z',
+ xLink: { __typename: 'Link', label: '', url: '' },
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: null,
+ currencyCode: '',
+ },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ },
+ },
+ {
+ __typename: 'Person',
+ city: 'San Francisco',
+ jobTitle: '',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-64ad-4b0e-bbfd-e9fd795b7016',
+ email: 'christopher.nelson@airbnb.com',
+ phone: '+33785678901',
+ position: 9,
+ name: {
+ __typename: 'FullName',
+ firstName: 'Christopher',
+ lastName: 'Nelson',
+ },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ xLink: { __typename: 'Link', label: '', url: '' },
+ company: {
+ __typename: 'Company',
+ domainName: 'airbnb.com',
+ name: 'Airbnb',
+ employees: 123333,
+ accountOwnerId: null,
+ address: '',
+ idealCustomerProfile: false,
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-171e-4bcc-9cf7-43448d6fb278',
+ position: 5,
+ updatedAt: '2024-05-28T15:52:27.902Z',
+ xLink: { __typename: 'Link', label: '', url: '' },
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: null,
+ currencyCode: '',
+ },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ },
+ },
+ {
+ __typename: 'Person',
+ city: 'New York',
+ jobTitle: '',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-5d54-41b7-ba36-f0d20e1417ae',
+ email: 'avery.carter@airbnb.com',
+ phone: '+33786789012',
+ position: 10,
+ name: { __typename: 'FullName', firstName: 'Avery', lastName: 'Carter' },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ xLink: { __typename: 'Link', label: '', url: '' },
+ company: {
+ __typename: 'Company',
+ domainName: 'airbnb.com',
+ name: 'Airbnb',
+ employees: 123333,
+ accountOwnerId: null,
+ address: '',
+ idealCustomerProfile: false,
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-171e-4bcc-9cf7-43448d6fb278',
+ position: 5,
+ updatedAt: '2024-05-28T15:52:27.902Z',
+ xLink: { __typename: 'Link', label: '', url: '' },
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: null,
+ currencyCode: '',
+ },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ },
+ },
+ {
+ __typename: 'Person',
+ city: 'Los Angeles',
+ jobTitle: '',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-623d-41fe-92e7-dd45b7c568e1',
+ email: 'ethan.mitchell@google.com',
+ phone: '+33787890123',
+ position: 11,
+ name: { __typename: 'FullName', firstName: 'Ethan', lastName: 'Mitchell' },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ xLink: { __typename: 'Link', label: '', url: '' },
+ company: {
+ __typename: 'Company',
+ domainName: 'google.com',
+ name: 'Google',
+ employees: 10202,
+ accountOwnerId: '20202020-0687-4c41-b707-ed1bfca972a7',
+ address: 'Paris France',
+ idealCustomerProfile: false,
+ createdAt: '2024-05-21T13:16:29.000Z',
+ id: '20202020-c21e-4ec2-873b-de4264d89025',
+ position: 7.5,
+ updatedAt: '2024-05-28T15:53:28.838Z',
+ xLink: { __typename: 'Link', label: '', url: '' },
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: 1001000000,
+ currencyCode: 'USD',
+ },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ },
+ },
+ {
+ __typename: 'Person',
+ city: 'Seattle',
+ jobTitle: '',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-2d40-4e49-8df4-9c6a049190ef',
+ email: 'madison.perez@google.com',
+ phone: '+33788901234',
+ position: 12,
+ name: { __typename: 'FullName', firstName: 'Madison', lastName: 'Perez' },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ xLink: { __typename: 'Link', label: '', url: '' },
+ company: {
+ __typename: 'Company',
+ domainName: 'google.com',
+ name: 'Google',
+ employees: 10202,
+ accountOwnerId: '20202020-0687-4c41-b707-ed1bfca972a7',
+ address: 'Paris France',
+ idealCustomerProfile: false,
+ createdAt: '2024-05-21T13:16:29.000Z',
+ id: '20202020-c21e-4ec2-873b-de4264d89025',
+ position: 7.5,
+ updatedAt: '2024-05-28T15:53:28.838Z',
+ xLink: { __typename: 'Link', label: '', url: '' },
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: 1001000000,
+ currencyCode: 'USD',
+ },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ },
+ },
+ {
+ __typename: 'Person',
+ city: 'Seattle',
+ jobTitle: '',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-2d40-4e49-8df4-9c6a049190df',
+ email: 'bertrand.voulzy@google.com',
+ phone: '+33788901234',
+ position: 13,
+ name: { __typename: 'FullName', firstName: 'Bertrand', lastName: 'Voulzy' },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ xLink: { __typename: 'Link', label: '', url: '' },
+ company: {
+ __typename: 'Company',
+ domainName: 'google.com',
+ name: 'Google',
+ employees: 10202,
+ accountOwnerId: '20202020-0687-4c41-b707-ed1bfca972a7',
+ address: 'Paris France',
+ idealCustomerProfile: false,
+ createdAt: '2024-05-21T13:16:29.000Z',
+ id: '20202020-c21e-4ec2-873b-de4264d89025',
+ position: 7.5,
+ updatedAt: '2024-05-28T15:53:28.838Z',
+ xLink: { __typename: 'Link', label: '', url: '' },
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: 1001000000,
+ currencyCode: 'USD',
+ },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ },
+ },
+ {
+ __typename: 'Person',
+ city: 'Seattle',
+ jobTitle: '',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-2d40-4e49-8df4-9c6a049191de',
+ email: 'louis.duss@google.com',
+ phone: '+33788901234',
+ position: 14,
+ name: { __typename: 'FullName', firstName: 'Louis', lastName: 'Duss' },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ xLink: { __typename: 'Link', label: '', url: '' },
+ company: {
+ __typename: 'Company',
+ domainName: 'google.com',
+ name: 'Google',
+ employees: 10202,
+ accountOwnerId: '20202020-0687-4c41-b707-ed1bfca972a7',
+ address: 'Paris France',
+ idealCustomerProfile: false,
+ createdAt: '2024-05-21T13:16:29.000Z',
+ id: '20202020-c21e-4ec2-873b-de4264d89025',
+ position: 7.5,
+ updatedAt: '2024-05-28T15:53:28.838Z',
+ xLink: { __typename: 'Link', label: '', url: '' },
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: 1001000000,
+ currencyCode: 'USD',
+ },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ },
+ },
+ {
+ __typename: 'Person',
+ city: 'Seattle',
+ jobTitle: '',
+ createdAt: '2024-05-01T13:16:29.046Z',
+ id: '20202020-2d40-4e49-8df4-9c6a049191df',
+ email: 'lorie.vladim@google.com',
+ phone: '+33788901235',
+ position: 15,
+ name: { __typename: 'FullName', firstName: 'Lorie', lastName: 'Vladim' },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ xLink: { __typename: 'Link', label: '', url: '' },
+ company: {
+ __typename: 'Company',
+ domainName: 'google.com',
+ name: 'Google',
+ employees: 10202,
+ accountOwnerId: '20202020-0687-4c41-b707-ed1bfca972a7',
+ address: 'Paris France',
+ idealCustomerProfile: false,
+ createdAt: '2024-05-21T13:16:29.000Z',
+ id: '20202020-c21e-4ec2-873b-de4264d89025',
+ position: 7.5,
+ updatedAt: '2024-05-28T15:53:28.838Z',
+ xLink: { __typename: 'Link', label: '', url: '' },
+ annualRecurringRevenue: {
+ __typename: 'Currency',
+ amountMicros: 1001000000,
+ currencyCode: 'USD',
+ },
+ linkedinLink: { __typename: 'Link', label: '', url: '' },
+ },
+ },
+];
diff --git a/packages/twenty-front/vite.config.ts b/packages/twenty-front/vite.config.ts
index 67dd65707a..b38c80ebcb 100644
--- a/packages/twenty-front/vite.config.ts
+++ b/packages/twenty-front/vite.config.ts
@@ -1,4 +1,5 @@
import react from '@vitejs/plugin-react-swc';
+import wyw from '@wyw-in-js/vite';
import path from 'path';
import { defineConfig, loadEnv } from 'vite';
import checker from 'vite-plugin-checker';
@@ -48,6 +49,12 @@ export default defineConfig(({ command, mode }) => {
}),
svgr(),
checker(checkers),
+ wyw({
+ include: ['**/EllipsisDisplay.tsx', '**/ContactLink.tsx'],
+ babelOptions: {
+ presets: ['@babel/preset-typescript', '@babel/preset-react'],
+ },
+ }),
],
build: {
diff --git a/yarn.lock b/yarn.lock
index 36d34c38e6..a95b93a370 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1516,6 +1516,16 @@ __metadata:
languageName: node
linkType: hard
+"@babel/code-frame@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/code-frame@npm:7.24.6"
+ dependencies:
+ "@babel/highlight": "npm:^7.24.6"
+ picocolors: "npm:^1.0.0"
+ checksum: c93c6d1763530f415218c31d07359364397f19b70026abdff766164c21ed352a931cf07f3102c5fb9e04792de319e332d68bcb1f7debef601a02197f90f9ba24
+ languageName: node
+ linkType: hard
+
"@babel/compat-data@npm:^7.20.5, @babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.23.3, @babel/compat-data@npm:^7.23.5":
version: 7.23.5
resolution: "@babel/compat-data@npm:7.23.5"
@@ -1648,6 +1658,15 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-annotate-as-pure@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/helper-annotate-as-pure@npm:7.24.6"
+ dependencies:
+ "@babel/types": "npm:^7.24.6"
+ checksum: 3fe446e3bd37e5e32152279c84ace4e83815e5b88b9e09a82a83974a0bb22e941d89db26b23aaab4c9eb0f9713772c2f6163feffc1bcb055c4cdb6b67e5dc82f
+ languageName: node
+ linkType: hard
+
"@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.22.15":
version: 7.22.15
resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.22.15"
@@ -1708,6 +1727,25 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-create-class-features-plugin@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/helper-create-class-features-plugin@npm:7.24.6"
+ dependencies:
+ "@babel/helper-annotate-as-pure": "npm:^7.24.6"
+ "@babel/helper-environment-visitor": "npm:^7.24.6"
+ "@babel/helper-function-name": "npm:^7.24.6"
+ "@babel/helper-member-expression-to-functions": "npm:^7.24.6"
+ "@babel/helper-optimise-call-expression": "npm:^7.24.6"
+ "@babel/helper-replace-supers": "npm:^7.24.6"
+ "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.24.6"
+ "@babel/helper-split-export-declaration": "npm:^7.24.6"
+ semver: "npm:^6.3.1"
+ peerDependencies:
+ "@babel/core": ^7.0.0
+ checksum: e6734671bc6a5f3cca4ec46e4cc70238e5a2fa063e51225c2be572f157119002af419b33ea0f846dbb1307370fe9f3aa92d199449abbea5e88e0262513c8a821
+ languageName: node
+ linkType: hard
+
"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.22.15, @babel/helper-create-regexp-features-plugin@npm:^7.22.5":
version: 7.22.15
resolution: "@babel/helper-create-regexp-features-plugin@npm:7.22.15"
@@ -1773,6 +1811,13 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-environment-visitor@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/helper-environment-visitor@npm:7.24.6"
+ checksum: fdcd18ac505ed71f40c05cc992b648a4495b0aa5310a774492a0f74d8dcf3579691102f516561a651d3de6c3a44fe64bfb3049d11c14c5857634ef1823ea409a
+ languageName: node
+ linkType: hard
+
"@babel/helper-function-name@npm:^7.22.5, @babel/helper-function-name@npm:^7.23.0":
version: 7.23.0
resolution: "@babel/helper-function-name@npm:7.23.0"
@@ -1783,6 +1828,16 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-function-name@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/helper-function-name@npm:7.24.6"
+ dependencies:
+ "@babel/template": "npm:^7.24.6"
+ "@babel/types": "npm:^7.24.6"
+ checksum: 5ba2f8db789b3f5a2b2239300a217aa212e303cd7bfad9c8b90563807f49215e8c679e8f8f177b6aaca2038038e29bc702b83839e1f7b4896d79c44a75cac97a
+ languageName: node
+ linkType: hard
+
"@babel/helper-hoist-variables@npm:^7.22.5":
version: 7.22.5
resolution: "@babel/helper-hoist-variables@npm:7.22.5"
@@ -1801,6 +1856,15 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-member-expression-to-functions@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/helper-member-expression-to-functions@npm:7.24.6"
+ dependencies:
+ "@babel/types": "npm:^7.24.6"
+ checksum: 7595f62978f55921b24de6ed5252fcedbffacfb8271f71e092f38724179ba554cb3a24a4764a1a3890b8a53504c2bee9c99eab81f1f365582739f566c8e28eaa
+ languageName: node
+ linkType: hard
+
"@babel/helper-module-imports@npm:^7.16.7, @babel/helper-module-imports@npm:^7.22.15":
version: 7.22.15
resolution: "@babel/helper-module-imports@npm:7.22.15"
@@ -1810,6 +1874,15 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-module-imports@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/helper-module-imports@npm:7.24.6"
+ dependencies:
+ "@babel/types": "npm:^7.24.6"
+ checksum: e0db3fbfcd963d138f0792ff626f940a576fcf212d02b8fe6478dccf3421bd1c2a76f8e69c7450c049985e7b63b30be309a24eeeb6ad7c2137a31b676a095a84
+ languageName: node
+ linkType: hard
+
"@babel/helper-module-transforms@npm:^7.23.3":
version: 7.23.3
resolution: "@babel/helper-module-transforms@npm:7.23.3"
@@ -1825,6 +1898,21 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-module-transforms@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/helper-module-transforms@npm:7.24.6"
+ dependencies:
+ "@babel/helper-environment-visitor": "npm:^7.24.6"
+ "@babel/helper-module-imports": "npm:^7.24.6"
+ "@babel/helper-simple-access": "npm:^7.24.6"
+ "@babel/helper-split-export-declaration": "npm:^7.24.6"
+ "@babel/helper-validator-identifier": "npm:^7.24.6"
+ peerDependencies:
+ "@babel/core": ^7.0.0
+ checksum: 9e2e3d0ddb397b36b9e8c7d94e175a36be8cb888ef370cefef2cdfd53ae1f87d567b268bd90ed9a6c706485a8de3da19cac577657613e9cd17210b91cbdfb00b
+ languageName: node
+ linkType: hard
+
"@babel/helper-optimise-call-expression@npm:^7.22.5":
version: 7.22.5
resolution: "@babel/helper-optimise-call-expression@npm:7.22.5"
@@ -1834,6 +1922,15 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-optimise-call-expression@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/helper-optimise-call-expression@npm:7.24.6"
+ dependencies:
+ "@babel/types": "npm:^7.24.6"
+ checksum: 7fce2c4ce22c4ba3c2178d1ce85f34fc9bbe286af5ec153b4b6ea9bf2212390359c4a1e8a54551c4daa4688022d619668bdb8c8060cb185c0c9ad02c5247efc9
+ languageName: node
+ linkType: hard
+
"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.20.2, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3":
version: 7.22.5
resolution: "@babel/helper-plugin-utils@npm:7.22.5"
@@ -1848,6 +1945,13 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-plugin-utils@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/helper-plugin-utils@npm:7.24.6"
+ checksum: 636d3ce8cabc0621c1f78187e1d95f1087209921fa452f76aad06224ef5dffb3d934946f5183109920f32a4b94dd75ac91c63bc52813fee639d10cd54d49ba1f
+ languageName: node
+ linkType: hard
+
"@babel/helper-remap-async-to-generator@npm:^7.22.20":
version: 7.22.20
resolution: "@babel/helper-remap-async-to-generator@npm:7.22.20"
@@ -1874,6 +1978,19 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-replace-supers@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/helper-replace-supers@npm:7.24.6"
+ dependencies:
+ "@babel/helper-environment-visitor": "npm:^7.24.6"
+ "@babel/helper-member-expression-to-functions": "npm:^7.24.6"
+ "@babel/helper-optimise-call-expression": "npm:^7.24.6"
+ peerDependencies:
+ "@babel/core": ^7.0.0
+ checksum: aaf2dfaf25360da1525ecea5979d5afed201b96f0feeed2e15f90883a97776132a720b25039e67fee10a5c537363aea5cc2a46c0f1d13fdb86d0e920244f2da7
+ languageName: node
+ linkType: hard
+
"@babel/helper-simple-access@npm:^7.22.5":
version: 7.22.5
resolution: "@babel/helper-simple-access@npm:7.22.5"
@@ -1883,6 +2000,15 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-simple-access@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/helper-simple-access@npm:7.24.6"
+ dependencies:
+ "@babel/types": "npm:^7.24.6"
+ checksum: b17e404dd6c9787fc7d558aea5222471a77e29596705f0d10b4c2a58b9d71ff7eae915094204848cc1af99b771553caa69337a768b9abdd82b54a0050ba83eb9
+ languageName: node
+ linkType: hard
+
"@babel/helper-skip-transparent-expression-wrappers@npm:^7.20.0, @babel/helper-skip-transparent-expression-wrappers@npm:^7.22.5":
version: 7.22.5
resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.22.5"
@@ -1892,6 +2018,15 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-skip-transparent-expression-wrappers@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.24.6"
+ dependencies:
+ "@babel/types": "npm:^7.24.6"
+ checksum: 6928f698362d6082a67ee2bc73991ef6b0cc6b5f2854177389bc8f3c09296580f0ee20134dd1a29dfcb1906ad9e346fa0f7c6fcd7589ab3ff176d4f09504577f
+ languageName: node
+ linkType: hard
+
"@babel/helper-split-export-declaration@npm:^7.22.6":
version: 7.22.6
resolution: "@babel/helper-split-export-declaration@npm:7.22.6"
@@ -1901,6 +2036,15 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-split-export-declaration@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/helper-split-export-declaration@npm:7.24.6"
+ dependencies:
+ "@babel/types": "npm:^7.24.6"
+ checksum: 53a5dd8691fdffc89cc7fcf5aed0ad1d8bc39796a5782a3d170dcbf249eb5c15cc8a290e8d09615711d18798ad04a7d0694ab5195d35fa651abbc1b9c885d6a8
+ languageName: node
+ linkType: hard
+
"@babel/helper-string-parser@npm:^7.23.4":
version: 7.23.4
resolution: "@babel/helper-string-parser@npm:7.23.4"
@@ -1908,6 +2052,13 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-string-parser@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/helper-string-parser@npm:7.24.6"
+ checksum: 95115bf676e92c4e99166395649108d97447e6cabef1fabaec8cdbc53a43f27b5df2268ff6534439d405bc1bd06685b163eb3b470455bd49f69159dada414145
+ languageName: node
+ linkType: hard
+
"@babel/helper-validator-identifier@npm:^7.22.20":
version: 7.22.20
resolution: "@babel/helper-validator-identifier@npm:7.22.20"
@@ -1915,6 +2066,13 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-validator-identifier@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/helper-validator-identifier@npm:7.24.6"
+ checksum: d29d2e3fca66c31867a009014169b93f7bc21c8fc1dd7d0b9d85d7a4000670526ff2222d966febb75a6e12f9859a31d1e75b558984e28ecb69651314dd0a6fd1
+ languageName: node
+ linkType: hard
+
"@babel/helper-validator-option@npm:^7.22.15, @babel/helper-validator-option@npm:^7.23.5":
version: 7.23.5
resolution: "@babel/helper-validator-option@npm:7.23.5"
@@ -1922,6 +2080,13 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-validator-option@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/helper-validator-option@npm:7.24.6"
+ checksum: 787268dff5cf77f3b704454b96ab7b58aa4f43b2808247e51859a103a1c28a9c252100f830433f4b37a73f4a61ba745bbeef4cdccbab48c1e9adf037f4ca3491
+ languageName: node
+ linkType: hard
+
"@babel/helper-wrap-function@npm:^7.22.20":
version: 7.22.20
resolution: "@babel/helper-wrap-function@npm:7.22.20"
@@ -1988,6 +2153,18 @@ __metadata:
languageName: node
linkType: hard
+"@babel/highlight@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/highlight@npm:7.24.6"
+ dependencies:
+ "@babel/helper-validator-identifier": "npm:^7.24.6"
+ chalk: "npm:^2.4.2"
+ js-tokens: "npm:^4.0.0"
+ picocolors: "npm:^1.0.0"
+ checksum: 5bbc31695e5d44e97feb267f7aaf4c52908560d184ffeb2e2e57aae058d40125592931883889413e19def3326895ddb41ff45e090fa90b459d8c294b4ffc238c
+ languageName: node
+ linkType: hard
+
"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.16.8, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.22.7, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.5":
version: 7.23.5
resolution: "@babel/parser@npm:7.23.5"
@@ -2015,6 +2192,15 @@ __metadata:
languageName: node
linkType: hard
+"@babel/parser@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/parser@npm:7.24.6"
+ bin:
+ parser: ./bin/babel-parser.js
+ checksum: cbef70923078a20fe163b03f4a6482be65ed99d409a57f3091a23ce3a575ee75716c30e7ea9f40b692ac5660f34055f4cbeb66a354fad15a6cf1fca35c3496c5
+ languageName: node
+ linkType: hard
+
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.23.3":
version: 7.23.3
resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.23.3"
@@ -2268,6 +2454,17 @@ __metadata:
languageName: node
linkType: hard
+"@babel/plugin-syntax-jsx@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/plugin-syntax-jsx@npm:7.24.6"
+ dependencies:
+ "@babel/helper-plugin-utils": "npm:^7.24.6"
+ peerDependencies:
+ "@babel/core": ^7.0.0-0
+ checksum: f00d783a9e2d52f0a8797823a3cbdbe2d0dc09c7235fe8c88e6dce3a02f234f52fb5e976a001cc30b0e2b330590b5680f54436e56d67f9ab05d1e4bdeb3992cd
+ languageName: node
+ linkType: hard
+
"@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4, @babel/plugin-syntax-logical-assignment-operators@npm:^7.8.3":
version: 7.10.4
resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4"
@@ -2367,6 +2564,17 @@ __metadata:
languageName: node
linkType: hard
+"@babel/plugin-syntax-typescript@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/plugin-syntax-typescript@npm:7.24.6"
+ dependencies:
+ "@babel/helper-plugin-utils": "npm:^7.24.6"
+ peerDependencies:
+ "@babel/core": ^7.0.0-0
+ checksum: b1eeabf8bebfa78cea559c0a0d55e480fe2ebd799472d1f6bd5afbd2759d02b362d29ad30009c81d5b112797beb987e58a3000d2331adaa4bf03862e1ed18cef
+ languageName: node
+ linkType: hard
+
"@babel/plugin-syntax-unicode-sets-regex@npm:^7.18.6":
version: 7.18.6
resolution: "@babel/plugin-syntax-unicode-sets-regex@npm:7.18.6"
@@ -2691,6 +2899,19 @@ __metadata:
languageName: node
linkType: hard
+"@babel/plugin-transform-modules-commonjs@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/plugin-transform-modules-commonjs@npm:7.24.6"
+ dependencies:
+ "@babel/helper-module-transforms": "npm:^7.24.6"
+ "@babel/helper-plugin-utils": "npm:^7.24.6"
+ "@babel/helper-simple-access": "npm:^7.24.6"
+ peerDependencies:
+ "@babel/core": ^7.0.0-0
+ checksum: 4fc790136d066105fa773ffc7e249d88c6f0d0126984ede36fedd51ac2b622b46c08565bcdd1ab62ac10195eeedeaba0d26e7e4c676ed50906cbed16540a4e22
+ languageName: node
+ linkType: hard
+
"@babel/plugin-transform-modules-systemjs@npm:^7.23.3":
version: 7.23.3
resolution: "@babel/plugin-transform-modules-systemjs@npm:7.23.3"
@@ -3071,6 +3292,20 @@ __metadata:
languageName: node
linkType: hard
+"@babel/plugin-transform-typescript@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/plugin-transform-typescript@npm:7.24.6"
+ dependencies:
+ "@babel/helper-annotate-as-pure": "npm:^7.24.6"
+ "@babel/helper-create-class-features-plugin": "npm:^7.24.6"
+ "@babel/helper-plugin-utils": "npm:^7.24.6"
+ "@babel/plugin-syntax-typescript": "npm:^7.24.6"
+ peerDependencies:
+ "@babel/core": ^7.0.0-0
+ checksum: 46b054e4d4253187403e392ef30f4dd624d8486a1992703f5ff1b415d4e8d00f474e35fb77bc7a3a16a17330873cadcd5af4a8493c61b16da2dde212b2788ccd
+ languageName: node
+ linkType: hard
+
"@babel/plugin-transform-unicode-escapes@npm:^7.23.3":
version: 7.23.3
resolution: "@babel/plugin-transform-unicode-escapes@npm:7.23.3"
@@ -3355,6 +3590,21 @@ __metadata:
languageName: node
linkType: hard
+"@babel/preset-typescript@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/preset-typescript@npm:7.24.6"
+ dependencies:
+ "@babel/helper-plugin-utils": "npm:^7.24.6"
+ "@babel/helper-validator-option": "npm:^7.24.6"
+ "@babel/plugin-syntax-jsx": "npm:^7.24.6"
+ "@babel/plugin-transform-modules-commonjs": "npm:^7.24.6"
+ "@babel/plugin-transform-typescript": "npm:^7.24.6"
+ peerDependencies:
+ "@babel/core": ^7.0.0-0
+ checksum: bfcef91ed80d67301301e17a799814457b57bfd0d85d9897dce6df6ed0b0af155c0f5b2af7a1a122a3f36faaaa1de87ccf9954ce06d2f440898ffdfaf18aab86
+ languageName: node
+ linkType: hard
+
"@babel/register@npm:^7.13.16, @babel/register@npm:^7.22.15":
version: 7.23.7
resolution: "@babel/register@npm:7.23.7"
@@ -3446,6 +3696,17 @@ __metadata:
languageName: node
linkType: hard
+"@babel/template@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/template@npm:7.24.6"
+ dependencies:
+ "@babel/code-frame": "npm:^7.24.6"
+ "@babel/parser": "npm:^7.24.6"
+ "@babel/types": "npm:^7.24.6"
+ checksum: a4d5805770de908b445f7cdcebfcb6eaa07b1ec9c7b78fd3f375a911b1522c249bddae6b96bc4aac24247cc603e3e6cffcf2fe50b4c929dfeb22de289b517525
+ languageName: node
+ linkType: hard
+
"@babel/traverse@npm:^7.14.0, @babel/traverse@npm:^7.16.8, @babel/traverse@npm:^7.18.9, @babel/traverse@npm:^7.22.8, @babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.23.5":
version: 7.23.5
resolution: "@babel/traverse@npm:7.23.5"
@@ -3551,6 +3812,17 @@ __metadata:
languageName: node
linkType: hard
+"@babel/types@npm:^7.24.6":
+ version: 7.24.6
+ resolution: "@babel/types@npm:7.24.6"
+ dependencies:
+ "@babel/helper-string-parser": "npm:^7.24.6"
+ "@babel/helper-validator-identifier": "npm:^7.24.6"
+ to-fast-properties: "npm:^2.0.0"
+ checksum: 1d94d92d97ef49030ad7f9e14cfccfeb70b1706dabcaa69037e659ec9d2c3178fb005d2088cce40d88dfc1306153d9157fe038a79ea2be92e5e6b99a59ef80cc
+ languageName: node
+ linkType: hard
+
"@base2/pretty-print-object@npm:1.0.1":
version: 1.0.1
resolution: "@base2/pretty-print-object@npm:1.0.1"
@@ -4760,6 +5032,15 @@ __metadata:
languageName: node
linkType: hard
+"@emotion/is-prop-valid@npm:^1.2.0":
+ version: 1.2.2
+ resolution: "@emotion/is-prop-valid@npm:1.2.2"
+ dependencies:
+ "@emotion/memoize": "npm:^0.8.1"
+ checksum: bb1530dcb4e0e5a4fabb219279f2d0bc35796baf66f6241f98b0d03db1985c890a8cafbea268e0edefd5eeda143dbd5c09a54b5fba74cee8c69b98b13194af50
+ languageName: node
+ linkType: hard
+
"@emotion/is-prop-valid@npm:^1.2.1":
version: 1.2.1
resolution: "@emotion/is-prop-valid@npm:1.2.1"
@@ -7479,6 +7760,33 @@ __metadata:
languageName: node
linkType: hard
+"@linaria/core@npm:^6.2.0":
+ version: 6.2.0
+ resolution: "@linaria/core@npm:6.2.0"
+ dependencies:
+ "@wyw-in-js/processor-utils": "npm:^0.5.3"
+ checksum: 4eb6083c0988f19aa3721e34bf14093dab8a0c6a784237ae4276a0b4e68bb82e91c594d7dd1d12173aaa2b38400a6bf5e0bd8b961a9ae05cdba854e2c566a134
+ languageName: node
+ linkType: hard
+
+"@linaria/react@npm:^6.2.1":
+ version: 6.2.1
+ resolution: "@linaria/react@npm:6.2.1"
+ dependencies:
+ "@emotion/is-prop-valid": "npm:^1.2.0"
+ "@linaria/core": "npm:^6.2.0"
+ "@wyw-in-js/processor-utils": "npm:^0.5.3"
+ "@wyw-in-js/shared": "npm:^0.5.3"
+ minimatch: "npm:^9.0.3"
+ react-html-attributes: "npm:^1.4.6"
+ resolve: "npm:^1.22.8"
+ ts-invariant: "npm:^0.10.3"
+ peerDependencies:
+ react: ">=16"
+ checksum: 102480195bc6e5f41cf3da4c7181640cf617256fcdd48847238cdc7def30536f132f29f35530bd261cbf5580a87981f5a6f7717e791b73cc309552141a10d256
+ languageName: node
+ linkType: hard
+
"@ljharb/through@npm:^2.3.9":
version: 2.3.12
resolution: "@ljharb/through@npm:2.3.12"
@@ -18685,6 +18993,62 @@ __metadata:
languageName: node
linkType: hard
+"@wyw-in-js/processor-utils@npm:0.5.3, @wyw-in-js/processor-utils@npm:^0.5.3":
+ version: 0.5.3
+ resolution: "@wyw-in-js/processor-utils@npm:0.5.3"
+ dependencies:
+ "@babel/generator": "npm:^7.23.5"
+ "@wyw-in-js/shared": "npm:0.5.3"
+ checksum: d9d12fe96a423551876b00cd715c61945a11770b448cb9363d435f1cd3506f7f57c068558ea8cb87eb78d39ff7cdb255ed055af540ee289f8b4e4798f12dd66d
+ languageName: node
+ linkType: hard
+
+"@wyw-in-js/shared@npm:0.5.3, @wyw-in-js/shared@npm:^0.5.3":
+ version: 0.5.3
+ resolution: "@wyw-in-js/shared@npm:0.5.3"
+ dependencies:
+ debug: "npm:^4.3.4"
+ find-up: "npm:^5.0.0"
+ minimatch: "npm:^9.0.3"
+ checksum: 0e02195f113793231953f8a2b0a65e8641f851d2627d961949fa925c60a72ce35a20dd477b12f5ac3f0cfedc30c8507a4540d0f5acf7983fd5c636acba50d293
+ languageName: node
+ linkType: hard
+
+"@wyw-in-js/transform@npm:0.5.3":
+ version: 0.5.3
+ resolution: "@wyw-in-js/transform@npm:0.5.3"
+ dependencies:
+ "@babel/core": "npm:^7.23.5"
+ "@babel/generator": "npm:^7.23.5"
+ "@babel/helper-module-imports": "npm:^7.22.15"
+ "@babel/plugin-transform-modules-commonjs": "npm:^7.23.3"
+ "@babel/template": "npm:^7.22.15"
+ "@babel/traverse": "npm:^7.23.5"
+ "@babel/types": "npm:^7.23.5"
+ "@wyw-in-js/processor-utils": "npm:0.5.3"
+ "@wyw-in-js/shared": "npm:0.5.3"
+ babel-merge: "npm:^3.0.0"
+ cosmiconfig: "npm:^8.0.0"
+ happy-dom: "npm:^12.5.0"
+ source-map: "npm:^0.7.4"
+ stylis: "npm:^4.3.0"
+ ts-invariant: "npm:^0.10.3"
+ checksum: 947633c7ed6fbbd2546a88db7ba5e70e558eb460eb60a479031f5edae07234f4e7eda5bc960aabee755e154d7cf6e3f191cd291666f3c5735b65d469896e8574
+ languageName: node
+ linkType: hard
+
+"@wyw-in-js/vite@npm:^0.5.3":
+ version: 0.5.3
+ resolution: "@wyw-in-js/vite@npm:0.5.3"
+ dependencies:
+ "@wyw-in-js/shared": "npm:0.5.3"
+ "@wyw-in-js/transform": "npm:0.5.3"
+ peerDependencies:
+ vite: ">=3.2.7"
+ checksum: 0fbbdfe2fde2061b160052c7607d15f4fc3254058888b03f4affe42f4fd5bc059784732e1d372e79dcd8b40e9fa4f92c98805c018d5912d4227236328c32ea30
+ languageName: node
+ linkType: hard
+
"@xobotyi/scrollbar-width@npm:^1.9.5":
version: 1.9.5
resolution: "@xobotyi/scrollbar-width@npm:1.9.5"
@@ -20244,6 +20608,18 @@ __metadata:
languageName: node
linkType: hard
+"babel-merge@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "babel-merge@npm:3.0.0"
+ dependencies:
+ deepmerge: "npm:^2.2.1"
+ object.omit: "npm:^3.0.0"
+ peerDependencies:
+ "@babel/core": ^7.0.0
+ checksum: 8337358ba69553305ba0ee6ddfdeb79b58d37012d5c99953d87e608eb22299a565501a854e451c2daa8f7b2310d1a52c66ed92f17e18a9858153e9fd9f3090e5
+ languageName: node
+ linkType: hard
+
"babel-messages@npm:^6.23.0":
version: 6.23.0
resolution: "babel-messages@npm:6.23.0"
@@ -23714,7 +24090,7 @@ __metadata:
languageName: node
linkType: hard
-"cosmiconfig@npm:8.3.6, cosmiconfig@npm:^8.1.3, cosmiconfig@npm:^8.2.0, cosmiconfig@npm:^8.3.5":
+"cosmiconfig@npm:8.3.6, cosmiconfig@npm:^8.0.0, cosmiconfig@npm:^8.1.3, cosmiconfig@npm:^8.2.0, cosmiconfig@npm:^8.3.5":
version: 8.3.6
resolution: "cosmiconfig@npm:8.3.6"
dependencies:
@@ -24836,6 +25212,13 @@ __metadata:
languageName: node
linkType: hard
+"deepmerge@npm:^2.2.1":
+ version: 2.2.1
+ resolution: "deepmerge@npm:2.2.1"
+ checksum: 4379288cabd817587cee92a095ea65d18317b45e48010a2e0d87982b5f432239a144f9c8ebd4ab090cc21f0cb47e51ebfe32921f329b3b3084a2711d5d63e450
+ languageName: node
+ linkType: hard
+
"deepmerge@npm:^4.2.2, deepmerge@npm:^4.3.1":
version: 4.3.1
resolution: "deepmerge@npm:4.3.1"
@@ -29608,6 +29991,20 @@ __metadata:
languageName: node
linkType: hard
+"happy-dom@npm:^12.5.0":
+ version: 12.10.3
+ resolution: "happy-dom@npm:12.10.3"
+ dependencies:
+ css.escape: "npm:^1.5.1"
+ entities: "npm:^4.5.0"
+ iconv-lite: "npm:^0.6.3"
+ webidl-conversions: "npm:^7.0.0"
+ whatwg-encoding: "npm:^2.0.0"
+ whatwg-mimetype: "npm:^3.0.0"
+ checksum: fbf8647e17c4af5c166d7c4b6963f4bbc9d1c279e94a4c77234b1fecca98c59989b894c7b186f5107e1062d40ffd84f12350b757f51330a5fc1c5228eb199517
+ languageName: node
+ linkType: hard
+
"har-schema@npm:^2.0.0":
version: 2.0.0
resolution: "har-schema@npm:2.0.0"
@@ -30391,6 +30788,13 @@ __metadata:
languageName: node
linkType: hard
+"html-element-attributes@npm:^1.0.0":
+ version: 1.3.1
+ resolution: "html-element-attributes@npm:1.3.1"
+ checksum: caf9704577854275bfe4b6f5a77c9b5f2d988b6bc86f48aa1ee043421950c314c43d8f2915178f5cb7a00409e1f2690c1ddb0f4758f9d63b875172cbaa32bc9f
+ languageName: node
+ linkType: hard
+
"html-encoding-sniffer@npm:^3.0.0":
version: 3.0.0
resolution: "html-encoding-sniffer@npm:3.0.0"
@@ -30857,7 +31261,7 @@ __metadata:
languageName: node
linkType: hard
-"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2":
+"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2, iconv-lite@npm:^0.6.3":
version: 0.6.3
resolution: "iconv-lite@npm:0.6.3"
dependencies:
@@ -41673,6 +42077,15 @@ __metadata:
languageName: node
linkType: hard
+"react-html-attributes@npm:^1.4.6":
+ version: 1.4.6
+ resolution: "react-html-attributes@npm:1.4.6"
+ dependencies:
+ html-element-attributes: "npm:^1.0.0"
+ checksum: f2ef5b80c6254a0bc4cc802d7412bee0bd5008a1ac1a96eb52cdfde9b7e5017e9373ee613361d6c83df3faa8743c71fb42d1fb238bb797ece481d97848c02be2
+ languageName: node
+ linkType: hard
+
"react-icons@npm:^4.12.0, react-icons@npm:^4.3.1":
version: 4.12.0
resolution: "react-icons@npm:4.12.0"
@@ -43180,7 +43593,7 @@ __metadata:
languageName: node
linkType: hard
-"resolve@npm:^1.1.4, resolve@npm:^1.1.6, resolve@npm:^1.10.0, resolve@npm:^1.12.0, resolve@npm:^1.14.2, resolve@npm:^1.17.0, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.1, resolve@npm:^1.22.4, resolve@npm:^1.4.0, resolve@npm:~1.22.1":
+"resolve@npm:^1.1.4, resolve@npm:^1.1.6, resolve@npm:^1.10.0, resolve@npm:^1.12.0, resolve@npm:^1.14.2, resolve@npm:^1.17.0, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.1, resolve@npm:^1.22.4, resolve@npm:^1.22.8, resolve@npm:^1.4.0, resolve@npm:~1.22.1":
version: 1.22.8
resolution: "resolve@npm:1.22.8"
dependencies:
@@ -43216,7 +43629,7 @@ __metadata:
languageName: node
linkType: hard
-"resolve@patch:resolve@npm%3A^1.1.4#optional!builtin, resolve@patch:resolve@npm%3A^1.1.6#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.12.0#optional!builtin, resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.17.0#optional!builtin, resolve@patch:resolve@npm%3A^1.19.0#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.1#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin, resolve@patch:resolve@npm%3A^1.4.0#optional!builtin, resolve@patch:resolve@npm%3A~1.22.1#optional!builtin":
+"resolve@patch:resolve@npm%3A^1.1.4#optional!builtin, resolve@patch:resolve@npm%3A^1.1.6#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.12.0#optional!builtin, resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.17.0#optional!builtin, resolve@patch:resolve@npm%3A^1.19.0#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.1#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin, resolve@patch:resolve@npm%3A^1.22.8#optional!builtin, resolve@patch:resolve@npm%3A^1.4.0#optional!builtin, resolve@patch:resolve@npm%3A~1.22.1#optional!builtin":
version: 1.22.8
resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d"
dependencies:
@@ -46796,6 +47209,7 @@ __metadata:
"@aws-sdk/credential-providers": "npm:^3.363.0"
"@babel/core": "npm:^7.14.5"
"@babel/preset-react": "npm:^7.14.5"
+ "@babel/preset-typescript": "npm:^7.24.6"
"@blocknote/core": "npm:^0.12.1"
"@blocknote/react": "npm:^0.12.2"
"@chakra-ui/accordion": "npm:^2.3.0"
@@ -46822,6 +47236,8 @@ __metadata:
"@hello-pangea/dnd": "npm:^16.2.0"
"@hookform/resolvers": "npm:^3.1.1"
"@jsdevtools/rehype-toc": "npm:^3.0.2"
+ "@linaria/core": "npm:^6.2.0"
+ "@linaria/react": "npm:^6.2.1"
"@mdx-js/react": "npm:^3.0.0"
"@nestjs/apollo": "npm:^11.0.5"
"@nestjs/axios": "npm:^3.0.1"
@@ -46934,6 +47350,7 @@ __metadata:
"@typescript-eslint/utils": "npm:6.21.0"
"@vitejs/plugin-react-swc": "npm:^3.5.0"
"@vitest/ui": "npm:1.4.0"
+ "@wyw-in-js/vite": "npm:^0.5.3"
add: "npm:^2.0.6"
addressparser: "npm:^1.0.1"
afterframe: "npm:^1.0.2"