From f29a6758241595dda22325dd12230f6ba8dca1c6 Mon Sep 17 00:00:00 2001 From: Oliver Date: Sat, 28 Oct 2023 00:35:52 +1100 Subject: [PATCH] [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 --- src/frontend/package.json | 2 + .../src/components/images/ApiImage.tsx | 28 ++++-- .../src/components/nav/BreadcrumbList.tsx | 49 +++++++--- .../src/components/nav/NotificationDrawer.tsx | 3 +- .../src/components/nav/PageDetail.tsx | 7 +- .../src/components/nav/PartCategoryTree.tsx | 94 +++++++++++++++++++ .../src/components/nav/StockLocationTree.tsx | 94 +++++++++++++++++++ .../src/pages/part/CategoryDetail.tsx | 15 ++- src/frontend/src/pages/part/PartDetail.tsx | 15 ++- .../src/pages/stock/LocationDetail.tsx | 13 ++- src/frontend/src/pages/stock/StockDetail.tsx | 13 ++- src/frontend/src/states/ApiState.tsx | 6 ++ src/frontend/yarn.lock | 83 +++++++++++++++- 13 files changed, 392 insertions(+), 30 deletions(-) create mode 100644 src/frontend/src/components/nav/PartCategoryTree.tsx create mode 100644 src/frontend/src/components/nav/StockLocationTree.tsx diff --git a/src/frontend/package.json b/src/frontend/package.json index af3a80362e..0ac80c9f07 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -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": { diff --git a/src/frontend/src/components/images/ApiImage.tsx b/src/frontend/src/components/images/ApiImage.tsx index 0221d04990..60fa98d2a6 100644 --- a/src/frontend/src/components/images/ApiImage.tsx +++ b/src/frontend/src/components/images/ApiImage.tsx @@ -23,11 +23,17 @@ import { api } from '../../App'; export function ApiImage(props: ImageProps) { const [image, setImage] = useState(''); + const [authorized, setAuthorized] = useState(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) => { diff --git a/src/frontend/src/components/nav/BreadcrumbList.tsx b/src/frontend/src/components/nav/BreadcrumbList.tsx index 7223396b29..831f76c15e 100644 --- a/src/frontend/src/components/nav/BreadcrumbList.tsx +++ b/src/frontend/src/components/nav/BreadcrumbList.tsx @@ -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 ( - - {breadcrumbs.map((breadcrumb, index) => { - return ( - breadcrumb.url && navigate(breadcrumb.url)} - > - {breadcrumb.name} - - ); - })} - + + {navCallback && ( + + + + )} + + {breadcrumbs.map((breadcrumb, index) => { + return ( + breadcrumb.url && navigate(breadcrumb.url)} + > + {breadcrumb.name} + + ); + })} + + ); } diff --git a/src/frontend/src/components/nav/NotificationDrawer.tsx b/src/frontend/src/components/nav/NotificationDrawer.tsx index 22eb3774e1..cf7debae66 100644 --- a/src/frontend/src/components/nav/NotificationDrawer.tsx +++ b/src/frontend/src/components/nav/NotificationDrawer.tsx @@ -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={ - {t`Notifications`} + {t`Notifications`} { onClose(); diff --git a/src/frontend/src/components/nav/PageDetail.tsx b/src/frontend/src/components/nav/PageDetail.tsx index 6ef32b3c2b..c66c55df02 100644 --- a/src/frontend/src/components/nav/PageDetail.tsx +++ b/src/frontend/src/components/nav/PageDetail.tsx @@ -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 ( {breadcrumbs && breadcrumbs.length > 0 && ( - + )} diff --git a/src/frontend/src/components/nav/PartCategoryTree.tsx b/src/frontend/src/components/nav/PartCategoryTree.tsx new file mode 100644 index 0000000000..b541c53892 --- /dev/null +++ b/src/frontend/src/components/nav/PartCategoryTree.tsx @@ -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 ( + { + onClose(); + navigate(`/part/category/${node.id}`); + }} + > + {node.label} + + ); + } + + return ( + + + {t`Part Categories`} + + } + > + + + + + + ); +} diff --git a/src/frontend/src/components/nav/StockLocationTree.tsx b/src/frontend/src/components/nav/StockLocationTree.tsx new file mode 100644 index 0000000000..02917989f5 --- /dev/null +++ b/src/frontend/src/components/nav/StockLocationTree.tsx @@ -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 ( + { + onClose(); + navigate(`/stock/location/${node.id}`); + }} + > + {node.label} + + ); + } + + return ( + + + {t`Stock Locations`} + + } + > + + + + + + ); +} diff --git a/src/frontend/src/pages/part/CategoryDetail.tsx b/src/frontend/src/pages/part/CategoryDetail.tsx index 4db4bbce6b..05f9b0e746 100644 --- a/src/frontend/src/pages/part/CategoryDetail.tsx +++ b/src/frontend/src/pages/part/CategoryDetail.tsx @@ -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 ( + { + setTreeOpen(false); + }} + selectedCategory={category?.pk} + /> {category.name ?? 'Top level'}} breadcrumbs={breadcrumbs} + breadcrumbAction={() => { + setTreeOpen(true); + }} /> diff --git a/src/frontend/src/pages/part/PartDetail.tsx b/src/frontend/src/pages/part/PartDetail.tsx index a154a9f5fa..e3d1e692d7 100644 --- a/src/frontend/src/pages/part/PartDetail.tsx +++ b/src/frontend/src/pages/part/PartDetail.tsx @@ -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() { <> + { + setTreeOpen(false); + }} + selectedCategory={part?.category} + /> { + setTreeOpen(true); + }} actions={partActions} /> diff --git a/src/frontend/src/pages/stock/LocationDetail.tsx b/src/frontend/src/pages/stock/LocationDetail.tsx index 75244ef515..a156086894 100644 --- a/src/frontend/src/pages/stock/LocationDetail.tsx +++ b/src/frontend/src/pages/stock/LocationDetail.tsx @@ -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() { <> + setTreeOpen(false)} + selectedLocation={location?.pk} + /> {location.name ?? 'Top level'}} breadcrumbs={breadcrumbs} + breadcrumbAction={() => { + setTreeOpen(true); + }} /> diff --git a/src/frontend/src/pages/stock/StockDetail.tsx b/src/frontend/src/pages/stock/StockDetail.tsx index 7a31b8b07b..ea953bd6ac 100644 --- a/src/frontend/src/pages/stock/StockDetail.tsx +++ b/src/frontend/src/pages/stock/StockDetail.tsx @@ -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 ( + setTreeOpen(false)} + selectedLocation={stockitem?.location} + /> } breadcrumbs={breadcrumbs} + breadcrumbAction={() => { + setTreeOpen(true); + }} /> diff --git a/src/frontend/src/states/ApiState.tsx b/src/frontend/src/states/ApiState.tsx index 703e377a0f..b16034705e 100644 --- a/src/frontend/src/states/ApiState.tsx +++ b/src/frontend/src/states/ApiState.tsx @@ -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: diff --git a/src/frontend/yarn.lock b/src/frontend/yarn.lock index c39cd379bc..f055cda8be 100644 --- a/src/frontend/yarn.lock +++ b/src/frontend/yarn.lock @@ -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==