mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
[React] Tree navigation (#5800)
* Adds placehold "PartCategoryTree" - Global navigation (within the "Part" context) for part categories - Replaces multiple tree views from legacy UI * FIx for ApiImage component - Do not continuously request if the user is unauthorized * Add StockLocation tree * Add initial data to nav tree panels * Display data * Render tree view * Fix unused variables
This commit is contained in:
parent
70578500ca
commit
f29a675824
@ -26,6 +26,7 @@
|
||||
"@mantine/hooks": "<7",
|
||||
"@mantine/modals": "<7",
|
||||
"@mantine/notifications": "<7",
|
||||
"@naisutech/react-tree": "^3.1.0",
|
||||
"@sentry/react": "^7.74.1",
|
||||
"@tabler/icons-react": "^2.39.0",
|
||||
"@tanstack/react-query": "^5.0.0",
|
||||
@ -41,6 +42,7 @@
|
||||
"react-router-dom": "^6.17.0",
|
||||
"react-select": "^5.7.7",
|
||||
"react-simplemde-editor": "^5.2.0",
|
||||
"styled-components": "^6.1.0",
|
||||
"zustand": "^4.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -23,11 +23,17 @@ import { api } from '../../App';
|
||||
export function ApiImage(props: ImageProps) {
|
||||
const [image, setImage] = useState<string>('');
|
||||
|
||||
const [authorized, setAuthorized] = useState<boolean>(true);
|
||||
|
||||
const queryKey = useId();
|
||||
|
||||
const imgQuery = useQuery({
|
||||
queryKey: ['image', queryKey, props.src],
|
||||
enabled: props.src != undefined && props.src != null && props.src != '',
|
||||
enabled:
|
||||
authorized &&
|
||||
props.src != undefined &&
|
||||
props.src != null &&
|
||||
props.src != '',
|
||||
queryFn: async () => {
|
||||
if (!props.src) {
|
||||
return null;
|
||||
@ -37,11 +43,21 @@ export function ApiImage(props: ImageProps) {
|
||||
responseType: 'blob'
|
||||
})
|
||||
.then((response) => {
|
||||
let img = new Blob([response.data], {
|
||||
type: response.headers['content-type']
|
||||
});
|
||||
let url = URL.createObjectURL(img);
|
||||
setImage(url);
|
||||
switch (response.status) {
|
||||
case 200:
|
||||
let img = new Blob([response.data], {
|
||||
type: response.headers['content-type']
|
||||
});
|
||||
let url = URL.createObjectURL(img);
|
||||
setImage(url);
|
||||
break;
|
||||
default:
|
||||
// User is not authorized to view this image
|
||||
setAuthorized(false);
|
||||
console.error(`Error fetching image ${props.src}:`, response);
|
||||
break;
|
||||
}
|
||||
|
||||
return response;
|
||||
})
|
||||
.catch((error) => {
|
||||
|
@ -1,4 +1,12 @@
|
||||
import { Anchor, Breadcrumbs, Paper, Text } from '@mantine/core';
|
||||
import {
|
||||
ActionIcon,
|
||||
Anchor,
|
||||
Breadcrumbs,
|
||||
Group,
|
||||
Paper,
|
||||
Text
|
||||
} from '@mantine/core';
|
||||
import { IconMenu2 } from '@tabler/icons-react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
export type Breadcrumb = {
|
||||
@ -9,23 +17,36 @@ export type Breadcrumb = {
|
||||
/**
|
||||
* Construct a breadcrumb list, with integrated navigation.
|
||||
*/
|
||||
export function BreadcrumbList({ breadcrumbs }: { breadcrumbs: Breadcrumb[] }) {
|
||||
export function BreadcrumbList({
|
||||
breadcrumbs,
|
||||
navCallback
|
||||
}: {
|
||||
breadcrumbs: Breadcrumb[];
|
||||
navCallback?: () => void;
|
||||
}) {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<Paper p="3" radius="xs">
|
||||
<Breadcrumbs separator=">">
|
||||
{breadcrumbs.map((breadcrumb, index) => {
|
||||
return (
|
||||
<Anchor
|
||||
key={`breadcrumb-${index}`}
|
||||
onClick={() => breadcrumb.url && navigate(breadcrumb.url)}
|
||||
>
|
||||
<Text size="sm">{breadcrumb.name}</Text>
|
||||
</Anchor>
|
||||
);
|
||||
})}
|
||||
</Breadcrumbs>
|
||||
<Group spacing="xs">
|
||||
{navCallback && (
|
||||
<ActionIcon key="nav-action" onClick={navCallback}>
|
||||
<IconMenu2 />
|
||||
</ActionIcon>
|
||||
)}
|
||||
<Breadcrumbs key="breadcrumbs" separator=">">
|
||||
{breadcrumbs.map((breadcrumb, index) => {
|
||||
return (
|
||||
<Anchor
|
||||
key={`breadcrumb-${index}`}
|
||||
onClick={() => breadcrumb.url && navigate(breadcrumb.url)}
|
||||
>
|
||||
<Text size="sm">{breadcrumb.name}</Text>
|
||||
</Anchor>
|
||||
);
|
||||
})}
|
||||
</Breadcrumbs>
|
||||
</Group>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { api } from '../../App';
|
||||
import { ApiPaths, apiUrl } from '../../states/ApiState';
|
||||
import { StylishText } from '../items/StylishText';
|
||||
|
||||
/**
|
||||
* Construct a notification drawer.
|
||||
@ -65,7 +66,7 @@ export function NotificationDrawer({
|
||||
}}
|
||||
title={
|
||||
<Group position="apart" noWrap={true}>
|
||||
<Text size="lg">{t`Notifications`}</Text>
|
||||
<StylishText size="lg">{t`Notifications`}</StylishText>
|
||||
<ActionIcon
|
||||
onClick={() => {
|
||||
onClose();
|
||||
|
@ -17,6 +17,7 @@ export function PageDetail({
|
||||
detail,
|
||||
imageUrl,
|
||||
breadcrumbs,
|
||||
breadcrumbAction,
|
||||
actions
|
||||
}: {
|
||||
title?: string;
|
||||
@ -24,13 +25,17 @@ export function PageDetail({
|
||||
imageUrl?: string;
|
||||
detail?: ReactNode;
|
||||
breadcrumbs?: Breadcrumb[];
|
||||
breadcrumbAction?: () => void;
|
||||
actions?: ReactNode[];
|
||||
}) {
|
||||
return (
|
||||
<Stack spacing="xs">
|
||||
{breadcrumbs && breadcrumbs.length > 0 && (
|
||||
<Paper p="xs" radius="xs" shadow="xs">
|
||||
<BreadcrumbList breadcrumbs={breadcrumbs} />
|
||||
<BreadcrumbList
|
||||
navCallback={breadcrumbAction}
|
||||
breadcrumbs={breadcrumbs}
|
||||
/>
|
||||
</Paper>
|
||||
)}
|
||||
<Paper p="xs" radius="xs" shadow="xs">
|
||||
|
94
src/frontend/src/components/nav/PartCategoryTree.tsx
Normal file
94
src/frontend/src/components/nav/PartCategoryTree.tsx
Normal file
@ -0,0 +1,94 @@
|
||||
import { t } from '@lingui/macro';
|
||||
import { Drawer, Group, LoadingOverlay, Stack, Text } from '@mantine/core';
|
||||
import { ReactTree } from '@naisutech/react-tree';
|
||||
import { IconSitemap } from '@tabler/icons-react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { api } from '../../App';
|
||||
import { ApiPaths, apiUrl } from '../../states/ApiState';
|
||||
import { StylishText } from '../items/StylishText';
|
||||
|
||||
export function PartCategoryTree({
|
||||
opened,
|
||||
onClose,
|
||||
selectedCategory
|
||||
}: {
|
||||
opened: boolean;
|
||||
onClose: () => void;
|
||||
selectedCategory?: number | null;
|
||||
}) {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const treeQuery = useQuery({
|
||||
enabled: opened,
|
||||
queryKey: ['part_category_tree', opened],
|
||||
queryFn: async () =>
|
||||
api
|
||||
.get(apiUrl(ApiPaths.category_tree), {})
|
||||
.then((response) =>
|
||||
response.data.map((category: any) => {
|
||||
return {
|
||||
id: category.pk,
|
||||
label: category.name,
|
||||
parentId: category.parent
|
||||
};
|
||||
})
|
||||
)
|
||||
.catch((error) => {
|
||||
console.error('Error fetching part categpry tree:', error);
|
||||
return error;
|
||||
}),
|
||||
refetchOnMount: true
|
||||
});
|
||||
|
||||
function renderNode({ node }: { node: any }) {
|
||||
return (
|
||||
<Group
|
||||
position="apart"
|
||||
key={node.id}
|
||||
noWrap={true}
|
||||
onClick={() => {
|
||||
onClose();
|
||||
navigate(`/part/category/${node.id}`);
|
||||
}}
|
||||
>
|
||||
<Text>{node.label}</Text>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
opened={opened}
|
||||
size="md"
|
||||
position="left"
|
||||
onClose={onClose}
|
||||
withCloseButton={true}
|
||||
styles={{
|
||||
header: {
|
||||
width: '100%'
|
||||
},
|
||||
title: {
|
||||
width: '100%'
|
||||
}
|
||||
}}
|
||||
title={
|
||||
<Group position="left" p="ms" spacing="md" noWrap={true}>
|
||||
<IconSitemap />
|
||||
<StylishText size="lg">{t`Part Categories`}</StylishText>
|
||||
</Group>
|
||||
}
|
||||
>
|
||||
<Stack spacing="xs">
|
||||
<LoadingOverlay visible={treeQuery.isFetching} />
|
||||
<ReactTree
|
||||
nodes={treeQuery.data ?? []}
|
||||
RenderNode={renderNode}
|
||||
defaultSelectedNodes={selectedCategory ? [selectedCategory] : []}
|
||||
showEmptyItems={false}
|
||||
/>
|
||||
</Stack>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
94
src/frontend/src/components/nav/StockLocationTree.tsx
Normal file
94
src/frontend/src/components/nav/StockLocationTree.tsx
Normal file
@ -0,0 +1,94 @@
|
||||
import { t } from '@lingui/macro';
|
||||
import { Drawer, Group, LoadingOverlay, Stack, Text } from '@mantine/core';
|
||||
import { ReactTree } from '@naisutech/react-tree';
|
||||
import { IconSitemap } from '@tabler/icons-react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { api } from '../../App';
|
||||
import { ApiPaths, apiUrl } from '../../states/ApiState';
|
||||
import { StylishText } from '../items/StylishText';
|
||||
|
||||
export function StockLocationTree({
|
||||
opened,
|
||||
onClose,
|
||||
selectedLocation
|
||||
}: {
|
||||
opened: boolean;
|
||||
onClose: () => void;
|
||||
selectedLocation?: number | null;
|
||||
}) {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const treeQuery = useQuery({
|
||||
enabled: opened,
|
||||
queryKey: ['stock_location_tree', opened],
|
||||
queryFn: async () =>
|
||||
api
|
||||
.get(apiUrl(ApiPaths.stock_location_tree), {})
|
||||
.then((response) =>
|
||||
response.data.map((location: any) => {
|
||||
return {
|
||||
id: location.pk,
|
||||
label: location.name,
|
||||
parentId: location.parent
|
||||
};
|
||||
})
|
||||
)
|
||||
.catch((error) => {
|
||||
console.error('Error fetching stock location tree:', error);
|
||||
return error;
|
||||
}),
|
||||
refetchOnMount: true
|
||||
});
|
||||
|
||||
function renderNode({ node }: { node: any }) {
|
||||
return (
|
||||
<Group
|
||||
position="apart"
|
||||
key={node.id}
|
||||
noWrap={true}
|
||||
onClick={() => {
|
||||
onClose();
|
||||
navigate(`/stock/location/${node.id}`);
|
||||
}}
|
||||
>
|
||||
<Text>{node.label}</Text>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
opened={opened}
|
||||
size="md"
|
||||
position="left"
|
||||
onClose={onClose}
|
||||
withCloseButton={true}
|
||||
styles={{
|
||||
header: {
|
||||
width: '100%'
|
||||
},
|
||||
title: {
|
||||
width: '100%'
|
||||
}
|
||||
}}
|
||||
title={
|
||||
<Group position="left" noWrap={true} spacing="md" p="md">
|
||||
<IconSitemap />
|
||||
<StylishText size="lg">{t`Stock Locations`}</StylishText>
|
||||
</Group>
|
||||
}
|
||||
>
|
||||
<Stack spacing="xs">
|
||||
<LoadingOverlay visible={treeQuery.isFetching} />
|
||||
<ReactTree
|
||||
nodes={treeQuery.data ?? []}
|
||||
showEmptyItems={false}
|
||||
RenderNode={renderNode}
|
||||
defaultSelectedNodes={selectedLocation ? [selectedLocation] : []}
|
||||
/>
|
||||
</Stack>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
@ -5,12 +5,13 @@ import {
|
||||
IconListDetails,
|
||||
IconSitemap
|
||||
} from '@tabler/icons-react';
|
||||
import { useMemo } from 'react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { PlaceholderPanel } from '../../components/items/Placeholder';
|
||||
import { PageDetail } from '../../components/nav/PageDetail';
|
||||
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
||||
import { PartCategoryTree } from '../../components/nav/PartCategoryTree';
|
||||
import { PartCategoryTable } from '../../components/tables/part/PartCategoryTable';
|
||||
import { PartListTable } from '../../components/tables/part/PartTable';
|
||||
import { useInstance } from '../../hooks/UseInstance';
|
||||
@ -24,6 +25,8 @@ import { ApiPaths } from '../../states/ApiState';
|
||||
export default function CategoryDetail({}: {}) {
|
||||
const { id } = useParams();
|
||||
|
||||
const [treeOpen, setTreeOpen] = useState(false);
|
||||
|
||||
const {
|
||||
instance: category,
|
||||
refreshInstance,
|
||||
@ -88,10 +91,20 @@ export default function CategoryDetail({}: {}) {
|
||||
return (
|
||||
<Stack spacing="xs">
|
||||
<LoadingOverlay visible={instanceQuery.isFetching} />
|
||||
<PartCategoryTree
|
||||
opened={treeOpen}
|
||||
onClose={() => {
|
||||
setTreeOpen(false);
|
||||
}}
|
||||
selectedCategory={category?.pk}
|
||||
/>
|
||||
<PageDetail
|
||||
title={t`Part Category`}
|
||||
detail={<Text>{category.name ?? 'Top level'}</Text>}
|
||||
breadcrumbs={breadcrumbs}
|
||||
breadcrumbAction={() => {
|
||||
setTreeOpen(true);
|
||||
}}
|
||||
/>
|
||||
<PanelGroup pageKey="partcategory" panels={categoryPanels} />
|
||||
</Stack>
|
||||
|
@ -27,12 +27,13 @@ import {
|
||||
IconUnlink,
|
||||
IconVersions
|
||||
} from '@tabler/icons-react';
|
||||
import { useMemo } from 'react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { ActionDropdown } from '../../components/items/ActionDropdown';
|
||||
import { PageDetail } from '../../components/nav/PageDetail';
|
||||
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
||||
import { PartCategoryTree } from '../../components/nav/PartCategoryTree';
|
||||
import { AttachmentTable } from '../../components/tables/general/AttachmentTable';
|
||||
import { PartParameterTable } from '../../components/tables/part/PartParameterTable';
|
||||
import { PartVariantTable } from '../../components/tables/part/PartVariantTable';
|
||||
@ -52,6 +53,8 @@ export default function PartDetail() {
|
||||
|
||||
const user = useUserState();
|
||||
|
||||
const [treeOpen, setTreeOpen] = useState(false);
|
||||
|
||||
const {
|
||||
instance: part,
|
||||
refreshInstance,
|
||||
@ -289,12 +292,22 @@ export default function PartDetail() {
|
||||
<>
|
||||
<Stack spacing="xs">
|
||||
<LoadingOverlay visible={instanceQuery.isFetching} />
|
||||
<PartCategoryTree
|
||||
opened={treeOpen}
|
||||
onClose={() => {
|
||||
setTreeOpen(false);
|
||||
}}
|
||||
selectedCategory={part?.category}
|
||||
/>
|
||||
<PageDetail
|
||||
title={t`Part` + ': ' + part.full_name}
|
||||
subtitle={part.description}
|
||||
imageUrl={part.image}
|
||||
detail={partDetail}
|
||||
breadcrumbs={breadcrumbs}
|
||||
breadcrumbAction={() => {
|
||||
setTreeOpen(true);
|
||||
}}
|
||||
actions={partActions}
|
||||
/>
|
||||
<PanelGroup pageKey="part" panels={partPanels} />
|
||||
|
@ -1,11 +1,12 @@
|
||||
import { t } from '@lingui/macro';
|
||||
import { LoadingOverlay, Stack, Text } from '@mantine/core';
|
||||
import { IconPackages, IconSitemap } from '@tabler/icons-react';
|
||||
import { useMemo } from 'react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { PageDetail } from '../../components/nav/PageDetail';
|
||||
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
||||
import { StockLocationTree } from '../../components/nav/StockLocationTree';
|
||||
import { StockItemTable } from '../../components/tables/stock/StockItemTable';
|
||||
import { StockLocationTable } from '../../components/tables/stock/StockLocationTable';
|
||||
import { useInstance } from '../../hooks/UseInstance';
|
||||
@ -14,6 +15,8 @@ import { ApiPaths } from '../../states/ApiState';
|
||||
export default function Stock() {
|
||||
const { id } = useParams();
|
||||
|
||||
const [treeOpen, setTreeOpen] = useState(false);
|
||||
|
||||
const {
|
||||
instance: location,
|
||||
refreshInstance,
|
||||
@ -70,10 +73,18 @@ export default function Stock() {
|
||||
<>
|
||||
<Stack>
|
||||
<LoadingOverlay visible={instanceQuery.isFetching} />
|
||||
<StockLocationTree
|
||||
opened={treeOpen}
|
||||
onClose={() => setTreeOpen(false)}
|
||||
selectedLocation={location?.pk}
|
||||
/>
|
||||
<PageDetail
|
||||
title={t`Stock Items`}
|
||||
detail={<Text>{location.name ?? 'Top level'}</Text>}
|
||||
breadcrumbs={breadcrumbs}
|
||||
breadcrumbAction={() => {
|
||||
setTreeOpen(true);
|
||||
}}
|
||||
/>
|
||||
<PanelGroup pageKey="stocklocation" panels={locationPanels} />
|
||||
</Stack>
|
||||
|
@ -9,12 +9,13 @@ import {
|
||||
IconPaperclip,
|
||||
IconSitemap
|
||||
} from '@tabler/icons-react';
|
||||
import { useMemo } from 'react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { PlaceholderPanel } from '../../components/items/Placeholder';
|
||||
import { PageDetail } from '../../components/nav/PageDetail';
|
||||
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
||||
import { StockLocationTree } from '../../components/nav/StockLocationTree';
|
||||
import { AttachmentTable } from '../../components/tables/general/AttachmentTable';
|
||||
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
|
||||
import { useInstance } from '../../hooks/UseInstance';
|
||||
@ -23,6 +24,8 @@ import { ApiPaths, apiUrl } from '../../states/ApiState';
|
||||
export default function StockDetail() {
|
||||
const { id } = useParams();
|
||||
|
||||
const [treeOpen, setTreeOpen] = useState(false);
|
||||
|
||||
const {
|
||||
instance: stockitem,
|
||||
refreshInstance,
|
||||
@ -110,6 +113,11 @@ export default function StockDetail() {
|
||||
return (
|
||||
<Stack>
|
||||
<LoadingOverlay visible={instanceQuery.isFetching} />
|
||||
<StockLocationTree
|
||||
opened={treeOpen}
|
||||
onClose={() => setTreeOpen(false)}
|
||||
selectedLocation={stockitem?.location}
|
||||
/>
|
||||
<PageDetail
|
||||
title={t`Stock Items`}
|
||||
subtitle={stockitem.part_detail?.full_name ?? 'name goes here'}
|
||||
@ -119,6 +127,9 @@ export default function StockDetail() {
|
||||
</Alert>
|
||||
}
|
||||
breadcrumbs={breadcrumbs}
|
||||
breadcrumbAction={() => {
|
||||
setTreeOpen(true);
|
||||
}}
|
||||
/>
|
||||
<PanelGroup pageKey="stockitem" panels={stockPanels} />
|
||||
</Stack>
|
||||
|
@ -76,6 +76,7 @@ export enum ApiPaths {
|
||||
// Part URLs
|
||||
part_list = 'api-part-list',
|
||||
category_list = 'api-category-list',
|
||||
category_tree = 'api-category-tree',
|
||||
related_part_list = 'api-related-part-list',
|
||||
part_attachment_list = 'api-part-attachment-list',
|
||||
part_parameter_list = 'api-part-parameter-list',
|
||||
@ -89,6 +90,7 @@ export enum ApiPaths {
|
||||
// Stock Item URLs
|
||||
stock_item_list = 'api-stock-item-list',
|
||||
stock_location_list = 'api-stock-location-list',
|
||||
stock_location_tree = 'api-stock-location-tree',
|
||||
stock_attachment_list = 'api-stock-attachment-list',
|
||||
|
||||
// Purchase Order URLs
|
||||
@ -165,6 +167,8 @@ export function apiEndpoint(path: ApiPaths): string {
|
||||
return 'part/parameter/template/';
|
||||
case ApiPaths.category_list:
|
||||
return 'part/category/';
|
||||
case ApiPaths.category_tree:
|
||||
return 'part/category/tree/';
|
||||
case ApiPaths.related_part_list:
|
||||
return 'part/related/';
|
||||
case ApiPaths.part_attachment_list:
|
||||
@ -179,6 +183,8 @@ export function apiEndpoint(path: ApiPaths): string {
|
||||
return 'stock/';
|
||||
case ApiPaths.stock_location_list:
|
||||
return 'stock/location/';
|
||||
case ApiPaths.stock_location_tree:
|
||||
return 'stock/location/tree/';
|
||||
case ApiPaths.stock_attachment_list:
|
||||
return 'stock/attachment/';
|
||||
case ApiPaths.purchase_order_list:
|
||||
|
@ -389,6 +389,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43"
|
||||
integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==
|
||||
|
||||
"@emotion/is-prop-valid@^1.2.0", "@emotion/is-prop-valid@^1.2.1":
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz#23116cf1ed18bfeac910ec6436561ecb1a3885cc"
|
||||
integrity sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==
|
||||
dependencies:
|
||||
"@emotion/memoize" "^0.8.1"
|
||||
|
||||
"@emotion/memoize@^0.8.1":
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17"
|
||||
@ -424,7 +431,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.2.tgz#d58e788ee27267a14342303e1abb3d508b6d0fec"
|
||||
integrity sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==
|
||||
|
||||
"@emotion/unitless@^0.8.1":
|
||||
"@emotion/unitless@^0.8.0", "@emotion/unitless@^0.8.1":
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.1.tgz#182b5a4704ef8ad91bde93f7a860a88fd92c79a3"
|
||||
integrity sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==
|
||||
@ -963,6 +970,15 @@
|
||||
dependencies:
|
||||
moo "^0.5.1"
|
||||
|
||||
"@naisutech/react-tree@^3.1.0":
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@naisutech/react-tree/-/react-tree-3.1.0.tgz#a83820425b53a1ec7a39804ff8bd9024f0a953f4"
|
||||
integrity sha512-6p1l3ZIaTmbgiAf/mpFELvqwl51LDhr+09f7L+C27DBLWjtleezCMoUuiSLhrJgpixCPNL13PuI3q2yn+0AGvA==
|
||||
dependencies:
|
||||
"@emotion/is-prop-valid" "^1.2.0"
|
||||
nanoid "^4.0.0"
|
||||
react-draggable "^4.4.5"
|
||||
|
||||
"@playwright/test@^1.39.0":
|
||||
version "1.39.0"
|
||||
resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.39.0.tgz#d10ba8e38e44104499e25001945f07faa9fa91cd"
|
||||
@ -1302,6 +1318,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.4.tgz#fedc3e5b15c26dc18faae96bf1317487cb3658cf"
|
||||
integrity sha512-2L9ifAGl7wmXwP4v3pN4p2FLhD0O1qsJpvKmNin5VA8+UvNVb447UDaAEV6UdrkA+m/Xs58U1RFps44x6TFsVQ==
|
||||
|
||||
"@types/stylis@^4.0.2":
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/stylis/-/stylis-4.2.2.tgz#baabb6b3aa6787e90a6bd6cd75cd8fb9a4f256a3"
|
||||
integrity sha512-Rm17MsTpQQP5Jq4BF7CdrxJsDufoiL/q5IbJZYZmOZAJALyijgF7BzLgobXUqraNcQdqFYLYGeglDp6QzaxPpg==
|
||||
|
||||
"@types/tern@*":
|
||||
version "0.23.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/tern/-/tern-0.23.5.tgz#8d369a06749ea83956885cb734788ec208a0e900"
|
||||
@ -1478,6 +1499,11 @@ camelcase@^6.2.0:
|
||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
|
||||
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
|
||||
|
||||
camelize@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.1.tgz#89b7e16884056331a35d6b5ad064332c91daa6c3"
|
||||
integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==
|
||||
|
||||
caniuse-lite@^1.0.30001541:
|
||||
version "1.0.30001549"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001549.tgz#7d1a3dce7ea78c06ed72c32c2743ea364b3615aa"
|
||||
@ -1653,12 +1679,26 @@ cosmiconfig@^8.0.0:
|
||||
parse-json "^5.2.0"
|
||||
path-type "^4.0.0"
|
||||
|
||||
css-color-keywords@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05"
|
||||
integrity sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==
|
||||
|
||||
css-to-react-native@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.2.0.tgz#cdd8099f71024e149e4f6fe17a7d46ecd55f1e32"
|
||||
integrity sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==
|
||||
dependencies:
|
||||
camelize "^1.0.0"
|
||||
css-color-keywords "^1.0.0"
|
||||
postcss-value-parser "^4.0.2"
|
||||
|
||||
csstype@3.0.9:
|
||||
version "3.0.9"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.9.tgz#6410af31b26bd0520933d02cbc64fce9ce3fbf0b"
|
||||
integrity sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw==
|
||||
|
||||
csstype@^3.0.2:
|
||||
csstype@^3.0.2, csstype@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b"
|
||||
integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==
|
||||
@ -2246,6 +2286,11 @@ nanoid@^3.3.6:
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
|
||||
integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
|
||||
|
||||
nanoid@^4.0.0:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-4.0.2.tgz#140b3c5003959adbebf521c170f282c5e7f9fb9e"
|
||||
integrity sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==
|
||||
|
||||
node-releases@^2.0.13:
|
||||
version "2.0.13"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d"
|
||||
@ -2392,7 +2437,12 @@ pofile@^1.1.4:
|
||||
resolved "https://registry.yarnpkg.com/pofile/-/pofile-1.1.4.tgz#eab7e29f5017589b2a61b2259dff608c0cad76a2"
|
||||
integrity sha512-r6Q21sKsY1AjTVVjOuU02VYKVNQGJNQHjTIvs4dEbeuuYfxgYk/DGD2mqqq4RDaVkwdSq0VEtmQUOPe/wH8X3g==
|
||||
|
||||
postcss@^8.4.27:
|
||||
postcss-value-parser@^4.0.2:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
|
||||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||
|
||||
postcss@^8.4.27, postcss@^8.4.31:
|
||||
version "8.4.31"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d"
|
||||
integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==
|
||||
@ -2691,6 +2741,11 @@ semver@^6.3.1:
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||
|
||||
shallowequal@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8"
|
||||
integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==
|
||||
|
||||
signal-exit@^3.0.2:
|
||||
version "3.0.7"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
|
||||
@ -2736,11 +2791,31 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||
dependencies:
|
||||
ansi-regex "^5.0.1"
|
||||
|
||||
styled-components@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-6.1.0.tgz#228e3ab9c1ee1daa4b0a06aae30df0ed14fda274"
|
||||
integrity sha512-VWNfYYBuXzuLS/QYEeoPgMErP26WL+dX9//rEh80B2mmlS1yRxRxuL5eax4m6ybYEUoHWlTy2XOU32767mlMkg==
|
||||
dependencies:
|
||||
"@emotion/is-prop-valid" "^1.2.1"
|
||||
"@emotion/unitless" "^0.8.0"
|
||||
"@types/stylis" "^4.0.2"
|
||||
css-to-react-native "^3.2.0"
|
||||
csstype "^3.1.2"
|
||||
postcss "^8.4.31"
|
||||
shallowequal "^1.1.0"
|
||||
stylis "^4.3.0"
|
||||
tslib "^2.5.0"
|
||||
|
||||
stylis@4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51"
|
||||
integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==
|
||||
|
||||
stylis@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.0.tgz#abe305a669fc3d8777e10eefcfc73ad861c5588c"
|
||||
integrity sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==
|
||||
|
||||
supports-color@^5.3.0:
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
|
||||
@ -2801,7 +2876,7 @@ tslib@^1.9.0:
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
||||
tslib@^2.0.0, tslib@^2.1.0, tslib@^2.4.0, "tslib@^2.4.1 || ^1.9.3":
|
||||
tslib@^2.0.0, tslib@^2.1.0, tslib@^2.4.0, "tslib@^2.4.1 || ^1.9.3", tslib@^2.5.0:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
|
||||
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
|
||||
|
Loading…
Reference in New Issue
Block a user