Use SelectableList in RelationPicker, SingleEntitySelectBase and MultipleEntitySelect (#2949)

* 2747-fix: conditional updation of selectedItemId

* 2747-fix: bug in toggling

* 2747-feat: SingleEntitySelectBase list changed to SelectableList

* 2747-feat: MultipleEntitySelect use SelectableList

* Fix lint

* 2747-fix: onEnter property fix for SingleEntitySelectBase

* 2747-fix: onEnter property fix for MultipleEntitySelect

* yarn fix in twenty-front

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Kanav Arora 2023-12-14 16:40:58 +05:30 committed by GitHub
parent 4673a302c7
commit ed2cd408bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 297 additions and 75 deletions

View File

@ -106,6 +106,7 @@ module.exports = {
'*.config.ts', '*.config.ts',
'*config.js', '*config.js',
'codegen*', 'codegen*',
'tsup.ui.index.tsx'
], ],
overrides: [ overrides: [
{ {

View File

@ -9,7 +9,6 @@
"build": "tsc && vite build && yarn build:inject-runtime-env", "build": "tsc && vite build && yarn build:inject-runtime-env",
"build:inject-runtime-env": "sh ./scripts/inject-runtime-env.sh", "build:inject-runtime-env": "sh ./scripts/inject-runtime-env.sh",
"preview": "vite preview", "preview": "vite preview",
"eslint-plugin:setup": "cd ../packages/eslint-plugin-twenty/ && yarn && yarn build && cd ../../front/ && yarn upgrade eslint-plugin-twenty",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"fmt:fix": "prettier --cache --write \"src/**/*.ts\" \"src/**/*.tsx\"", "fmt:fix": "prettier --cache --write \"src/**/*.ts\" \"src/**/*.tsx\"",
"fmt": "prettier --check \"src/**/*.ts\" \"src/**/*.tsx\"", "fmt": "prettier --check \"src/**/*.ts\" \"src/**/*.tsx\"",
@ -66,6 +65,7 @@
"lodash.kebabcase": "^4.1.1", "lodash.kebabcase": "^4.1.1",
"lodash.snakecase": "^4.1.1", "lodash.snakecase": "^4.1.1",
"luxon": "^3.3.0", "luxon": "^3.3.0",
"nx": "17.2.3",
"react": "^18.2.0", "react": "^18.2.0",
"react-data-grid": "7.0.0-beta.13", "react-data-grid": "7.0.0-beta.13",
"react-datepicker": "^4.11.0", "react-datepicker": "^4.11.0",

View File

@ -1,11 +1,16 @@
/* eslint-disable react-hooks/rules-of-hooks */
import { useRef } from 'react'; import { useRef } from 'react';
import { isNonEmptyString } from '@sniptt/guards'; import { isNonEmptyString } from '@sniptt/guards';
import debounce from 'lodash.debounce'; import debounce from 'lodash.debounce';
import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope';
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu'; import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { SelectableItem } from '@/ui/layout/selectable-list/components/SelectableItem';
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { MenuItemMultiSelectAvatar } from '@/ui/navigation/menu-item/components/MenuItemMultiSelectAvatar'; import { MenuItemMultiSelectAvatar } from '@/ui/navigation/menu-item/components/MenuItemMultiSelectAvatar';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
@ -71,6 +76,8 @@ export const MultipleEntitySelect = <
}, },
}); });
const selectableItemIds = entitiesInDropdown.map((entity) => entity.id);
return ( return (
<DropdownMenu ref={containerRef} data-select-disable> <DropdownMenu ref={containerRef} data-select-disable>
<DropdownMenuSearchInput <DropdownMenuSearchInput
@ -80,25 +87,46 @@ export const MultipleEntitySelect = <
/> />
<DropdownMenuSeparator /> <DropdownMenuSeparator />
<DropdownMenuItemsContainer hasMaxHeight> <DropdownMenuItemsContainer hasMaxHeight>
{entitiesInDropdown?.map((entity) => ( <SelectableList
<MenuItemMultiSelectAvatar selectableListId="multiple-entity-select-list"
key={entity.id} selectableItemIds={[selectableItemIds]}
selected={value[entity.id]} hotkeyScope={RelationPickerHotkeyScope.RelationPicker}
onSelectChange={(newCheckedValue) => onEnter={(_itemId) => {
onChange({ ...value, [entity.id]: newCheckedValue }) if (_itemId in value === false || value[_itemId] === false) {
onChange({ ...value, [_itemId]: true });
} else {
onChange({ ...value, [_itemId]: false });
} }
avatar={ }}
<Avatar >
avatarUrl={entity.avatarUrl} {entitiesInDropdown?.map((entity) => (
colorId={entity.id} <SelectableItem itemId={entity.id} key={entity.id}>
placeholder={entity.name} <MenuItemMultiSelectAvatar
size="md" key={entity.id}
type={entity.avatarType ?? 'rounded'} isKeySelected={
useSelectableList({
selectableListId: 'multiple-entity-select-list',
itemId: entity.id,
}).isSelectedItemId
}
selected={value[entity.id]}
onSelectChange={(newCheckedValue) =>
onChange({ ...value, [entity.id]: newCheckedValue })
}
avatar={
<Avatar
avatarUrl={entity.avatarUrl}
colorId={entity.id}
placeholder={entity.name}
size="md"
type={entity.avatarType ?? 'rounded'}
/>
}
text={entity.name}
/> />
} </SelectableItem>
text={entity.name} ))}
/> </SelectableList>
))}
{entitiesInDropdown?.length === 0 && <MenuItem text="No result" />} {entitiesInDropdown?.length === 0 && <MenuItem text="No result" />}
</DropdownMenuItemsContainer> </DropdownMenuItemsContainer>
</DropdownMenu> </DropdownMenu>

View File

@ -1,3 +1,4 @@
/* eslint-disable react-hooks/rules-of-hooks */
import { useRef } from 'react'; import { useRef } from 'react';
import { isNonEmptyString } from '@sniptt/guards'; import { isNonEmptyString } from '@sniptt/guards';
import { Key } from 'ts-key-enum'; import { Key } from 'ts-key-enum';
@ -6,6 +7,9 @@ import { IconPlus } from '@/ui/display/icon';
import { IconComponent } from '@/ui/display/icon/types/IconComponent'; import { IconComponent } from '@/ui/display/icon/types/IconComponent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { SelectableItem } from '@/ui/layout/selectable-list/components/SelectableItem';
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { MenuItemSelect } from '@/ui/navigation/menu-item/components/MenuItemSelect'; import { MenuItemSelect } from '@/ui/navigation/menu-item/components/MenuItemSelect';
import { MenuItemSelectAvatar } from '@/ui/navigation/menu-item/components/MenuItemSelectAvatar'; import { MenuItemSelectAvatar } from '@/ui/navigation/menu-item/components/MenuItemSelectAvatar';
@ -64,7 +68,7 @@ export const SingleEntitySelectBase = <
assertNotNull(entity) && isNonEmptyString(entity.name), assertNotNull(entity) && isNonEmptyString(entity.name),
); );
const { preselectedOptionId, resetScroll } = useEntitySelectScroll({ const { preselectedOptionId } = useEntitySelectScroll({
selectableOptionIds: [ selectableOptionIds: [
EmptyButtonId, EmptyButtonId,
...entitiesInDropdown.map((item) => item.id), ...entitiesInDropdown.map((item) => item.id),
@ -73,24 +77,6 @@ export const SingleEntitySelectBase = <
containerRef, containerRef,
}); });
useScopedHotkeys(
Key.Enter,
() => {
if (showCreateButton && preselectedOptionId === CreateButtonId) {
onCreate?.();
} else {
const entity = entitiesInDropdown.findIndex(
(entity) => entity.id === preselectedOptionId,
);
onEntitySelected(entitiesInDropdown[entity]);
}
resetScroll();
},
RelationPickerHotkeyScope.RelationPicker,
[entitiesInDropdown, preselectedOptionId, onEntitySelected],
);
useScopedHotkeys( useScopedHotkeys(
Key.Escape, Key.Escape,
() => { () => {
@ -100,6 +86,8 @@ export const SingleEntitySelectBase = <
[onCancel], [onCancel],
); );
const selectableItemIds = entitiesInDropdown.map((entity) => entity.id);
return ( return (
<div ref={containerRef}> <div ref={containerRef}>
<DropdownMenuItemsContainer hasMaxHeight> <DropdownMenuItemsContainer hasMaxHeight>
@ -130,23 +118,49 @@ export const SingleEntitySelectBase = <
/> />
)} )}
{entitiesInDropdown?.map((entity) => ( {entitiesInDropdown?.map((entity) => (
<MenuItemSelectAvatar <SelectableList
key={entity.id} selectableListId="single-entity-select-base-list"
testId="menu-item" selectableItemIds={[selectableItemIds]}
selected={selectedEntity?.id === entity.id} hotkeyScope={RelationPickerHotkeyScope.RelationPicker}
onClick={() => onEntitySelected(entity)} onEnter={(_itemId) => {
text={entity.name} if (
hovered={preselectedOptionId === entity.id} showCreateButton &&
avatar={ preselectedOptionId === CreateButtonId
<Avatar ) {
avatarUrl={entity.avatarUrl} onCreate?.();
colorId={entity.id} } else {
placeholder={entity.name} const entity = entitiesInDropdown.findIndex(
size="md" (entity) => entity.id === _itemId,
type={entity.avatarType ?? 'rounded'} );
onEntitySelected(entitiesInDropdown[entity]);
}
}}
>
<SelectableItem itemId={entity.id} key={entity.id}>
<MenuItemSelectAvatar
key={entity.id}
testId="menu-item"
onClick={() => onEntitySelected(entity)}
text={entity.name}
selected={selectedEntity?.id === entity.id}
hovered={
useSelectableList({
selectableListId: 'single-entity-select-base-list',
itemId: entity.id,
}).isSelectedItemId
}
avatar={
<Avatar
avatarUrl={entity.avatarUrl}
colorId={entity.id}
placeholder={entity.name}
size="md"
type={entity.avatarType ?? 'rounded'}
/>
}
/> />
} </SelectableItem>
/> </SelectableList>
))} ))}
</> </>
)} )}

View File

@ -115,7 +115,6 @@ export const turnFiltersIntoObjectRecordFilters = (
); );
} }
// eslint-disable-next-line no-case-declarations
const parsedRecordIds = JSON.parse(rawUIFilter.value) as string[]; const parsedRecordIds = JSON.parse(rawUIFilter.value) as string[];
if (parsedRecordIds.length > 0) { if (parsedRecordIds.length > 0) {

View File

@ -1,4 +1,4 @@
import { Meta, Story, StoryObj } from '@storybook/react'; import { Meta, StoryObj } from '@storybook/react';
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator'; import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';

View File

@ -16,8 +16,7 @@ export const useSelectableListHotKeys = (
selectedItemId?: string | null, selectedItemId?: string | null,
) => { ) => {
if (!selectedItemId) { if (!selectedItemId) {
// If nothing is selected, return the default position return { row: 0, col: -1 };
return { row: 0, col: 0 };
} }
for (let row = 0; row < selectableItemIds.length; row++) { for (let row = 0; row < selectableItemIds.length; row++) {
@ -94,21 +93,23 @@ export const useSelectableListHotKeys = (
const nextId = computeNextId(direction); const nextId = computeNextId(direction);
if (nextId) { if (!selectedItemId || (selectedItemId && selectedItemId !== nextId)) {
const { isSelectedItemIdSelector } = getSelectableListScopedStates({ if (nextId) {
selectableListScopeId: scopeId, const { isSelectedItemIdSelector } = getSelectableListScopedStates({
itemId: nextId, selectableListScopeId: scopeId,
}); itemId: nextId,
set(isSelectedItemIdSelector, true); });
set(selectedItemIdState, nextId); set(isSelectedItemIdSelector, true);
} set(selectedItemIdState, nextId);
}
if (selectedItemId) { if (selectedItemId) {
const { isSelectedItemIdSelector } = getSelectableListScopedStates({ const { isSelectedItemIdSelector } = getSelectableListScopedStates({
selectableListScopeId: scopeId, selectableListScopeId: scopeId,
itemId: selectedItemId, itemId: selectedItemId,
}); });
set(isSelectedItemIdSelector, false); set(isSelectedItemIdSelector, false);
}
} }
}, },
[scopeId], [scopeId],

View File

@ -19,6 +19,7 @@ const StyledLeftContentWithCheckboxContainer = styled.div`
type MenuItemMultiSelectAvatarProps = { type MenuItemMultiSelectAvatarProps = {
avatar?: ReactNode; avatar?: ReactNode;
selected: boolean; selected: boolean;
isKeySelected: boolean;
text: string; text: string;
className?: string; className?: string;
onSelectChange?: (selected: boolean) => void; onSelectChange?: (selected: boolean) => void;
@ -29,6 +30,7 @@ export const MenuItemMultiSelectAvatar = ({
text, text,
selected, selected,
className, className,
isKeySelected,
onSelectChange, onSelectChange,
}: MenuItemMultiSelectAvatarProps) => { }: MenuItemMultiSelectAvatarProps) => {
const handleOnClick = () => { const handleOnClick = () => {
@ -36,7 +38,11 @@ export const MenuItemMultiSelectAvatar = ({
}; };
return ( return (
<StyledMenuItemBase className={className} onClick={handleOnClick}> <StyledMenuItemBase
className={className}
onClick={handleOnClick}
isKeySelected={isKeySelected}
>
<StyledLeftContentWithCheckboxContainer> <StyledLeftContentWithCheckboxContainer>
<Checkbox checked={selected} /> <Checkbox checked={selected} />
<StyledMenuItemLeftContent> <StyledMenuItemLeftContent>

View File

@ -7,6 +7,7 @@ import { MenuItemAccent } from '../../types/MenuItemAccent';
export type MenuItemBaseProps = { export type MenuItemBaseProps = {
accent?: MenuItemAccent; accent?: MenuItemAccent;
isKeySelected?: boolean;
}; };
export const StyledMenuItemBase = styled.li<MenuItemBaseProps>` export const StyledMenuItemBase = styled.li<MenuItemBaseProps>`
@ -15,8 +16,13 @@ export const StyledMenuItemBase = styled.li<MenuItemBaseProps>`
align-items: center; align-items: center;
background: ${({ isKeySelected, theme }) =>
isKeySelected
? theme.background.transparent.light
: theme.background.primary};
border-radius: ${({ theme }) => theme.border.radius.sm}; border-radius: ${({ theme }) => theme.border.radius.sm};
cursor: pointer; cursor: pointer;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@ -26,8 +32,8 @@ export const StyledMenuItemBase = styled.li<MenuItemBaseProps>`
gap: ${({ theme }) => theme.spacing(2)}; gap: ${({ theme }) => theme.spacing(2)};
height: calc(32px - 2 * var(--vertical-padding)); height: calc(32px - 2 * var(--vertical-padding));
justify-content: space-between; justify-content: space-between;
padding: var(--vertical-padding) var(--horizontal-padding); padding: var(--vertical-padding) var(--horizontal-padding);
${hoverBackground}; ${hoverBackground};

171
yarn.lock
View File

@ -7235,6 +7235,18 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@nrwl/tao@npm:17.2.3":
version: 17.2.3
resolution: "@nrwl/tao@npm:17.2.3"
dependencies:
nx: "npm:17.2.3"
tslib: "npm:^2.3.0"
bin:
tao: index.js
checksum: db353ea11664e9db2f3e3e5956748452cd50ca01b400170aaa667f1d1853175731c5e6377f756f58b87101c9cc04e210447cec3b64e16a25b27882d4eea17e0e
languageName: node
linkType: hard
"@nuxtjs/opencollective@npm:0.3.2": "@nuxtjs/opencollective@npm:0.3.2":
version: 0.3.2 version: 0.3.2
resolution: "@nuxtjs/opencollective@npm:0.3.2" resolution: "@nuxtjs/opencollective@npm:0.3.2"
@ -7255,6 +7267,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@nx/nx-darwin-arm64@npm:17.2.3":
version: 17.2.3
resolution: "@nx/nx-darwin-arm64@npm:17.2.3"
conditions: os=darwin & cpu=arm64
languageName: node
linkType: hard
"@nx/nx-darwin-x64@npm:17.2.0": "@nx/nx-darwin-x64@npm:17.2.0":
version: 17.2.0 version: 17.2.0
resolution: "@nx/nx-darwin-x64@npm:17.2.0" resolution: "@nx/nx-darwin-x64@npm:17.2.0"
@ -7262,6 +7281,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@nx/nx-darwin-x64@npm:17.2.3":
version: 17.2.3
resolution: "@nx/nx-darwin-x64@npm:17.2.3"
conditions: os=darwin & cpu=x64
languageName: node
linkType: hard
"@nx/nx-freebsd-x64@npm:17.2.0": "@nx/nx-freebsd-x64@npm:17.2.0":
version: 17.2.0 version: 17.2.0
resolution: "@nx/nx-freebsd-x64@npm:17.2.0" resolution: "@nx/nx-freebsd-x64@npm:17.2.0"
@ -7269,6 +7295,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@nx/nx-freebsd-x64@npm:17.2.3":
version: 17.2.3
resolution: "@nx/nx-freebsd-x64@npm:17.2.3"
conditions: os=freebsd & cpu=x64
languageName: node
linkType: hard
"@nx/nx-linux-arm-gnueabihf@npm:17.2.0": "@nx/nx-linux-arm-gnueabihf@npm:17.2.0":
version: 17.2.0 version: 17.2.0
resolution: "@nx/nx-linux-arm-gnueabihf@npm:17.2.0" resolution: "@nx/nx-linux-arm-gnueabihf@npm:17.2.0"
@ -7276,6 +7309,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@nx/nx-linux-arm-gnueabihf@npm:17.2.3":
version: 17.2.3
resolution: "@nx/nx-linux-arm-gnueabihf@npm:17.2.3"
conditions: os=linux & cpu=arm
languageName: node
linkType: hard
"@nx/nx-linux-arm64-gnu@npm:17.2.0": "@nx/nx-linux-arm64-gnu@npm:17.2.0":
version: 17.2.0 version: 17.2.0
resolution: "@nx/nx-linux-arm64-gnu@npm:17.2.0" resolution: "@nx/nx-linux-arm64-gnu@npm:17.2.0"
@ -7283,6 +7323,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@nx/nx-linux-arm64-gnu@npm:17.2.3":
version: 17.2.3
resolution: "@nx/nx-linux-arm64-gnu@npm:17.2.3"
conditions: os=linux & cpu=arm64 & libc=glibc
languageName: node
linkType: hard
"@nx/nx-linux-arm64-musl@npm:17.2.0": "@nx/nx-linux-arm64-musl@npm:17.2.0":
version: 17.2.0 version: 17.2.0
resolution: "@nx/nx-linux-arm64-musl@npm:17.2.0" resolution: "@nx/nx-linux-arm64-musl@npm:17.2.0"
@ -7290,6 +7337,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@nx/nx-linux-arm64-musl@npm:17.2.3":
version: 17.2.3
resolution: "@nx/nx-linux-arm64-musl@npm:17.2.3"
conditions: os=linux & cpu=arm64 & libc=musl
languageName: node
linkType: hard
"@nx/nx-linux-x64-gnu@npm:17.2.0": "@nx/nx-linux-x64-gnu@npm:17.2.0":
version: 17.2.0 version: 17.2.0
resolution: "@nx/nx-linux-x64-gnu@npm:17.2.0" resolution: "@nx/nx-linux-x64-gnu@npm:17.2.0"
@ -7297,6 +7351,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@nx/nx-linux-x64-gnu@npm:17.2.3":
version: 17.2.3
resolution: "@nx/nx-linux-x64-gnu@npm:17.2.3"
conditions: os=linux & cpu=x64 & libc=glibc
languageName: node
linkType: hard
"@nx/nx-linux-x64-musl@npm:17.2.0": "@nx/nx-linux-x64-musl@npm:17.2.0":
version: 17.2.0 version: 17.2.0
resolution: "@nx/nx-linux-x64-musl@npm:17.2.0" resolution: "@nx/nx-linux-x64-musl@npm:17.2.0"
@ -7304,6 +7365,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@nx/nx-linux-x64-musl@npm:17.2.3":
version: 17.2.3
resolution: "@nx/nx-linux-x64-musl@npm:17.2.3"
conditions: os=linux & cpu=x64 & libc=musl
languageName: node
linkType: hard
"@nx/nx-win32-arm64-msvc@npm:17.2.0": "@nx/nx-win32-arm64-msvc@npm:17.2.0":
version: 17.2.0 version: 17.2.0
resolution: "@nx/nx-win32-arm64-msvc@npm:17.2.0" resolution: "@nx/nx-win32-arm64-msvc@npm:17.2.0"
@ -7311,6 +7379,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@nx/nx-win32-arm64-msvc@npm:17.2.3":
version: 17.2.3
resolution: "@nx/nx-win32-arm64-msvc@npm:17.2.3"
conditions: os=win32 & cpu=arm64
languageName: node
linkType: hard
"@nx/nx-win32-x64-msvc@npm:17.2.0": "@nx/nx-win32-x64-msvc@npm:17.2.0":
version: 17.2.0 version: 17.2.0
resolution: "@nx/nx-win32-x64-msvc@npm:17.2.0" resolution: "@nx/nx-win32-x64-msvc@npm:17.2.0"
@ -7318,6 +7393,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@nx/nx-win32-x64-msvc@npm:17.2.3":
version: 17.2.3
resolution: "@nx/nx-win32-x64-msvc@npm:17.2.3"
conditions: os=win32 & cpu=x64
languageName: node
linkType: hard
"@open-draft/deferred-promise@npm:^2.1.0, @open-draft/deferred-promise@npm:^2.2.0": "@open-draft/deferred-promise@npm:^2.1.0, @open-draft/deferred-promise@npm:^2.2.0":
version: 2.2.0 version: 2.2.0
resolution: "@open-draft/deferred-promise@npm:2.2.0" resolution: "@open-draft/deferred-promise@npm:2.2.0"
@ -19087,8 +19169,8 @@ __metadata:
"eslint-plugin-twenty@file:../eslint-plugin-twenty::locator=twenty-front%40workspace%3Apackages%2Ftwenty-front": "eslint-plugin-twenty@file:../eslint-plugin-twenty::locator=twenty-front%40workspace%3Apackages%2Ftwenty-front":
version: 1.0.3 version: 1.0.3
resolution: "eslint-plugin-twenty@file:../eslint-plugin-twenty#../eslint-plugin-twenty::hash=2e5a59&locator=twenty-front%40workspace%3Apackages%2Ftwenty-front" resolution: "eslint-plugin-twenty@file:../eslint-plugin-twenty#../eslint-plugin-twenty::hash=1e4d37&locator=twenty-front%40workspace%3Apackages%2Ftwenty-front"
checksum: 4b12b2be1d0f355f9b932f209abbda06fe51eca3092592ce443ddfb379dc12af0d00e5a124acc0070b3913b0c6468ba7fb513cd13251c4684abaf2b00152bdea checksum: 8d9085c852371f3cd641baca9865f85f3dbea8e4886fee4ab62ff5d6e040c7674b6997fe352c6416fecbd5ef426d912932f27c0c1e680c021e61c9497b2a767e
languageName: node languageName: node
linkType: hard linkType: hard
@ -27824,6 +27906,90 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"nx@npm:17.2.3":
version: 17.2.3
resolution: "nx@npm:17.2.3"
dependencies:
"@nrwl/tao": "npm:17.2.3"
"@nx/nx-darwin-arm64": "npm:17.2.3"
"@nx/nx-darwin-x64": "npm:17.2.3"
"@nx/nx-freebsd-x64": "npm:17.2.3"
"@nx/nx-linux-arm-gnueabihf": "npm:17.2.3"
"@nx/nx-linux-arm64-gnu": "npm:17.2.3"
"@nx/nx-linux-arm64-musl": "npm:17.2.3"
"@nx/nx-linux-x64-gnu": "npm:17.2.3"
"@nx/nx-linux-x64-musl": "npm:17.2.3"
"@nx/nx-win32-arm64-msvc": "npm:17.2.3"
"@nx/nx-win32-x64-msvc": "npm:17.2.3"
"@yarnpkg/lockfile": "npm:^1.1.0"
"@yarnpkg/parsers": "npm:3.0.0-rc.46"
"@zkochan/js-yaml": "npm:0.0.6"
axios: "npm:^1.5.1"
chalk: "npm:^4.1.0"
cli-cursor: "npm:3.1.0"
cli-spinners: "npm:2.6.1"
cliui: "npm:^8.0.1"
dotenv: "npm:~16.3.1"
dotenv-expand: "npm:~10.0.0"
enquirer: "npm:~2.3.6"
figures: "npm:3.2.0"
flat: "npm:^5.0.2"
fs-extra: "npm:^11.1.0"
glob: "npm:7.1.4"
ignore: "npm:^5.0.4"
jest-diff: "npm:^29.4.1"
js-yaml: "npm:4.1.0"
jsonc-parser: "npm:3.2.0"
lines-and-columns: "npm:~2.0.3"
minimatch: "npm:3.0.5"
node-machine-id: "npm:1.1.12"
npm-run-path: "npm:^4.0.1"
open: "npm:^8.4.0"
semver: "npm:7.5.3"
string-width: "npm:^4.2.3"
strong-log-transformer: "npm:^2.1.0"
tar-stream: "npm:~2.2.0"
tmp: "npm:~0.2.1"
tsconfig-paths: "npm:^4.1.2"
tslib: "npm:^2.3.0"
yargs: "npm:^17.6.2"
yargs-parser: "npm:21.1.1"
peerDependencies:
"@swc-node/register": ^1.6.7
"@swc/core": ^1.3.85
dependenciesMeta:
"@nx/nx-darwin-arm64":
optional: true
"@nx/nx-darwin-x64":
optional: true
"@nx/nx-freebsd-x64":
optional: true
"@nx/nx-linux-arm-gnueabihf":
optional: true
"@nx/nx-linux-arm64-gnu":
optional: true
"@nx/nx-linux-arm64-musl":
optional: true
"@nx/nx-linux-x64-gnu":
optional: true
"@nx/nx-linux-x64-musl":
optional: true
"@nx/nx-win32-arm64-msvc":
optional: true
"@nx/nx-win32-x64-msvc":
optional: true
peerDependenciesMeta:
"@swc-node/register":
optional: true
"@swc/core":
optional: true
bin:
nx: bin/nx.js
nx-cloud: bin/nx-cloud.js
checksum: 56c343fa73dd58b37ca517b8fadfa9cbe1ff0ad59edf7b51f85a3bb81ed8da58b92c679d66884a2146d838d566b122468a94902dc86292b2902bf442f77d43b2
languageName: node
linkType: hard
"nyc@npm:^15.1.0": "nyc@npm:^15.1.0":
version: 15.1.0 version: 15.1.0
resolution: "nyc@npm:15.1.0" resolution: "nyc@npm:15.1.0"
@ -34371,6 +34537,7 @@ __metadata:
luxon: "npm:^3.3.0" luxon: "npm:^3.3.0"
msw: "npm:^2.0.11" msw: "npm:^2.0.11"
msw-storybook-addon: "npm:2.0.0--canary.122.b3ed3b1.0" msw-storybook-addon: "npm:2.0.0--canary.122.b3ed3b1.0"
nx: "npm:17.2.3"
prettier: "npm:^3.1.0" prettier: "npm:^3.1.0"
react: "npm:^18.2.0" react: "npm:^18.2.0"
react-data-grid: "npm:7.0.0-beta.13" react-data-grid: "npm:7.0.0-beta.13"