Merge pull request #270 from fleekxyz/release/release-v0.0.9
Release v0.0.9 to main
This commit is contained in:
commit
57ea7fc545
|
|
@ -22,6 +22,10 @@ query lastNFAsPaginated(
|
||||||
accessPoints {
|
accessPoints {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
owner {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
verified
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -31,41 +35,52 @@ query totalTokens($contractId: ID!) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
query getLatestNFAs {
|
|
||||||
tokens {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
query getNFADetail($id: ID!) {
|
query getNFADetail($id: ID!) {
|
||||||
token(id: $id) {
|
token(id: $id) {
|
||||||
tokenId
|
accessPoints {
|
||||||
owner {
|
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
name
|
|
||||||
description
|
description
|
||||||
ENS
|
|
||||||
externalURL
|
|
||||||
logo
|
|
||||||
color
|
color
|
||||||
createdAt
|
createdAt
|
||||||
accessPoints {
|
ENS
|
||||||
createdAt
|
externalURL
|
||||||
contentVerified
|
gitRepository {
|
||||||
owner {
|
id
|
||||||
id
|
}
|
||||||
}
|
logo
|
||||||
|
name
|
||||||
|
owner {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
verified
|
verified
|
||||||
verifier {
|
verifier {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
gitRepository {
|
tokenId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
query getAccessPointsNFA(
|
||||||
|
$tokenId: String!
|
||||||
|
$orderBy: AccessPoint_orderBy
|
||||||
|
$orderDirection: OrderDirection
|
||||||
|
$pageSize: Int
|
||||||
|
$skip: Int
|
||||||
|
) {
|
||||||
|
accessPoints(
|
||||||
|
where: { token: $tokenId }
|
||||||
|
orderDirection: $orderDirection
|
||||||
|
orderBy: $orderBy
|
||||||
|
first: $pageSize
|
||||||
|
skip: $skip
|
||||||
|
) {
|
||||||
|
contentVerified
|
||||||
|
createdAt
|
||||||
|
owner {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,6 @@
|
||||||
"@types/react": "^18.0.25",
|
"@types/react": "^18.0.25",
|
||||||
"@types/react-dom": "^18.0.9",
|
"@types/react-dom": "^18.0.9",
|
||||||
"@vitejs/plugin-react": "2.2.0",
|
"@vitejs/plugin-react": "2.2.0",
|
||||||
"autoprefixer": "^10.4.13",
|
|
||||||
"babel-loader": "^8.3.0",
|
"babel-loader": "^8.3.0",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"eslint": "^8.28.0",
|
"eslint": "^8.28.0",
|
||||||
|
|
@ -59,11 +58,9 @@
|
||||||
"eslint-plugin-react": "^7.31.11",
|
"eslint-plugin-react": "^7.31.11",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"ethers": "^5.7.2",
|
"ethers": "^5.7.2",
|
||||||
"postcss": "^8.4.21",
|
|
||||||
"prettier": "^2.8.0",
|
"prettier": "^2.8.0",
|
||||||
"process": "^0.11.10",
|
"process": "^0.11.10",
|
||||||
"react-query": "^3.39.2",
|
"react-query": "^3.39.2",
|
||||||
"tailwindcss": "^3.2.4",
|
|
||||||
"ts-loader": "^9.4.1",
|
"ts-loader": "^9.4.1",
|
||||||
"typescript": "^4.9.3",
|
"typescript": "^4.9.3",
|
||||||
"vite": "^3.2.4",
|
"vite": "^3.2.4",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
import { createContext } from './utils';
|
||||||
|
|
||||||
|
export type AppContext = {
|
||||||
|
backgroundColor: string;
|
||||||
|
setBackgroundColor: (color: string) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const [AppProvider, useContext] = createContext<AppContext>({
|
||||||
|
name: 'App.Context',
|
||||||
|
hookName: 'App.useContext',
|
||||||
|
providerName: 'App.Provider',
|
||||||
|
});
|
||||||
|
|
||||||
|
export abstract class App {
|
||||||
|
static readonly useContext = useContext;
|
||||||
|
static readonly Provider: React.FC<App.AppProps> = ({ children }) => {
|
||||||
|
const [backgroundColor, setBackgroundColor] = useState('');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppProvider value={{ backgroundColor, setBackgroundColor }}>
|
||||||
|
{children}
|
||||||
|
</AppProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace App {
|
||||||
|
export type AppProps = {
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ import { HashRouter, Navigate, Route, Routes } from 'react-router-dom';
|
||||||
|
|
||||||
import { themeGlobals } from '@/theme/globals';
|
import { themeGlobals } from '@/theme/globals';
|
||||||
|
|
||||||
|
import { App as AppContext } from './app.context';
|
||||||
import { AppPage, ToastProvider } from './components';
|
import { AppPage, ToastProvider } from './components';
|
||||||
import {
|
import {
|
||||||
ComponentsTest,
|
ComponentsTest,
|
||||||
|
|
@ -17,17 +18,19 @@ export const App: React.FC = () => {
|
||||||
<>
|
<>
|
||||||
<HashRouter>
|
<HashRouter>
|
||||||
<ToastProvider />
|
<ToastProvider />
|
||||||
<AppPage>
|
<AppContext.Provider>
|
||||||
<Routes>
|
<AppPage>
|
||||||
<Route path="/" element={<ExploreView />} />
|
<Routes>
|
||||||
<Route path="/mint" element={<Mint />} />
|
<Route path="/" element={<ExploreView />} />
|
||||||
<Route path="/create-ap/:id" element={<CreateAP />} />
|
<Route path="/mint" element={<Mint />} />
|
||||||
<Route path="/nfa/:id" element={<IndexedNFAView />} />
|
<Route path="/create-ap/:id" element={<CreateAP />} />
|
||||||
{/** TODO remove for release */}
|
<Route path="/nfa/:id" element={<IndexedNFAView />} />
|
||||||
<Route path="/components-test" element={<ComponentsTest />} />
|
{/** TODO remove for release */}
|
||||||
<Route path="*" element={<Navigate to="/" />} />
|
<Route path="/components-test" element={<ComponentsTest />} />
|
||||||
</Routes>
|
<Route path="*" element={<Navigate to="/" />} />
|
||||||
</AppPage>
|
</Routes>
|
||||||
|
</AppPage>
|
||||||
|
</AppContext.Provider>
|
||||||
</HashRouter>
|
</HashRouter>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 8.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 9.8 KiB |
|
|
@ -3,6 +3,7 @@ import { styled } from '@/theme';
|
||||||
export abstract class CardStyles {
|
export abstract class CardStyles {
|
||||||
static readonly Container = styled('div', {
|
static readonly Container = styled('div', {
|
||||||
width: '$full',
|
width: '$full',
|
||||||
|
height: 'fit-content',
|
||||||
backgroundColor: '$slate2',
|
backgroundColor: '$slate2',
|
||||||
borderRadius: '$xlh',
|
borderRadius: '$xlh',
|
||||||
padding: '$7',
|
padding: '$7',
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,6 @@ export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
|
||||||
|
|
||||||
return props[size as 'sm' | 'md' | 'lg'];
|
return props[size as 'sm' | 'md' | 'lg'];
|
||||||
}, [size]);
|
}, [size]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
|
@ -73,10 +72,10 @@ export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
|
||||||
size={size}
|
size={size}
|
||||||
{...rest}
|
{...rest}
|
||||||
css={{
|
css={{
|
||||||
padding: 0,
|
|
||||||
minWidth,
|
minWidth,
|
||||||
fontSize,
|
fontSize,
|
||||||
borderRadius: isRound ? '$full' : undefined,
|
borderRadius: isRound ? '$full' : undefined,
|
||||||
|
padding: 0,
|
||||||
...(rest.css ?? {}),
|
...(rest.css ?? {}),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { Flex } from '@/components';
|
||||||
|
import { styled } from '@/theme';
|
||||||
|
|
||||||
|
export const ColorPickerStyles = {
|
||||||
|
Container: styled('div', {
|
||||||
|
position: 'relative',
|
||||||
|
|
||||||
|
[`${Flex}`]: {
|
||||||
|
gap: '$3h',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
Input: styled('input', {
|
||||||
|
position: 'absolute',
|
||||||
|
right: '4rem',
|
||||||
|
height: '1.25rem',
|
||||||
|
}),
|
||||||
|
Image: styled('img', {
|
||||||
|
display: 'none',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
@ -3,7 +3,9 @@
|
||||||
import ColorThief from 'colorthief';
|
import ColorThief from 'colorthief';
|
||||||
import { useRef } from 'react';
|
import { useRef } from 'react';
|
||||||
|
|
||||||
import { Button, Card, Flex, Icon } from '@/components';
|
import { Button, Card, Flex, Icon, Text } from '@/components';
|
||||||
|
|
||||||
|
import { ColorPickerStyles as CS } from './color-picker.styles';
|
||||||
|
|
||||||
export type ColorPickerProps = {
|
export type ColorPickerProps = {
|
||||||
logoColor: string;
|
logoColor: string;
|
||||||
|
|
@ -38,9 +40,9 @@ export const ColorPicker: React.FC<ColorPickerProps> = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card.Text css={{ height: '$22', mt: '$6' }}>
|
<Card.Text css={{ height: '$22', mt: '$6' }}>
|
||||||
<div className="relative">
|
<CS.Container>
|
||||||
<Flex css={{ gap: '$3h', alignItems: 'center' }}>
|
<Flex css={{ gap: '0.0625rem' }}>
|
||||||
<span>Primary Color</span>
|
<Text>Primary Color</Text>
|
||||||
<Button
|
<Button
|
||||||
leftIcon={
|
leftIcon={
|
||||||
<Icon name="square" css={{ color: `${logoColor || '$black'}` }} />
|
<Icon name="square" css={{ color: `${logoColor || '$black'}` }} />
|
||||||
|
|
@ -55,23 +57,22 @@ export const ColorPicker: React.FC<ColorPickerProps> = ({
|
||||||
color: '$slate12',
|
color: '$slate12',
|
||||||
zIndex: '$docked',
|
zIndex: '$docked',
|
||||||
minWidth: '$28',
|
minWidth: '$28',
|
||||||
|
gap: '0.125rem',
|
||||||
}}
|
}}
|
||||||
onClick={handleColorPickerClick}
|
onClick={handleColorPickerClick}
|
||||||
>
|
>
|
||||||
{logoColor.toUpperCase() || '#000000'}
|
{logoColor.toUpperCase() || '#000000'}
|
||||||
</Button>
|
</Button>
|
||||||
<input
|
<CS.Input
|
||||||
ref={inputColorRef}
|
ref={inputColorRef}
|
||||||
className="absolute right-16 h-5"
|
|
||||||
type="color"
|
type="color"
|
||||||
value={logoColor}
|
value={logoColor}
|
||||||
onChange={handleColorChange}
|
onChange={handleColorChange}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
</div>
|
</CS.Container>
|
||||||
|
|
||||||
<img
|
<CS.Image
|
||||||
className="hidden"
|
|
||||||
src={logo}
|
src={logo}
|
||||||
ref={imageRef}
|
ref={imageRef}
|
||||||
onLoad={handleLogoLoad}
|
onLoad={handleLogoLoad}
|
||||||
|
|
|
||||||
|
|
@ -5,3 +5,4 @@ export * from './fleek-name-icon';
|
||||||
export * from './beta-tag-icon';
|
export * from './beta-tag-icon';
|
||||||
export * from './error-icon';
|
export * from './error-icon';
|
||||||
export * from './fleek-logo-icon';
|
export * from './fleek-logo-icon';
|
||||||
|
export * from './opensea-icon';
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { IconStyles as IS } from '../icon.styles';
|
||||||
|
|
||||||
|
export const OpenseaIcon: React.FC<IS.CustomProps> = (props) => (
|
||||||
|
<IS.Custom
|
||||||
|
{...props}
|
||||||
|
viewBox="0 0 90 90"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M45 0C20.151 0 0 20.151 0 45C0 69.849 20.151 90 45 90C69.849 90 90 69.849 90 45C90 20.151 69.858 0 45 0ZM22.203 46.512L22.392 46.206L34.101 27.891C34.272 27.63 34.677 27.657 34.803 27.945C36.756 32.328 38.448 37.782 37.656 41.175C37.323 42.57 36.396 44.46 35.352 46.206C35.217 46.458 35.073 46.71 34.911 46.953C34.839 47.061 34.713 47.124 34.578 47.124H22.545C22.221 47.124 22.032 46.773 22.203 46.512ZM74.376 52.812C74.376 52.983 74.277 53.127 74.133 53.19C73.224 53.577 70.119 55.008 68.832 56.799C65.538 61.38 63.027 67.932 57.402 67.932H33.948C25.632 67.932 18.9 61.173 18.9 52.83V52.56C18.9 52.344 19.08 52.164 19.305 52.164H32.373C32.634 52.164 32.823 52.398 32.805 52.659C32.706 53.505 32.868 54.378 33.273 55.17C34.047 56.745 35.658 57.726 37.395 57.726H43.866V52.677H37.467C37.143 52.677 36.945 52.299 37.134 52.029C37.206 51.921 37.278 51.813 37.368 51.687C37.971 50.823 38.835 49.491 39.699 47.97C40.284 46.944 40.851 45.846 41.31 44.748C41.4 44.55 41.472 44.343 41.553 44.145C41.679 43.794 41.805 43.461 41.895 43.137C41.985 42.858 42.066 42.57 42.138 42.3C42.354 41.364 42.444 40.374 42.444 39.348C42.444 38.943 42.426 38.52 42.39 38.124C42.372 37.683 42.318 37.242 42.264 36.801C42.228 36.414 42.156 36.027 42.084 35.631C41.985 35.046 41.859 34.461 41.715 33.876L41.661 33.651C41.553 33.246 41.454 32.868 41.328 32.463C40.959 31.203 40.545 29.97 40.095 28.818C39.933 28.359 39.753 27.918 39.564 27.486C39.294 26.82 39.015 26.217 38.763 25.65C38.628 25.389 38.52 25.155 38.412 24.912C38.286 24.642 38.16 24.372 38.025 24.111C37.935 23.913 37.827 23.724 37.755 23.544L36.963 22.086C36.855 21.888 37.035 21.645 37.251 21.708L42.201 23.049H42.219C42.228 23.049 42.228 23.049 42.237 23.049L42.885 23.238L43.605 23.436L43.866 23.508V20.574C43.866 19.152 45 18 46.413 18C47.115 18 47.754 18.288 48.204 18.756C48.663 19.224 48.951 19.863 48.951 20.574V24.939L49.482 25.083C49.518 25.101 49.563 25.119 49.599 25.146C49.725 25.236 49.914 25.38 50.148 25.56C50.337 25.704 50.535 25.884 50.769 26.073C51.246 26.46 51.822 26.955 52.443 27.522C52.605 27.666 52.767 27.81 52.92 27.963C53.721 28.71 54.621 29.583 55.485 30.555C55.728 30.834 55.962 31.104 56.205 31.401C56.439 31.698 56.7 31.986 56.916 32.274C57.213 32.661 57.519 33.066 57.798 33.489C57.924 33.687 58.077 33.894 58.194 34.092C58.554 34.623 58.86 35.172 59.157 35.721C59.283 35.973 59.409 36.252 59.517 36.522C59.85 37.26 60.111 38.007 60.273 38.763C60.327 38.925 60.363 39.096 60.381 39.258V39.294C60.435 39.51 60.453 39.744 60.471 39.987C60.543 40.752 60.507 41.526 60.345 42.3C60.273 42.624 60.183 42.93 60.075 43.263C59.958 43.578 59.85 43.902 59.706 44.217C59.427 44.856 59.103 45.504 58.716 46.098C58.59 46.323 58.437 46.557 58.293 46.782C58.131 47.016 57.96 47.241 57.816 47.457C57.609 47.736 57.393 48.024 57.168 48.285C56.97 48.555 56.772 48.825 56.547 49.068C56.241 49.437 55.944 49.779 55.629 50.112C55.449 50.328 55.251 50.553 55.044 50.751C54.846 50.976 54.639 51.174 54.459 51.354C54.144 51.669 53.892 51.903 53.676 52.11L53.163 52.569C53.091 52.641 52.992 52.677 52.893 52.677H48.951V57.726H53.91C55.017 57.726 56.07 57.339 56.925 56.61C57.213 56.358 58.482 55.26 59.985 53.604C60.039 53.541 60.102 53.505 60.174 53.487L73.863 49.527C74.124 49.455 74.376 49.644 74.376 49.914V52.812V52.812Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
</IS.Custom>
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { IconStyles as IS } from '../icon.styles';
|
||||||
|
|
||||||
|
export const Share: React.FC<IS.CustomProps> = (props) => (
|
||||||
|
<IS.Custom
|
||||||
|
{...props}
|
||||||
|
viewBox="0 0 18 18"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M9.91684 1.66675V5.33341C3.88976 6.27575 1.64851 11.5557 0.750173 16.3334C0.716256 16.5222 5.68551 10.8682 9.91684 10.8334V14.5001L17.2502 8.08341L9.91684 1.66675Z"
|
||||||
|
stroke="white"
|
||||||
|
strokeWidth="1.41667"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
</IS.Custom>
|
||||||
|
);
|
||||||
|
|
@ -1,16 +1,19 @@
|
||||||
import { AiFillCheckCircle } from '@react-icons/all-files/ai/AiFillCheckCircle';
|
import { AiFillCheckCircle } from '@react-icons/all-files/ai/AiFillCheckCircle';
|
||||||
import { AiOutlineCheck } from '@react-icons/all-files/ai/AiOutlineCheck';
|
import { AiOutlineCheck } from '@react-icons/all-files/ai/AiOutlineCheck';
|
||||||
import { AiOutlineTwitter } from '@react-icons/all-files/ai/AiOutlineTwitter';
|
import { AiOutlineTwitter } from '@react-icons/all-files/ai/AiOutlineTwitter';
|
||||||
|
import { AiOutlineUnorderedList } from '@react-icons/all-files/ai/AiOutlineUnorderedList';
|
||||||
import { BiGitBranch } from '@react-icons/all-files/bi/BiGitBranch';
|
import { BiGitBranch } from '@react-icons/all-files/bi/BiGitBranch';
|
||||||
import { BiSearch } from '@react-icons/all-files/bi/BiSearch';
|
import { BiSearch } from '@react-icons/all-files/bi/BiSearch';
|
||||||
import { BsFillSquareFill } from '@react-icons/all-files/bs/BsFillSquareFill';
|
import { BsFillSquareFill } from '@react-icons/all-files/bs/BsFillSquareFill';
|
||||||
import { FaBars } from '@react-icons/all-files/fa/FaBars';
|
import { FaBars } from '@react-icons/all-files/fa/FaBars';
|
||||||
import { FaChevronRight } from '@react-icons/all-files/fa/FaChevronRight';
|
import { FaChevronRight } from '@react-icons/all-files/fa/FaChevronRight';
|
||||||
import { FaExternalLinkAlt } from '@react-icons/all-files/fa/FaExternalLinkAlt';
|
import { FaExternalLinkAlt } from '@react-icons/all-files/fa/FaExternalLinkAlt';
|
||||||
|
import { HiOutlineDotsHorizontal } from '@react-icons/all-files/hi/HiOutlineDotsHorizontal';
|
||||||
import { IoArrowBackCircleSharp } from '@react-icons/all-files/io5/IoArrowBackCircleSharp';
|
import { IoArrowBackCircleSharp } from '@react-icons/all-files/io5/IoArrowBackCircleSharp';
|
||||||
import { IoCheckmarkCircleSharp } from '@react-icons/all-files/io5/IoCheckmarkCircleSharp';
|
import { IoCheckmarkCircleSharp } from '@react-icons/all-files/io5/IoCheckmarkCircleSharp';
|
||||||
import { IoClose } from '@react-icons/all-files/io5/IoClose';
|
import { IoClose } from '@react-icons/all-files/io5/IoClose';
|
||||||
import { IoCloudUploadSharp } from '@react-icons/all-files/io5/IoCloudUploadSharp';
|
import { IoCloudUploadSharp } from '@react-icons/all-files/io5/IoCloudUploadSharp';
|
||||||
|
import { IoGridOutline } from '@react-icons/all-files/io5/IoGridOutline';
|
||||||
import { IoInformationCircleSharp } from '@react-icons/all-files/io5/IoInformationCircleSharp';
|
import { IoInformationCircleSharp } from '@react-icons/all-files/io5/IoInformationCircleSharp';
|
||||||
import { IoLogoGithub } from '@react-icons/all-files/io5/IoLogoGithub';
|
import { IoLogoGithub } from '@react-icons/all-files/io5/IoLogoGithub';
|
||||||
import { MdVerifiedUser } from '@react-icons/all-files/md/MdVerifiedUser';
|
import { MdVerifiedUser } from '@react-icons/all-files/md/MdVerifiedUser';
|
||||||
|
|
@ -23,7 +26,9 @@ import {
|
||||||
FleekLogo,
|
FleekLogo,
|
||||||
FleekName,
|
FleekName,
|
||||||
MetamaskIcon,
|
MetamaskIcon,
|
||||||
|
OpenseaIcon,
|
||||||
} from './custom';
|
} from './custom';
|
||||||
|
import { Share } from './custom/share-icon';
|
||||||
|
|
||||||
export const IconLibrary = Object.freeze({
|
export const IconLibrary = Object.freeze({
|
||||||
back: IoArrowBackCircleSharp,
|
back: IoArrowBackCircleSharp,
|
||||||
|
|
@ -40,13 +45,18 @@ export const IconLibrary = Object.freeze({
|
||||||
'fleek-logo': FleekLogo,
|
'fleek-logo': FleekLogo,
|
||||||
'fleek-name': FleekName,
|
'fleek-name': FleekName,
|
||||||
github: IoLogoGithub,
|
github: IoLogoGithub,
|
||||||
|
grid: IoGridOutline,
|
||||||
info: IoInformationCircleSharp,
|
info: IoInformationCircleSharp,
|
||||||
|
list: AiOutlineUnorderedList,
|
||||||
menu: FaBars,
|
menu: FaBars,
|
||||||
metamask: MetamaskIcon, //remove if not used
|
metamask: MetamaskIcon, //remove if not used
|
||||||
|
opensea: OpenseaIcon,
|
||||||
search: BiSearch,
|
search: BiSearch,
|
||||||
square: BsFillSquareFill,
|
square: BsFillSquareFill,
|
||||||
|
share: Share,
|
||||||
success: AiFillCheckCircle,
|
success: AiFillCheckCircle,
|
||||||
twitter: AiOutlineTwitter,
|
twitter: AiOutlineTwitter,
|
||||||
|
'three-dots': HiOutlineDotsHorizontal,
|
||||||
upload: IoCloudUploadSharp,
|
upload: IoCloudUploadSharp,
|
||||||
verified: MdVerifiedUser,
|
verified: MdVerifiedUser,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -7,3 +7,4 @@ export * from './separator.styles';
|
||||||
export * from './text';
|
export * from './text';
|
||||||
export * from './switch';
|
export * from './switch';
|
||||||
export * from './color-picker';
|
export * from './color-picker';
|
||||||
|
export * from './menu';
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
import { Flex } from '@/components/layout';
|
import { Flex } from '@/components/layout';
|
||||||
import { styled } from '@/theme';
|
import { styled } from '@/theme';
|
||||||
|
|
||||||
export abstract class InputFileStyles {
|
export const InputFileStyles = {
|
||||||
static readonly Container = styled(Flex, {
|
Container: styled(Flex, {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
});
|
}),
|
||||||
|
Border: styled('div', {
|
||||||
static readonly Border = styled('div', {
|
|
||||||
borderStyle: 'solid',
|
borderStyle: 'solid',
|
||||||
borderColor: '$gray7',
|
borderColor: '$gray7',
|
||||||
width: '$22',
|
width: '$22',
|
||||||
|
|
@ -24,5 +23,14 @@ export abstract class InputFileStyles {
|
||||||
'&[aria-invalid=true], &[data-invalid]': {
|
'&[aria-invalid=true], &[data-invalid]': {
|
||||||
borderColor: '$red9',
|
borderColor: '$red9',
|
||||||
},
|
},
|
||||||
});
|
}),
|
||||||
}
|
Image: styled('img', {
|
||||||
|
position: 'absolute',
|
||||||
|
width: '3.5rem',
|
||||||
|
height: '3.5rem',
|
||||||
|
}),
|
||||||
|
Input: styled('input', {
|
||||||
|
all: 'unset',
|
||||||
|
display: 'none',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -25,14 +25,13 @@ export const StyledInputFile = forwardRef<HTMLDivElement, InputFileProps>(
|
||||||
<>
|
<>
|
||||||
<S.Container onClick={handleInputClick}>
|
<S.Container onClick={handleInputClick}>
|
||||||
{file !== '' ? (
|
{file !== '' ? (
|
||||||
<img className="absolute w-14 h-14" src={file} alt="logo" />
|
<S.Image src={file} alt="logo" />
|
||||||
) : (
|
) : (
|
||||||
<Icon name="upload" size="md" css={{ position: 'absolute' }} />
|
<Icon name="upload" size="md" css={{ position: 'absolute' }} />
|
||||||
)}
|
)}
|
||||||
<S.Border {...props} ref={ref} />
|
<S.Border {...props} ref={ref} />
|
||||||
<input
|
<S.Input
|
||||||
type="file"
|
type="file"
|
||||||
className="hidden"
|
|
||||||
accept={'.svg'}
|
accept={'.svg'}
|
||||||
ref={inputFileRef}
|
ref={inputFileRef}
|
||||||
onChange={handleFileChange}
|
onChange={handleFileChange}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './menu';
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
import { Menu } from '@headlessui/react';
|
||||||
|
|
||||||
|
import { styled } from '@/theme';
|
||||||
|
|
||||||
|
export const MenuStyles = {
|
||||||
|
Wrapper: styled('div', {
|
||||||
|
position: 'relative',
|
||||||
|
}),
|
||||||
|
Items: styled(Menu.Items, {
|
||||||
|
width: '100%',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
position: 'absolute',
|
||||||
|
border: '1px solid $slate6',
|
||||||
|
backgroundColor: '$black',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
top: 'calc(100% + $3)',
|
||||||
|
padding: '$3',
|
||||||
|
gap: '$2',
|
||||||
|
borderRadius: '$lg',
|
||||||
|
zIndex: '$dropdown',
|
||||||
|
maxHeight: '30vh',
|
||||||
|
overflow: 'auto',
|
||||||
|
}),
|
||||||
|
Item: styled(Menu.Item, {
|
||||||
|
width: '100%',
|
||||||
|
position: 'relative',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: '$3',
|
||||||
|
cursor: 'pointer',
|
||||||
|
padding: '$2 $3',
|
||||||
|
borderRadius: '$lg',
|
||||||
|
color: '$slate11',
|
||||||
|
transition: '$all-200',
|
||||||
|
fontSize: '$sm',
|
||||||
|
|
||||||
|
a: {
|
||||||
|
all: 'unset',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&[data-headlessui-state*="active"]': {
|
||||||
|
backgroundColor: '$slate2',
|
||||||
|
color: '$slate12',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
import { Menu as MenuHeadless } from '@headlessui/react';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { forwardStyledRef } from '@/theme';
|
||||||
|
|
||||||
|
import { MenuStyles as MS } from './menu.styles';
|
||||||
|
|
||||||
|
export abstract class Menu {
|
||||||
|
static readonly Root = ({ children }: Menu.MenuProps): JSX.Element => {
|
||||||
|
return <MenuHeadless as={MS.Wrapper}>{children}</MenuHeadless>;
|
||||||
|
};
|
||||||
|
|
||||||
|
static readonly Items = forwardStyledRef<HTMLDivElement, Menu.ItemsProps>(
|
||||||
|
({ children, ...props }, ref): JSX.Element => {
|
||||||
|
return (
|
||||||
|
<MS.Items ref={ref} {...props}>
|
||||||
|
{children.map((child, index) => (
|
||||||
|
<MS.Item key={index}>{child}</MS.Item>
|
||||||
|
))}
|
||||||
|
</MS.Items>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
static readonly Button = MenuHeadless.Button;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace Menu {
|
||||||
|
export type ItemsProps = {
|
||||||
|
children: React.ReactNode[];
|
||||||
|
} & React.ComponentPropsWithRef<typeof MS.Items>;
|
||||||
|
|
||||||
|
export type Elements = {
|
||||||
|
Button: React.FC<React.ComponentPropsWithRef<typeof MenuHeadless.Button>>;
|
||||||
|
Items: React.FC<ItemsProps>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type MenuProps = {
|
||||||
|
children: React.ReactNode;
|
||||||
|
} & React.ComponentPropsWithRef<typeof MS.Wrapper>;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
import { Switch } from '@headlessui/react';
|
||||||
|
|
||||||
|
import { styled } from '@/theme';
|
||||||
|
|
||||||
|
export const SwitchStyles = {
|
||||||
|
Wrapper: styled(Switch, {
|
||||||
|
position: 'relative',
|
||||||
|
display: 'inline-flex',
|
||||||
|
height: '2rem',
|
||||||
|
width: '4.625rem',
|
||||||
|
flexShrink: 0,
|
||||||
|
cursor: 'pointer',
|
||||||
|
borderRadius: '$full',
|
||||||
|
borderWidth: '0.125rem',
|
||||||
|
borderColor: 'transparent',
|
||||||
|
|
||||||
|
transitionProperty: 'all',
|
||||||
|
|
||||||
|
transitionTimingFunction: 'cubic-bezier(0.4, 0, 0.2, 1)',
|
||||||
|
transitionDuration: '200ms',
|
||||||
|
|
||||||
|
'&:focus': {
|
||||||
|
outline: '0.125rem solid transparent',
|
||||||
|
outlineOffset: '0.125rem',
|
||||||
|
},
|
||||||
|
|
||||||
|
variants: {
|
||||||
|
isChecked: {
|
||||||
|
true: {
|
||||||
|
backgroundColor: '$green4',
|
||||||
|
},
|
||||||
|
false: {
|
||||||
|
backgroundColor: '$red4',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
Text: styled('span', {
|
||||||
|
position: 'absolute',
|
||||||
|
top: '25%',
|
||||||
|
fontSize: '$sm',
|
||||||
|
|
||||||
|
variants: {
|
||||||
|
checked: {
|
||||||
|
true: {
|
||||||
|
right: '0.75rem',
|
||||||
|
color: '$green11',
|
||||||
|
},
|
||||||
|
false: {
|
||||||
|
left: '1rem',
|
||||||
|
color: '$red11',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
Dot: styled('span', {
|
||||||
|
position: 'absolute',
|
||||||
|
top: '5px',
|
||||||
|
left: '5px',
|
||||||
|
pointerEvents: 'none',
|
||||||
|
display: 'inline-block',
|
||||||
|
height: '1.25rem',
|
||||||
|
width: '1.25rem',
|
||||||
|
borderRadius: '$full',
|
||||||
|
|
||||||
|
transitionProperty: 'all',
|
||||||
|
|
||||||
|
transitionTimingFunction: 'cubic-bezier(0.4, 0, 0.2, 1)',
|
||||||
|
transitionDuration: '200ms',
|
||||||
|
|
||||||
|
variants: {
|
||||||
|
checked: {
|
||||||
|
true: {
|
||||||
|
backgroundColor: '$green11',
|
||||||
|
transform: 'translateX(0px)',
|
||||||
|
},
|
||||||
|
false: {
|
||||||
|
backgroundColor: '$red11',
|
||||||
|
transform: 'translateX(2.625rem)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
@ -1,31 +1,21 @@
|
||||||
import { Switch as SwitchComponent } from '@headlessui/react';
|
import { Switch as SwitchHeadless } from '@headlessui/react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
import { SwitchStyles as S } from './switch.styles';
|
||||||
|
|
||||||
type SwitchProps = {
|
type SwitchProps = {
|
||||||
checked: boolean;
|
checked: boolean;
|
||||||
onChange: (checked: boolean) => void;
|
onChange: (checked: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Switch: React.FC<SwitchProps> = ({ checked, onChange }) => (
|
export const Switch: React.FC<SwitchProps> = ({ checked, onChange }) => (
|
||||||
<SwitchComponent
|
<SwitchHeadless
|
||||||
|
as={S.Wrapper}
|
||||||
checked={checked}
|
checked={checked}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
className={`${checked ? 'bg-green4' : 'bg-red4'}
|
isChecked={checked}
|
||||||
relative inline-flex h-[32px] w-[74px] shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75`}
|
|
||||||
>
|
>
|
||||||
<span
|
<S.Text checked={checked}>{checked ? 'Yes' : 'No'}</S.Text>
|
||||||
className={`absolute top-1 ${
|
<S.Dot checked={checked} />
|
||||||
checked ? 'right-3 text-green11' : 'text-red11 left-4'
|
</SwitchHeadless>
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{checked ? 'Yes' : 'No'}
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
aria-hidden="true"
|
|
||||||
className={`${
|
|
||||||
checked ? 'bg-green11 translate-x-0' : 'bg-red11 translate-x-[2.625rem]'
|
|
||||||
}
|
|
||||||
absolute top-1 left-1 pointer-events-none inline-block h-[20px] w-[20px] transform rounded-full shadow-lg ring-0 transition duration-200 ease-in-out`}
|
|
||||||
/>
|
|
||||||
</SwitchComponent>
|
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ export * from './spinner';
|
||||||
export * from './toast';
|
export * from './toast';
|
||||||
export * from './step';
|
export * from './step';
|
||||||
export * from './nfa-card';
|
export * from './nfa-card';
|
||||||
|
export * from './nfa-icon';
|
||||||
export * from './nfa-preview';
|
export * from './nfa-preview';
|
||||||
export * from './card-tag';
|
export * from './card-tag';
|
||||||
export * from './resolved-address';
|
export * from './resolved-address';
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ export const NavBarStyles = {
|
||||||
content: '""',
|
content: '""',
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
inset: 0,
|
inset: 0,
|
||||||
backgroundColor: alphaColor('black', 0.8),
|
|
||||||
backdropFilter: 'blur(4px)',
|
backdropFilter: 'blur(4px)',
|
||||||
zIndex: -1,
|
zIndex: -1,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { useMediaQuery } from '@/hooks';
|
import { useMediaQuery } from '@/hooks';
|
||||||
|
|
||||||
import { ConnectWalletButton } from './connect-wallet-button';
|
|
||||||
import { Logo } from './logo';
|
import { Logo } from './logo';
|
||||||
import { NavBarStyles as Styles } from './nav-bar.styles';
|
import { NavBarStyles as Styles } from './nav-bar.styles';
|
||||||
|
import { NavBarConnectWalletButton } from './navbar-connect-wallet-button';
|
||||||
import { Navigation } from './navigation';
|
import { Navigation } from './navigation';
|
||||||
import { Sidebar } from './sidebar';
|
import { Sidebar } from './sidebar';
|
||||||
|
|
||||||
|
|
@ -13,7 +13,7 @@ export const NavBar: React.FC = () => {
|
||||||
<Styles.Container>
|
<Styles.Container>
|
||||||
<Styles.Content>
|
<Styles.Content>
|
||||||
<Logo />
|
<Logo />
|
||||||
<ConnectWalletButton />
|
<NavBarConnectWalletButton />
|
||||||
{enableSidebar ? <Sidebar /> : <Navigation />}
|
{enableSidebar ? <Sidebar /> : <Navigation />}
|
||||||
</Styles.Content>
|
</Styles.Content>
|
||||||
</Styles.Container>
|
</Styles.Container>
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,24 @@
|
||||||
import { Avatar, ConnectKitButton } from 'connectkit';
|
import { Avatar, ConnectKitButton } from 'connectkit';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import { useAccount, useEnsName } from 'wagmi';
|
||||||
|
|
||||||
import { Button, Flex } from '@/components';
|
import { Button, Flex } from '@/components';
|
||||||
import { ENSActions, useAppDispatch, useENSStore } from '@/store';
|
import { ENSActions, useAppDispatch, useENSStore } from '@/store';
|
||||||
|
|
||||||
export const ConnectWalletButton: React.FC = () => {
|
export const NavBarConnectWalletButton: React.FC = () => {
|
||||||
const { addressMap } = useENSStore();
|
const { addressMap } = useENSStore();
|
||||||
|
const { address } = useAccount();
|
||||||
|
const { data: ensName } = useEnsName({
|
||||||
|
address,
|
||||||
|
});
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
const setEnsNameStore = (ensName: string, address: string): void => {
|
useEffect(() => {
|
||||||
|
if (address === undefined) return;
|
||||||
|
|
||||||
const stored = addressMap[address] || {};
|
const stored = addressMap[address] || {};
|
||||||
if (typeof stored.state !== 'undefined') return;
|
if (typeof stored.state !== 'undefined') return;
|
||||||
|
if (ensName === null) return;
|
||||||
|
|
||||||
dispatch(
|
dispatch(
|
||||||
ENSActions.setAddress({
|
ENSActions.setAddress({
|
||||||
|
|
@ -17,13 +26,11 @@ export const ConnectWalletButton: React.FC = () => {
|
||||||
value: { state: 'success', value: ensName },
|
value: { state: 'success', value: ensName },
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
}, [address, addressMap, dispatch, ensName]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConnectKitButton.Custom>
|
<ConnectKitButton.Custom>
|
||||||
{({ isConnected, show, truncatedAddress, address, ensName }) => {
|
{({ isConnected, show, truncatedAddress, address, ensName }) => {
|
||||||
if (ensName && address) setEnsNameStore(ensName, address);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button onClick={show} css={{ gridArea: 'wallet' }}>
|
<Button onClick={show} css={{ gridArea: 'wallet' }}>
|
||||||
{isConnected && !!address && !!truncatedAddress ? (
|
{isConnected && !!address && !!truncatedAddress ? (
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { App } from '@/app.context';
|
||||||
import { NavBar } from '@/components';
|
import { NavBar } from '@/components';
|
||||||
|
|
||||||
import { PageStyles as PS } from './page.styles';
|
import { PageStyles as PS } from './page.styles';
|
||||||
|
|
@ -7,8 +8,15 @@ export type AppPageProps = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AppPage: React.FC<AppPageProps> = ({ children }: AppPageProps) => {
|
export const AppPage: React.FC<AppPageProps> = ({ children }: AppPageProps) => {
|
||||||
|
const { backgroundColor } = App.useContext();
|
||||||
|
const background = `linear-gradient(180deg, #${backgroundColor}59 0%, #000000 30%)`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PS.Container>
|
<PS.Container
|
||||||
|
css={{
|
||||||
|
background: background,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<NavBar />
|
<NavBar />
|
||||||
<PS.Content as="main">{children}</PS.Content>
|
<PS.Content as="main">{children}</PS.Content>
|
||||||
</PS.Container>
|
</PS.Container>
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { Skeleton } from '../layout';
|
||||||
|
|
||||||
export const NFACardStyles = {
|
export const NFACardStyles = {
|
||||||
Container: styled(Link, {
|
Container: styled(Link, {
|
||||||
|
all: 'unset',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
minWidth: '12.5rem',
|
minWidth: '12.5rem',
|
||||||
|
|
|
||||||
|
|
@ -61,8 +61,7 @@ export const NFACard: React.FC<NFACardProps> = forwardStyledRef<
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<S.Title title={data.name}>{data.name}</S.Title>
|
<S.Title title={data.name}>{data.name}</S.Title>
|
||||||
{/* TODO: set correct value when it gets available on contract side */}
|
<Badge verified={data.verified} />
|
||||||
<Badge verified={Math.random() > 0.5} />
|
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<Flex css={{ gap: '$1' }}>
|
<Flex css={{ gap: '$1' }}>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { NFAIconStyles as NS } from './nfa-icon.styles';
|
||||||
|
|
||||||
|
type NFAIconProps = {
|
||||||
|
image: string;
|
||||||
|
color: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const NFAIcon: React.FC<NFAIconProps> = ({
|
||||||
|
image,
|
||||||
|
color,
|
||||||
|
}: NFAIconProps) => {
|
||||||
|
return (
|
||||||
|
<NS.Container css={{ backgroundColor: color }}>
|
||||||
|
<NS.Image
|
||||||
|
src={image}
|
||||||
|
onErrorCapture={(event) => (event.currentTarget.style.display = 'none')}
|
||||||
|
/>
|
||||||
|
</NS.Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Flex } from '@/components';
|
import { Flex, Text } from '@/components';
|
||||||
import { styled } from '@/theme';
|
import { styled } from '@/theme';
|
||||||
|
|
||||||
export const StepStyles = {
|
export const StepStyles = {
|
||||||
|
|
@ -23,4 +23,7 @@ export const StepStyles = {
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
maxWidth: '$106',
|
maxWidth: '$106',
|
||||||
}),
|
}),
|
||||||
|
Text: styled(Text, {
|
||||||
|
fontSize: '$4xl',
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ export const Step: React.FC<StepProps> = ({ children, header }: StepProps) => {
|
||||||
<S.Container>
|
<S.Container>
|
||||||
<S.Indicator>
|
<S.Indicator>
|
||||||
<Stepper.Indicator />
|
<Stepper.Indicator />
|
||||||
<h2 className="text-4xl">{header}</h2>
|
<S.Text>{header}</S.Text>
|
||||||
</S.Indicator>
|
</S.Indicator>
|
||||||
{children}
|
{children}
|
||||||
</S.Container>
|
</S.Container>
|
||||||
|
|
|
||||||
|
|
@ -4,26 +4,26 @@ import { keyframes, styled } from '@/theme';
|
||||||
|
|
||||||
import { Icon, IconButton } from '../core';
|
import { Icon, IconButton } from '../core';
|
||||||
import { Flex } from '../layout';
|
import { Flex } from '../layout';
|
||||||
|
import { IconStyles } from '../core/icon/icon.styles';
|
||||||
|
|
||||||
export abstract class ToastStyles {
|
const KeyFrames = {
|
||||||
static readonly Provider = ToastLib.Provider;
|
hide: keyframes({
|
||||||
|
'0%': { opacity: 1 },
|
||||||
|
'100%': { opacity: 0 },
|
||||||
|
}),
|
||||||
|
show: keyframes({
|
||||||
|
'0%': { opacity: 0 },
|
||||||
|
'100%': { opacity: 1 },
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
static readonly DismissTimeout = 200;
|
export const ViewportPadding = '$md';
|
||||||
|
export const DismissTimeout = 200;
|
||||||
|
|
||||||
static readonly ViewportPadding = '$md';
|
export const ToastStyles = {
|
||||||
|
Provider: ToastLib.Provider,
|
||||||
|
|
||||||
static readonly KeyFrames = {
|
Root: styled(ToastLib.Root, {
|
||||||
hide: keyframes({
|
|
||||||
'0%': { opacity: 1 },
|
|
||||||
'100%': { opacity: 0 },
|
|
||||||
}),
|
|
||||||
show: keyframes({
|
|
||||||
'0%': { opacity: 0 },
|
|
||||||
'100%': { opacity: 1 },
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
static readonly Root = styled(ToastLib.Root, {
|
|
||||||
padding: '$4 $5',
|
padding: '$4 $5',
|
||||||
borderRadius: '$lg',
|
borderRadius: '$lg',
|
||||||
borderWidth: '$default',
|
borderWidth: '$default',
|
||||||
|
|
@ -46,23 +46,20 @@ export abstract class ToastStyles {
|
||||||
|
|
||||||
'@media (prefers-reduced-motion: no-preference)': {
|
'@media (prefers-reduced-motion: no-preference)': {
|
||||||
'&[data-state="open"]': {
|
'&[data-state="open"]': {
|
||||||
animation: `${this.KeyFrames.show} 750ms `,
|
animation: `${KeyFrames.show} 750ms `,
|
||||||
},
|
},
|
||||||
'&[data-state="closed"]': {
|
'&[data-state="closed"]': {
|
||||||
animation: `${this.KeyFrames.hide} ${this.DismissTimeout}ms ease-in`,
|
animation: `${KeyFrames.hide} ${DismissTimeout}ms ease-in`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
}),
|
||||||
|
Body: styled(ToastLib.Description, {
|
||||||
static readonly Body = styled(ToastLib.Description, {
|
|
||||||
fontSize: '$md',
|
fontSize: '$md',
|
||||||
fontWeight: '$normal',
|
fontWeight: '$normal',
|
||||||
mr: '$5',
|
mr: '$5',
|
||||||
});
|
}),
|
||||||
|
Close: ToastLib.Close,
|
||||||
static readonly Close = styled(ToastLib.Close, {});
|
CloseButton: styled(IconButton, {
|
||||||
|
|
||||||
static readonly CloseButton = styled(IconButton, {
|
|
||||||
variants: {
|
variants: {
|
||||||
colorScheme: {
|
colorScheme: {
|
||||||
error: {
|
error: {
|
||||||
|
|
@ -73,11 +70,10 @@ export abstract class ToastStyles {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
}),
|
||||||
|
Viewport: styled(ToastLib.Viewport, {
|
||||||
static readonly Viewport = styled(ToastLib.Viewport, {
|
py: '$14',
|
||||||
padding: '$14',
|
listStyleType: 'none',
|
||||||
|
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
left: '50%',
|
left: '50%',
|
||||||
|
|
@ -86,17 +82,16 @@ export abstract class ToastStyles {
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
gap: '$4',
|
gap: '$4',
|
||||||
zIndex: '$toast',
|
zIndex: '$toast',
|
||||||
});
|
minWidth: '250px',
|
||||||
|
}),
|
||||||
static readonly Layout = styled(Flex, {
|
Layout: styled(Flex, {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
});
|
alignItems: 'center',
|
||||||
|
}),
|
||||||
static readonly Icon = styled(Icon, {
|
Icon: styled(Icon, {
|
||||||
fontSize: '$5',
|
fontSize: '1.25rem',
|
||||||
marginRight: '$2h',
|
marginRight: '$2h',
|
||||||
});
|
}),
|
||||||
|
Content: styled(Flex),
|
||||||
static readonly Content = styled(Flex, {});
|
};
|
||||||
}
|
|
||||||
|
|
@ -8,7 +8,7 @@ import {
|
||||||
} from '@/store';
|
} from '@/store';
|
||||||
|
|
||||||
import { Icon } from '../core';
|
import { Icon } from '../core';
|
||||||
import { ToastStyles } from './toast.styles';
|
import { DismissTimeout, ToastStyles } from './toast.styles';
|
||||||
|
|
||||||
type ToastProps = ToastsState.Toast;
|
type ToastProps = ToastsState.Toast;
|
||||||
|
|
||||||
|
|
@ -29,7 +29,7 @@ const Toast: React.FC<ToastProps> = ({
|
||||||
if (onDismiss) onDismiss();
|
if (onDismiss) onDismiss();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
dispatch(toastsActions.dismiss(id));
|
dispatch(toastsActions.dismiss(id));
|
||||||
}, ToastStyles.DismissTimeout);
|
}, DismissTimeout);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[onDismiss, dispatch, id]
|
[onDismiss, dispatch, id]
|
||||||
|
|
@ -54,6 +54,7 @@ const Toast: React.FC<ToastProps> = ({
|
||||||
variant="link"
|
variant="link"
|
||||||
icon={<Icon name="close" />}
|
icon={<Icon name="close" />}
|
||||||
onClick={onDismiss}
|
onClick={onDismiss}
|
||||||
|
css={{ p: '0' }}
|
||||||
/>
|
/>
|
||||||
</ToastStyles.Close>
|
</ToastStyles.Close>
|
||||||
</ToastStyles.Layout>
|
</ToastStyles.Layout>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
export const env = Object.freeze({
|
export const env = Object.freeze({
|
||||||
|
environment: import.meta.env.MODE,
|
||||||
alchemy: {
|
alchemy: {
|
||||||
id: import.meta.env.VITE_ALCHEMY_API_KEY || '',
|
id: import.meta.env.VITE_ALCHEMY_API_KEY || '',
|
||||||
appName: import.meta.env.VITE_ALCHEMY_APP_NAME || '',
|
appName: import.meta.env.VITE_ALCHEMY_APP_NAME || '',
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import './styles.css';
|
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,10 @@ const client = new ApolloClient({
|
||||||
keyArgs: ['where', 'orderBy', 'orderDirection'],
|
keyArgs: ['where', 'orderBy', 'orderDirection'],
|
||||||
merge: mergeByKey('id'),
|
merge: mergeByKey('id'),
|
||||||
},
|
},
|
||||||
|
accessPoints: {
|
||||||
|
keyArgs: ['where', 'orderBy', 'orderDirection'],
|
||||||
|
merge: mergeByKey('id'),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
//TODO: maybe we can use tailwind for this
|
|
||||||
export const shadows = {
|
export const shadows = {
|
||||||
none: '0 0 #0000',
|
none: '0 0 #0000',
|
||||||
inner: 'inset 0 2px 4px 0 rgb(0 0 0 / 0.05)',
|
inner: 'inset 0 2px 4px 0 rgb(0 0 0 / 0.05)',
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,25 @@
|
||||||
import { globalCss } from '@stitches/react';
|
import { globalCss } from '@stitches/react';
|
||||||
|
|
||||||
export const themeGlobals = globalCss({
|
export const themeGlobals = globalCss({
|
||||||
'html, body, #root': {
|
'html, body': {
|
||||||
height: '100%',
|
height: '100%',
|
||||||
padding: 0,
|
|
||||||
|
//TODO add theme colors
|
||||||
color: '#ECEDEE',
|
color: '#ECEDEE',
|
||||||
backgroundColor: 'black',
|
backgroundColor: 'black',
|
||||||
|
|
||||||
fontFamily: 'Manrope',
|
fontFamily: 'Manrope',
|
||||||
|
|
||||||
fontSize: '16px',
|
fontSize: '16px',
|
||||||
|
|
||||||
'@media (max-width: 850px)': {
|
'@media (max-width: 850px)': {
|
||||||
fontSize: '13px',
|
fontSize: '13px',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'*': {
|
||||||
|
margin: '0',
|
||||||
|
padding: '0',
|
||||||
|
border: '0',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ const createDripStitches = <
|
||||||
};
|
};
|
||||||
|
|
||||||
const { createTheme, ...otherStitches } = createStitches({
|
const { createTheme, ...otherStitches } = createStitches({
|
||||||
prefix: prefix || ('drip' as string),
|
prefix: prefix || ('nfa' as string),
|
||||||
media: {
|
media: {
|
||||||
...libMedia,
|
...libMedia,
|
||||||
...(media || {}),
|
...(media || {}),
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,9 @@ export const contractAddress = (address: string): string => {
|
||||||
|
|
||||||
export const getRepositoryFromURL = (url: string): string => {
|
export const getRepositoryFromURL = (url: string): string => {
|
||||||
const urlSplitted = url.split('/');
|
const urlSplitted = url.split('/');
|
||||||
return `${urlSplitted[3]}/${urlSplitted[4]}`;
|
return urlSplitted[3] && urlSplitted[4]
|
||||||
|
? `${urlSplitted[3]}/${urlSplitted[4]}`
|
||||||
|
: '';
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getDate = (date: number): string => {
|
export const getDate = (date: number): string => {
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import {
|
||||||
CardTag,
|
CardTag,
|
||||||
Flex,
|
Flex,
|
||||||
Form,
|
Form,
|
||||||
|
NFAIcon,
|
||||||
RowData,
|
RowData,
|
||||||
Spinner,
|
Spinner,
|
||||||
Stepper,
|
Stepper,
|
||||||
|
|
@ -18,17 +19,22 @@ import { getNFADocument } from '@/graphclient';
|
||||||
import { useAppDispatch } from '@/store';
|
import { useAppDispatch } from '@/store';
|
||||||
import { bunnyCDNActions, useBunnyCDNStore } from '@/store/features/bunny-cdn';
|
import { bunnyCDNActions, useBunnyCDNStore } from '@/store/features/bunny-cdn';
|
||||||
import { AppLog } from '@/utils';
|
import { AppLog } from '@/utils';
|
||||||
|
import { parseNumberToHexColor } from '@/utils/color';
|
||||||
|
|
||||||
import { CreateAccessPoint } from '../create-ap.context';
|
import { CreateAccessPoint } from '../create-ap.context';
|
||||||
import { NFAIconFragment } from '../nfa-icon';
|
|
||||||
import { useAccessPointFormContext } from './create-ap.form.context';
|
import { useAccessPointFormContext } from './create-ap.form.context';
|
||||||
|
|
||||||
export const SelectedNFA: React.FC = () => {
|
export const SelectedNFA: React.FC = () => {
|
||||||
const { nfa } = CreateAccessPoint.useContext();
|
const { nfa } = CreateAccessPoint.useContext();
|
||||||
|
if (!nfa.logo) return null;
|
||||||
return (
|
return (
|
||||||
<RowData
|
<RowData
|
||||||
leftIcon={<NFAIconFragment image={nfa.logo} color={nfa.color} />}
|
leftIcon={
|
||||||
|
<NFAIcon
|
||||||
|
image={nfa.logo}
|
||||||
|
color={`#${parseNumberToHexColor(nfa.color)}57`}
|
||||||
|
/>
|
||||||
|
}
|
||||||
label={nfa.name}
|
label={nfa.name}
|
||||||
rightComponent={<CardTag css={{ minWidth: '$28' }}>Selected NFA</CardTag>}
|
rightComponent={<CardTag css={{ minWidth: '$28' }}>Selected NFA</CardTag>}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { Flex } from '@/components';
|
||||||
|
import { styled } from '@/theme';
|
||||||
|
|
||||||
|
export const CreateApStyles = {
|
||||||
|
Container: styled(Flex, {
|
||||||
|
height: '100%',
|
||||||
|
flexDirection: 'column',
|
||||||
|
minHeight: '85vh',
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
|
||||||
|
'@md': {
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
@ -1,28 +1,20 @@
|
||||||
import { Flex } from '@/components';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CreateAccessPointFormProvider,
|
CreateAccessPointFormProvider,
|
||||||
useAccessPointFormContextInit,
|
useAccessPointFormContextInit,
|
||||||
} from './ap-form-step/create-ap.form.context';
|
} from './ap-form-step/create-ap.form.context';
|
||||||
import { CreateAccessPoint } from './create-ap.context';
|
import { CreateAccessPoint } from './create-ap.context';
|
||||||
import { CreateApStepper } from './create-ap.stepper';
|
import { CreateApStepper } from './create-ap.stepper';
|
||||||
|
import { CreateApStyles as S } from './create-ap.styles';
|
||||||
|
|
||||||
export const CreateAP: React.FC = () => {
|
export const CreateAP: React.FC = () => {
|
||||||
const context = useAccessPointFormContextInit();
|
const context = useAccessPointFormContextInit();
|
||||||
return (
|
return (
|
||||||
<Flex
|
<S.Container>
|
||||||
css={{
|
|
||||||
height: '100%',
|
|
||||||
flexDirection: 'column',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CreateAccessPoint.Provider>
|
<CreateAccessPoint.Provider>
|
||||||
<CreateAccessPointFormProvider value={context}>
|
<CreateAccessPointFormProvider value={context}>
|
||||||
<CreateApStepper />
|
<CreateApStepper />
|
||||||
</CreateAccessPointFormProvider>
|
</CreateAccessPointFormProvider>
|
||||||
</CreateAccessPoint.Provider>
|
</CreateAccessPoint.Provider>
|
||||||
</Flex>
|
</S.Container>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
import { parseNumberToHexColor } from '@/utils/color';
|
|
||||||
|
|
||||||
import { NFAIconStyles as NS } from './nfa-icon.styles';
|
|
||||||
|
|
||||||
type NFAIconProps = {
|
|
||||||
image: string;
|
|
||||||
color: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const NFAIconFragment: React.FC<NFAIconProps> = ({
|
|
||||||
image,
|
|
||||||
color,
|
|
||||||
}: NFAIconProps) => {
|
|
||||||
return (
|
|
||||||
<NS.Container
|
|
||||||
css={{ backgroundColor: `#${parseNumberToHexColor(color)}57` }}
|
|
||||||
>
|
|
||||||
<NS.Image src={image} />
|
|
||||||
</NS.Container>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
import { Flex, ResolvedAddress } from '@/components';
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
import { Flex, ResolvedAddress, Switch } from '@/components';
|
||||||
|
|
||||||
import { ColorPickerTest } from './color-picker';
|
import { ColorPickerTest } from './color-picker';
|
||||||
import { ComboboxTest } from './combobox-test';
|
import { ComboboxTest } from './combobox-test';
|
||||||
|
|
@ -6,9 +8,11 @@ import { SpinnerTest } from './spinner-test';
|
||||||
import { ToastTest } from './toast-test';
|
import { ToastTest } from './toast-test';
|
||||||
|
|
||||||
export const ComponentsTest: React.FC = () => {
|
export const ComponentsTest: React.FC = () => {
|
||||||
|
const [checked, setChecked] = useState(false);
|
||||||
return (
|
return (
|
||||||
<Flex css={{ flexDirection: 'column' }}>
|
<Flex css={{ flexDirection: 'column' }}>
|
||||||
<SpinnerTest />
|
<SpinnerTest />
|
||||||
|
<Switch checked={checked} onChange={setChecked} />
|
||||||
<ResolvedAddress css={{ alignSelf: 'center' }}>
|
<ResolvedAddress css={{ alignSelf: 'center' }}>
|
||||||
{'0x7ed735b7095c05d78df169f991f2b7f1a1f1a049a'}
|
{'0x7ed735b7095c05d78df169f991f2b7f1a1f1a049a'}
|
||||||
</ResolvedAddress>
|
</ResolvedAddress>
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ export abstract class ExploreHeaderStyles {
|
||||||
static readonly Text = styled('h2', {
|
static readonly Text = styled('h2', {
|
||||||
fontSize: '$4xl',
|
fontSize: '$4xl',
|
||||||
maxWidth: '46rem',
|
maxWidth: '46rem',
|
||||||
|
fontWeight: 400,
|
||||||
});
|
});
|
||||||
|
|
||||||
static readonly GrayText = styled('span', {
|
static readonly GrayText = styled('span', {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import { Explore } from '../explore.context';
|
import { Explore } from '../explore.context';
|
||||||
import { NFAListFragment } from './nfa-list.fragment';
|
import { NFAsContainerFragment } from './nfa-list';
|
||||||
import { NFASearchFragment } from './nfa-search.fragment';
|
import { NFASearchFragment } from './nfa-search.fragment';
|
||||||
|
|
||||||
export const ExploreListFragment: React.FC = () => {
|
export const ExploreListFragment: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<Explore.Provider>
|
<Explore.Provider>
|
||||||
<NFASearchFragment />
|
<NFASearchFragment />
|
||||||
<NFAListFragment />
|
<NFAsContainerFragment />
|
||||||
</Explore.Provider>
|
</Explore.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
import { styled } from '@/theme';
|
|
||||||
|
|
||||||
export const NFAListFragmentStyles = {
|
|
||||||
Container: styled('div', {
|
|
||||||
display: 'grid',
|
|
||||||
gridTemplateColumns: 'repeat(auto-fill, minmax(12.5rem, 1fr))',
|
|
||||||
alignItems: 'flex-start',
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
gap: '$6',
|
|
||||||
my: '$6',
|
|
||||||
minHeight: '50vh',
|
|
||||||
marginBottom: '30vh', // TODO: remove this if we add page footer
|
|
||||||
|
|
||||||
'@media (min-width: 1080px)': {
|
|
||||||
gridTemplateColumns: 'repeat(auto-fill, minmax(15rem, 1fr))',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
EmptyMessage: styled('span', {
|
|
||||||
padding: '$2 $3 $4 $3',
|
|
||||||
textAlign: 'center',
|
|
||||||
color: '$slate11',
|
|
||||||
width: '100%',
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './nfas-container.fragment';
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { NFACard, NFACardSkeleton } from '@/components';
|
||||||
|
import { lastNFAsPaginatedQuery } from '@/graphclient';
|
||||||
|
|
||||||
|
import { NFAListFragmentStyles as S } from './nfa-list.styles';
|
||||||
|
|
||||||
|
const LoadingSkeletons: React.FC = () => (
|
||||||
|
<>
|
||||||
|
<NFACardSkeleton />
|
||||||
|
<NFACardSkeleton />
|
||||||
|
<NFACardSkeleton />
|
||||||
|
<NFACardSkeleton />
|
||||||
|
<NFACardSkeleton />
|
||||||
|
<NFACardSkeleton />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
type NFAGridFragmentProps = {
|
||||||
|
tokens: Array<lastNFAsPaginatedQuery['tokens'][0]>;
|
||||||
|
isLoading: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const NFAGridFragment: React.FC<NFAGridFragmentProps> = ({
|
||||||
|
tokens,
|
||||||
|
isLoading,
|
||||||
|
}: NFAGridFragmentProps) => (
|
||||||
|
<S.Container>
|
||||||
|
{tokens.map((token) => (
|
||||||
|
<NFACard data={token} key={token.id} />
|
||||||
|
))}
|
||||||
|
|
||||||
|
{isLoading && <LoadingSkeletons />}
|
||||||
|
|
||||||
|
{!isLoading && tokens.length === 0 && (
|
||||||
|
<S.EmptyMessage>Nothing found.</S.EmptyMessage>
|
||||||
|
)}
|
||||||
|
</S.Container>
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
import { Text } from '@/components';
|
||||||
|
import { lastNFAsPaginatedQuery } from '@/graphclient';
|
||||||
|
|
||||||
|
import { NFAListFragmentStyles as S } from './nfa-list.styles';
|
||||||
|
import { NFARow } from './nfa-row.fragment';
|
||||||
|
import { NFARowSkeletonFragment } from './nfa-row.skeleton';
|
||||||
|
|
||||||
|
const LoadingListSkeleton: React.FC = () => (
|
||||||
|
<>
|
||||||
|
<NFARowSkeletonFragment />
|
||||||
|
<NFARowSkeletonFragment />
|
||||||
|
<NFARowSkeletonFragment />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
type NFAListFragmentProps = {
|
||||||
|
tokens: Array<lastNFAsPaginatedQuery['tokens'][0]>;
|
||||||
|
isLoading: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const NFAListFragment: React.FC<NFAListFragmentProps> = ({
|
||||||
|
tokens,
|
||||||
|
isLoading,
|
||||||
|
}: NFAListFragmentProps) => {
|
||||||
|
return (
|
||||||
|
<S.Table.Container>
|
||||||
|
<S.Table.Root>
|
||||||
|
<S.Table.Head>
|
||||||
|
<S.Table.Row>
|
||||||
|
<S.Table.Data>NAME</S.Table.Data>
|
||||||
|
<S.Table.Data># HOSTED</S.Table.Data>
|
||||||
|
<S.Table.Data>Owner</S.Table.Data>
|
||||||
|
</S.Table.Row>
|
||||||
|
</S.Table.Head>
|
||||||
|
<S.Table.Body>
|
||||||
|
{tokens.map((token) => (
|
||||||
|
<NFARow token={token} key={token.id} />
|
||||||
|
))}
|
||||||
|
|
||||||
|
{isLoading && <LoadingListSkeleton />}
|
||||||
|
|
||||||
|
{!isLoading && tokens.length === 0 && (
|
||||||
|
<S.Table.Row>
|
||||||
|
<S.Table.Data align="center" colSpan={5}>
|
||||||
|
<Text>No results</Text>
|
||||||
|
</S.Table.Data>
|
||||||
|
</S.Table.Row>
|
||||||
|
)}
|
||||||
|
</S.Table.Body>
|
||||||
|
</S.Table.Root>
|
||||||
|
</S.Table.Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
import { Skeleton } from '@/components';
|
||||||
|
import { styled } from '@/theme';
|
||||||
|
|
||||||
|
export const NFAListFragmentStyles = {
|
||||||
|
Container: styled('div', {
|
||||||
|
display: 'grid',
|
||||||
|
gridTemplateColumns: 'repeat(auto-fill, minmax(12.5rem, 1fr))',
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
gap: '$6',
|
||||||
|
my: '$6',
|
||||||
|
minHeight: '50vh',
|
||||||
|
marginBottom: '30vh', // TODO: remove this if we add page footer
|
||||||
|
|
||||||
|
'@media (min-width: 1080px)': {
|
||||||
|
gridTemplateColumns: 'repeat(auto-fill, minmax(15rem, 1fr))',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
EmptyMessage: styled('span', {
|
||||||
|
padding: '$2 $3 $4 $3',
|
||||||
|
textAlign: 'center',
|
||||||
|
color: '$slate11',
|
||||||
|
width: '100%',
|
||||||
|
}),
|
||||||
|
Table: {
|
||||||
|
Container: styled('div', {
|
||||||
|
marginTop: '$6',
|
||||||
|
padding: '0 $5',
|
||||||
|
|
||||||
|
// maxHeight: '15.125rem',
|
||||||
|
overflow: 'auto',
|
||||||
|
}),
|
||||||
|
Root: styled('table', {
|
||||||
|
width: 'calc(100% + 2 * $space$5)',
|
||||||
|
margin: '0 -$5',
|
||||||
|
}),
|
||||||
|
Head: styled('thead', {
|
||||||
|
position: 'sticky',
|
||||||
|
top: 0,
|
||||||
|
backgroundColor: '$black',
|
||||||
|
|
||||||
|
'&:after': {
|
||||||
|
position: 'absolute',
|
||||||
|
content: '""',
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
borderBottom: '1px solid $slate6',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
Row: styled('tr'),
|
||||||
|
Data: styled('td', {
|
||||||
|
padding: '$3',
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
}),
|
||||||
|
Body: styled('tbody', {
|
||||||
|
tr: {
|
||||||
|
height: '3rem',
|
||||||
|
'&:hover': {
|
||||||
|
cursor: 'pointer',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
|
||||||
|
Skeleton: styled(Skeleton, {
|
||||||
|
borderRadius: '$lg',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { Flex, NFAPreview, ResolvedAddress } from '@/components';
|
||||||
|
import { lastNFAsPaginatedQuery } from '@/graphclient';
|
||||||
|
import { parseNumberToHexColor } from '@/utils/color';
|
||||||
|
|
||||||
|
import { NFAListFragmentStyles as S } from './nfa-list.styles';
|
||||||
|
|
||||||
|
type NFARowProps = {
|
||||||
|
token: lastNFAsPaginatedQuery['tokens'][0];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const NFARow: React.FC<NFARowProps> = ({ token }: NFARowProps) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const handleClick = (): void => {
|
||||||
|
navigate(`/nfa/${token.tokenId}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<S.Table.Row onClick={handleClick}>
|
||||||
|
<S.Table.Data>
|
||||||
|
<Flex
|
||||||
|
css={{
|
||||||
|
flexDirection: 'row',
|
||||||
|
gap: '$2',
|
||||||
|
alignItems: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<NFAPreview
|
||||||
|
css={{
|
||||||
|
borderRadius: '$lg',
|
||||||
|
border: `1px solid #${parseNumberToHexColor(token.color)}`,
|
||||||
|
}}
|
||||||
|
size="4rem"
|
||||||
|
name={token.name}
|
||||||
|
color={`#${parseNumberToHexColor(token.color)}`}
|
||||||
|
logo={token.logo}
|
||||||
|
ens={token.ENS}
|
||||||
|
/>
|
||||||
|
{token.name}
|
||||||
|
</Flex>
|
||||||
|
</S.Table.Data>
|
||||||
|
<S.Table.Data css={{ textAlign: 'center' }}>
|
||||||
|
{token.accessPoints?.length ?? 0}
|
||||||
|
</S.Table.Data>
|
||||||
|
<S.Table.Data>
|
||||||
|
{/* TODO add menu button once the component it's added */}
|
||||||
|
<ResolvedAddress>{token.owner.id}</ResolvedAddress>
|
||||||
|
</S.Table.Data>
|
||||||
|
</S.Table.Row>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { Flex } from '@/components';
|
||||||
|
|
||||||
|
import { NFAListFragmentStyles as S } from './nfa-list.styles';
|
||||||
|
|
||||||
|
export const NFARowSkeletonFragment: React.FC = () => (
|
||||||
|
<S.Table.Row>
|
||||||
|
<S.Table.Data>
|
||||||
|
<Flex
|
||||||
|
css={{
|
||||||
|
flexDirection: 'row',
|
||||||
|
gap: '$3',
|
||||||
|
alignItems: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<S.Skeleton css={{ aspectRatio: 1, width: '5rem' }} />
|
||||||
|
<S.Skeleton css={{ height: '2rem', width: '100%' }} />
|
||||||
|
</Flex>
|
||||||
|
</S.Table.Data>
|
||||||
|
<S.Table.Data>
|
||||||
|
<S.Skeleton css={{ height: '2rem' }} />
|
||||||
|
</S.Table.Data>
|
||||||
|
<S.Table.Data>
|
||||||
|
<S.Skeleton css={{ height: '2rem' }} />
|
||||||
|
</S.Table.Data>
|
||||||
|
</S.Table.Row>
|
||||||
|
);
|
||||||
|
|
@ -1,33 +1,23 @@
|
||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
import { NFACard, NFACardSkeleton } from '@/components';
|
|
||||||
import { lastNFAsPaginatedDocument } from '@/graphclient';
|
import { lastNFAsPaginatedDocument } from '@/graphclient';
|
||||||
import { useWindowScrollEnd } from '@/hooks';
|
import { useWindowScrollEnd } from '@/hooks';
|
||||||
|
|
||||||
import { Explore } from '../explore.context';
|
import { Explore } from '../../explore.context';
|
||||||
import { NFAListFragmentStyles as S } from './nfa-list.styles';
|
import { NFAGridFragment } from './nfa-grid.fragment';
|
||||||
|
import { NFAListFragment } from './nfa-list.fragment';
|
||||||
|
|
||||||
const pageSize = 10; //Set this size to test pagination
|
const pageSize = 10; //Set this size to test pagination
|
||||||
|
|
||||||
const LoadingSkeletons: React.FC = () => (
|
export const NFAsContainerFragment: React.FC = () => {
|
||||||
<>
|
|
||||||
<NFACardSkeleton />
|
|
||||||
<NFACardSkeleton />
|
|
||||||
<NFACardSkeleton />
|
|
||||||
<NFACardSkeleton />
|
|
||||||
<NFACardSkeleton />
|
|
||||||
<NFACardSkeleton />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
export const NFAListFragment: React.FC = () => {
|
|
||||||
const {
|
const {
|
||||||
endReached,
|
endReached,
|
||||||
orderBy,
|
orderBy,
|
||||||
orderDirection,
|
orderDirection,
|
||||||
pageNumber,
|
pageNumber,
|
||||||
search,
|
search,
|
||||||
|
nfaView,
|
||||||
setEndReached,
|
setEndReached,
|
||||||
setPageNumber,
|
setPageNumber,
|
||||||
} = Explore.useContext();
|
} = Explore.useContext();
|
||||||
|
|
@ -46,7 +36,9 @@ export const NFAListFragment: React.FC = () => {
|
||||||
skip: pageNumber * pageSize, //skip is for the pagination
|
skip: pageNumber * pageSize, //skip is for the pagination
|
||||||
},
|
},
|
||||||
onCompleted: (data) => {
|
onCompleted: (data) => {
|
||||||
if (data.tokens.length - tokens.length < pageSize) setEndReached(true);
|
if (data.tokens.length - tokens.length < pageSize) {
|
||||||
|
setEndReached(true);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -63,17 +55,9 @@ export const NFAListFragment: React.FC = () => {
|
||||||
|
|
||||||
if (queryError) return <div>Error</div>; //TODO handle error
|
if (queryError) return <div>Error</div>; //TODO handle error
|
||||||
|
|
||||||
return (
|
if (nfaView === 'grid')
|
||||||
<S.Container>
|
return <NFAGridFragment tokens={tokens} isLoading={isLoading} />;
|
||||||
{tokens.map((token) => (
|
else {
|
||||||
<NFACard data={token} key={token.id} />
|
return <NFAListFragment tokens={tokens} isLoading={isLoading} />;
|
||||||
))}
|
}
|
||||||
|
|
||||||
{isLoading && <LoadingSkeletons />}
|
|
||||||
|
|
||||||
{!isLoading && tokens.length === 0 && (
|
|
||||||
<S.EmptyMessage>Nothing found.</S.EmptyMessage>
|
|
||||||
)}
|
|
||||||
</S.Container>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
@ -25,11 +25,13 @@ const orderResults: SortItem[] = [
|
||||||
export const NFASearchFragment: React.FC = () => {
|
export const NFASearchFragment: React.FC = () => {
|
||||||
const {
|
const {
|
||||||
search,
|
search,
|
||||||
|
nfaView,
|
||||||
setEndReached,
|
setEndReached,
|
||||||
setOrderBy,
|
setOrderBy,
|
||||||
setOrderDirection,
|
setOrderDirection,
|
||||||
setSearch,
|
setSearch,
|
||||||
setPageNumber,
|
setPageNumber,
|
||||||
|
setNFAView,
|
||||||
} = Explore.useContext();
|
} = Explore.useContext();
|
||||||
const [selectedValue, setSelectedValue] = useState<SortItem>(orderResults[0]);
|
const [selectedValue, setSelectedValue] = useState<SortItem>(orderResults[0]);
|
||||||
|
|
||||||
|
|
@ -40,6 +42,10 @@ export const NFASearchFragment: React.FC = () => {
|
||||||
skip: Boolean(search),
|
skip: Boolean(search),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handleViewChange = (view: View): void => {
|
||||||
|
setNFAView(view);
|
||||||
|
};
|
||||||
|
|
||||||
const handleSortChange = (item: SortItem | undefined): void => {
|
const handleSortChange = (item: SortItem | undefined): void => {
|
||||||
if (item) {
|
if (item) {
|
||||||
setSelectedValue(item);
|
setSelectedValue(item);
|
||||||
|
|
@ -83,41 +89,64 @@ export const NFASearchFragment: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<S.Container>
|
<S.Container>
|
||||||
<S.Data.Wrapper>
|
<S.Data.Wrapper>
|
||||||
{totalTokens?.collection && (<>
|
{totalTokens?.collection && (
|
||||||
<S.Data.Text>All NFAs </S.Data.Text>
|
<>
|
||||||
<S.Data.Number>({totalTokens.collection.totalTokens})</S.Data.Number>
|
<S.Data.Text>All NFAs </S.Data.Text>
|
||||||
</>)}
|
<S.Data.Number>
|
||||||
|
({totalTokens.collection.totalTokens})
|
||||||
|
</S.Data.Number>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</S.Data.Wrapper>
|
</S.Data.Wrapper>
|
||||||
|
|
||||||
<S.Input.Wrapper>
|
<S.Flex>
|
||||||
<InputGroup css={{ flex: 1 }}>
|
<S.Input.Wrapper>
|
||||||
<S.Input.Icon name="search" />
|
<InputGroup css={{ flex: 1 }}>
|
||||||
<InputGroupText placeholder="Search" onChange={handleSearchChange} />
|
<S.Input.Icon name="search" />
|
||||||
</InputGroup>
|
<InputGroupText
|
||||||
<Combobox
|
placeholder="Search"
|
||||||
items={orderResults}
|
onChange={handleSearchChange}
|
||||||
selected={[selectedValue, handleSortChange]}
|
/>
|
||||||
css={{ minWidth: '$28' }}
|
</InputGroup>
|
||||||
queryKey="label"
|
<Combobox
|
||||||
>
|
items={orderResults}
|
||||||
{({ Field, Options }) => (
|
selected={[selectedValue, handleSortChange]}
|
||||||
<>
|
css={{ minWidth: '$28' }}
|
||||||
<Field
|
queryKey="label"
|
||||||
css={{
|
>
|
||||||
backgroundColor: '$slate4',
|
{({ Field, Options }) => (
|
||||||
borderColor: '$slate4',
|
<>
|
||||||
color: '$slate11',
|
<Field
|
||||||
}}
|
css={{
|
||||||
>
|
color: '$slate11',
|
||||||
{(selected) => selected?.label || 'Select'}
|
}}
|
||||||
</Field>
|
>
|
||||||
<Options disableSearch css={{ minWidth: '$44', left: 'unset' }}>
|
{(selected) => selected?.label || 'Select'}
|
||||||
{(item) => item.label}
|
</Field>
|
||||||
</Options>
|
<Options disableSearch css={{ minWidth: '$44', left: 'unset' }}>
|
||||||
</>
|
{(item) => item.label}
|
||||||
)}
|
</Options>
|
||||||
</Combobox>
|
</>
|
||||||
</S.Input.Wrapper>
|
)}
|
||||||
|
</Combobox>
|
||||||
|
</S.Input.Wrapper>
|
||||||
|
|
||||||
|
{/* TODO move this to the app context */}
|
||||||
|
<S.GridList.Wrapper>
|
||||||
|
<S.GridList.Icon
|
||||||
|
name="grid"
|
||||||
|
selected={nfaView === 'grid'}
|
||||||
|
css={{ btrr: '0', bbrr: '0' }}
|
||||||
|
onClick={() => handleViewChange('grid')}
|
||||||
|
/>
|
||||||
|
<S.GridList.Icon
|
||||||
|
name="list"
|
||||||
|
css={{ btlr: '0', bblr: '0' }}
|
||||||
|
selected={nfaView === 'list'}
|
||||||
|
onClick={() => handleViewChange('list')}
|
||||||
|
/>
|
||||||
|
</S.GridList.Wrapper>
|
||||||
|
</S.Flex>
|
||||||
</S.Container>
|
</S.Container>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,16 @@ export const NFASearchFragmentStyles = {
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Flex: styled(Flex, {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
gap: '$3h',
|
||||||
|
|
||||||
|
'@media (max-width: 374px)': {
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
Input: {
|
Input: {
|
||||||
Wrapper: styled(Flex, {
|
Wrapper: styled(Flex, {
|
||||||
gap: '$3',
|
gap: '$3',
|
||||||
|
|
@ -36,4 +46,31 @@ export const NFASearchFragmentStyles = {
|
||||||
fontSize: '$lg',
|
fontSize: '$lg',
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
GridList: {
|
||||||
|
Wrapper: styled(Flex, {
|
||||||
|
border: '1px solid $slate7',
|
||||||
|
borderRadius: '$lg',
|
||||||
|
backgroundColor: '$slate7',
|
||||||
|
}),
|
||||||
|
Icon: styled(Icon, {
|
||||||
|
p: '$2 $3',
|
||||||
|
border: 'none',
|
||||||
|
borderRadius: '$lg',
|
||||||
|
cursor: 'pointer',
|
||||||
|
|
||||||
|
variants: {
|
||||||
|
selected: {
|
||||||
|
true: {
|
||||||
|
color: 'white',
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
},
|
||||||
|
false: {
|
||||||
|
color: '$slate7 ',
|
||||||
|
backgroundColor: 'black',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,17 +3,21 @@ import { useState } from 'react';
|
||||||
import { OrderDirection, Token_orderBy } from '@/graphclient';
|
import { OrderDirection, Token_orderBy } from '@/graphclient';
|
||||||
import { createContext } from '@/utils';
|
import { createContext } from '@/utils';
|
||||||
|
|
||||||
|
type View = 'grid' | 'list';
|
||||||
|
|
||||||
export type ExploreContext = {
|
export type ExploreContext = {
|
||||||
search: string;
|
search: string;
|
||||||
orderBy: Token_orderBy;
|
orderBy: Token_orderBy;
|
||||||
orderDirection: OrderDirection;
|
orderDirection: OrderDirection;
|
||||||
pageNumber: number;
|
pageNumber: number;
|
||||||
endReached: boolean;
|
endReached: boolean;
|
||||||
|
nfaView: View;
|
||||||
setSearch: (search: string) => void;
|
setSearch: (search: string) => void;
|
||||||
setOrderBy: (orderBy: string) => void;
|
setOrderBy: (orderBy: Token_orderBy) => void;
|
||||||
setOrderDirection: (orderDirection: OrderDirection) => void;
|
setOrderDirection: (orderDirection: OrderDirection) => void;
|
||||||
setPageNumber: (pageNumber: number) => void;
|
setPageNumber: (pageNumber: number) => void;
|
||||||
setEndReached: (isEndReaced: boolean) => void;
|
setEndReached: (isEndReaced: boolean) => void;
|
||||||
|
setNFAView: (view: View) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const [ExploreProvider, useContext] = createContext<ExploreContext>({
|
const [ExploreProvider, useContext] = createContext<ExploreContext>({
|
||||||
|
|
@ -29,11 +33,12 @@ export abstract class Explore {
|
||||||
children,
|
children,
|
||||||
}: Explore.ProviderProps) => {
|
}: Explore.ProviderProps) => {
|
||||||
const [search, setSearch] = useState('');
|
const [search, setSearch] = useState('');
|
||||||
const [orderBy, setOrderBy] = useState('tokenId');
|
const [orderBy, setOrderBy] = useState<Token_orderBy>('tokenId');
|
||||||
const [orderDirection, setOrderDirection] =
|
const [orderDirection, setOrderDirection] =
|
||||||
useState<OrderDirection>('desc');
|
useState<OrderDirection>('desc');
|
||||||
const [pageNumber, setPageNumber] = useState(0);
|
const [pageNumber, setPageNumber] = useState(0);
|
||||||
const [endReached, setEndReached] = useState(false);
|
const [endReached, setEndReached] = useState(false);
|
||||||
|
const [nfaView, setNFAView] = useState<View>('grid');
|
||||||
|
|
||||||
const context = {
|
const context = {
|
||||||
search,
|
search,
|
||||||
|
|
@ -41,11 +46,13 @@ export abstract class Explore {
|
||||||
orderDirection,
|
orderDirection,
|
||||||
pageNumber,
|
pageNumber,
|
||||||
endReached,
|
endReached,
|
||||||
|
nfaView,
|
||||||
setSearch,
|
setSearch,
|
||||||
setOrderBy,
|
setOrderBy,
|
||||||
setOrderDirection,
|
setOrderDirection,
|
||||||
setPageNumber,
|
setPageNumber,
|
||||||
setEndReached,
|
setEndReached,
|
||||||
|
setNFAView,
|
||||||
};
|
};
|
||||||
|
|
||||||
return <ExploreProvider value={context}>{children}</ExploreProvider>;
|
return <ExploreProvider value={context}>{children}</ExploreProvider>;
|
||||||
|
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
||||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
import { Button, Flex, Icon, NFAPreview } from '@/components';
|
|
||||||
import { parseNumberToHexColor } from '@/utils/color';
|
|
||||||
|
|
||||||
import { IndexedNFA } from '../indexed-nfa.context';
|
|
||||||
import { IndexedNFAStyles as S } from '../indexed-nfa.styles';
|
|
||||||
|
|
||||||
const Preview: React.FC = () => {
|
|
||||||
const { nfa } = IndexedNFA.useContext();
|
|
||||||
|
|
||||||
const color = useMemo(
|
|
||||||
() => `#${parseNumberToHexColor(nfa.color)}`,
|
|
||||||
[nfa]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<NFAPreview
|
|
||||||
color={color}
|
|
||||||
logo={nfa.logo}
|
|
||||||
ens={nfa.ENS}
|
|
||||||
name={nfa.name}
|
|
||||||
size="100%"
|
|
||||||
css={{
|
|
||||||
borderRadius: '$lg',
|
|
||||||
border: '1px solid $slate6',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const CreateAccessPoint: React.FC = () => {
|
|
||||||
const { nfa } = IndexedNFA.useContext();
|
|
||||||
return (
|
|
||||||
<S.Aside.CreateAccessPoint.Container>
|
|
||||||
<S.Aside.CreateAccessPoint.Heading>
|
|
||||||
Host NFA Frontend
|
|
||||||
</S.Aside.CreateAccessPoint.Heading>
|
|
||||||
{/* TODO: replace with correct text */}
|
|
||||||
|
|
||||||
<S.Aside.CreateAccessPoint.Text>
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce vitae
|
|
||||||
ante erat. Sed quis finibus diam.
|
|
||||||
</S.Aside.CreateAccessPoint.Text>
|
|
||||||
|
|
||||||
<Flex css={{ gap: '$3' }}>
|
|
||||||
<Button as={Link} to={`/create-ap/${nfa.tokenId}`} colorScheme="blue">
|
|
||||||
Host NFA Frontend
|
|
||||||
</Button>
|
|
||||||
<S.Aside.CreateAccessPoint.Extra href="">
|
|
||||||
{/* TODO: place correct href */}
|
|
||||||
Learn more
|
|
||||||
<Icon name="chevron-right" />
|
|
||||||
</S.Aside.CreateAccessPoint.Extra>
|
|
||||||
</Flex>
|
|
||||||
</S.Aside.CreateAccessPoint.Container>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const IndexedNFAAsideFragment: React.FC = () => {
|
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
|
||||||
const [top, setTop] = useState<number>();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setTop(ref.current?.getBoundingClientRect().top);
|
|
||||||
}, [ref]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<S.Aside.Container ref={ref} css={{ top }}>
|
|
||||||
<Preview />
|
|
||||||
<CreateAccessPoint />
|
|
||||||
</S.Aside.Container>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
import { Button, Flex, Icon, IconName, Menu } from '@/components';
|
||||||
|
import { env } from '@/constants';
|
||||||
|
import { FleekERC721 } from '@/integrations/ethereum/contracts';
|
||||||
|
import { forwardStyledRef } from '@/theme';
|
||||||
|
import { AppLog } from '@/utils';
|
||||||
|
|
||||||
|
import { IndexedNFA } from '../../indexed-nfa.context';
|
||||||
|
import { IndexedNFAStyles as S } from '../../indexed-nfa.styles';
|
||||||
|
|
||||||
|
const openseaLink = `https://${
|
||||||
|
env.environment === 'development' ? 'testnets' : ''
|
||||||
|
}.opensea.io/assets/${
|
||||||
|
env.environment === 'development' ? 'goerli' : 'ethereum'
|
||||||
|
}/${FleekERC721.address}`;
|
||||||
|
|
||||||
|
type CustomButtonProps = {
|
||||||
|
icon: IconName;
|
||||||
|
};
|
||||||
|
|
||||||
|
const CustomButon = forwardStyledRef<HTMLButtonElement, CustomButtonProps>(
|
||||||
|
({ icon, ...props }, ref) => (
|
||||||
|
<Button
|
||||||
|
ref={ref}
|
||||||
|
{...props}
|
||||||
|
css={{ borderRadius: '0.375rem', padding: '$2', color: 'white' }}
|
||||||
|
>
|
||||||
|
<Icon name={icon} />
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
type MenuItemProps = {
|
||||||
|
label: string;
|
||||||
|
iconName: IconName;
|
||||||
|
href: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const MenuItem: React.FC<MenuItemProps> = ({
|
||||||
|
label,
|
||||||
|
iconName,
|
||||||
|
href,
|
||||||
|
}: MenuItemProps) => {
|
||||||
|
return (
|
||||||
|
<a href={href} rel="noopener noreferrer" target="_blank">
|
||||||
|
<Flex css={{ gap: '$2' }}>
|
||||||
|
<Icon name={iconName} />
|
||||||
|
{label}
|
||||||
|
</Flex>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ButtonsFragment: React.FC = () => {
|
||||||
|
const { nfa } = IndexedNFA.useContext();
|
||||||
|
|
||||||
|
const handleShareOnClick = (): void => {
|
||||||
|
const location = window.location.href;
|
||||||
|
navigator.clipboard.writeText(location);
|
||||||
|
AppLog.successToast('Link copied to clipboard');
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<S.Aside.Button.Container>
|
||||||
|
<Menu.Root>
|
||||||
|
<Menu.Button as={CustomButon} icon="three-dots" />
|
||||||
|
<Menu.Items css={{ minWidth: '12rem' }}>
|
||||||
|
{/* TODO remove span and render as fragment */}
|
||||||
|
<span>
|
||||||
|
<MenuItem
|
||||||
|
label="Open on OpenSea"
|
||||||
|
iconName="opensea"
|
||||||
|
href={`${openseaLink}/${nfa.tokenId}`}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<MenuItem
|
||||||
|
label="Share to Twitter"
|
||||||
|
iconName="twitter"
|
||||||
|
href={env.twitter.url}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</Menu.Items>
|
||||||
|
</Menu.Root>
|
||||||
|
|
||||||
|
{/* TODO add tooltip to copy link */}
|
||||||
|
<CustomButon icon="share" onClick={handleShareOnClick} />
|
||||||
|
</S.Aside.Button.Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
|
import { Flex, Icon, NFAIcon, ResolvedAddress } from '@/components';
|
||||||
|
|
||||||
|
import { IndexedNFA } from '../../indexed-nfa.context';
|
||||||
|
import { IndexedNFAStyles as S } from '../../indexed-nfa.styles';
|
||||||
|
|
||||||
|
type BadgeProps = {
|
||||||
|
verified: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Badge: React.FC<BadgeProps> = ({ verified }: BadgeProps) => {
|
||||||
|
const text = useMemo(
|
||||||
|
() => (verified ? 'Verified' : 'Unverified'),
|
||||||
|
[verified]
|
||||||
|
);
|
||||||
|
|
||||||
|
const icon = useMemo(() => (verified ? 'verified' : 'error'), [verified]);
|
||||||
|
const color = useMemo(() => (verified ? '$green10' : '$red10'), [verified]);
|
||||||
|
return (
|
||||||
|
<S.Aside.Header.Badge verified={verified}>
|
||||||
|
<Icon name={icon} css={{ color: color }} />
|
||||||
|
{text}
|
||||||
|
</S.Aside.Header.Badge>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Header: React.FC = () => {
|
||||||
|
const { nfa } = IndexedNFA.useContext();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<S.Aside.Header.Wrapper>
|
||||||
|
<S.Aside.Header.Container>
|
||||||
|
<S.Aside.Header.Header>{nfa.name}</S.Aside.Header.Header>
|
||||||
|
<Badge verified={nfa.verified} />
|
||||||
|
</S.Aside.Header.Container>
|
||||||
|
|
||||||
|
<Flex css={{ gap: '$1h' }}>
|
||||||
|
<NFAIcon image={nfa.logo} color={'white'} />
|
||||||
|
<ResolvedAddress>{nfa.owner.id}</ResolvedAddress>
|
||||||
|
</Flex>
|
||||||
|
</S.Aside.Header.Wrapper>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { Flex, Text } from '@/components';
|
||||||
|
import { getDate } from '@/utils';
|
||||||
|
|
||||||
|
import { IndexedNFA } from '../../indexed-nfa.context';
|
||||||
|
import { IndexedNFAStyles as S } from '../../indexed-nfa.styles';
|
||||||
|
|
||||||
|
type HeaderDataProps = {
|
||||||
|
label: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
const HeaderData: React.FC<HeaderDataProps> = ({
|
||||||
|
label,
|
||||||
|
children,
|
||||||
|
}: HeaderDataProps) => (
|
||||||
|
<Flex css={{ gap: '$2', fontSize: '14px', fontWeight: '400' }}>
|
||||||
|
<Text css={{ color: '$slate11' }}>{label}</Text>
|
||||||
|
<Text css={{ color: '$slate12' }}>{children}</Text>
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const NFAInfo: React.FC = () => {
|
||||||
|
const { nfa } = IndexedNFA.useContext();
|
||||||
|
return (
|
||||||
|
<Flex css={{ alignItems: 'center', gap: '$2h' }}>
|
||||||
|
<HeaderData label="Hosted NFAs">
|
||||||
|
{nfa.accessPoints?.length ?? 0}
|
||||||
|
</HeaderData>
|
||||||
|
|
||||||
|
<S.Aside.Divider.Elipse />
|
||||||
|
|
||||||
|
<HeaderData label="Created">{getDate(nfa.createdAt)}</HeaderData>
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
|
import { NFAPreview } from '@/components';
|
||||||
|
import { parseNumberToHexColor } from '@/utils/color';
|
||||||
|
|
||||||
|
import { IndexedNFA } from '../../indexed-nfa.context';
|
||||||
|
|
||||||
|
export const Preview: React.FC = () => {
|
||||||
|
const { nfa } = IndexedNFA.useContext();
|
||||||
|
|
||||||
|
const color = useMemo(
|
||||||
|
() => `#${parseNumberToHexColor(nfa.color ?? '')}`,
|
||||||
|
[nfa]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NFAPreview
|
||||||
|
color={color}
|
||||||
|
logo={nfa.logo}
|
||||||
|
ens={nfa.ENS}
|
||||||
|
name={nfa.name}
|
||||||
|
size="100%"
|
||||||
|
css={{
|
||||||
|
borderRadius: '$lg',
|
||||||
|
border: '1px solid $slate6',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
import { useMemo, useState } from 'react';
|
||||||
|
|
||||||
|
import { Flex } from '@/components';
|
||||||
|
import { getRepositoryFromURL } from '@/utils';
|
||||||
|
|
||||||
|
import { IndexedNFA } from '../../indexed-nfa.context';
|
||||||
|
import { IndexedNFAStyles as S } from '../../indexed-nfa.styles';
|
||||||
|
import { Tab, TabContainer } from '../../tabs';
|
||||||
|
|
||||||
|
const OverviewFragment: React.FC = () => {
|
||||||
|
const { nfa } = IndexedNFA.useContext();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<S.Aside.Overview.Container
|
||||||
|
css={{ gap: '$4h', p: '$5 $6', height: '336px' }}
|
||||||
|
>
|
||||||
|
<S.Aside.Overview.Row.Container>
|
||||||
|
<S.Aside.Overview.Row.Label>Token ID</S.Aside.Overview.Row.Label>
|
||||||
|
<S.Aside.Overview.Row.Value>{nfa.tokenId}</S.Aside.Overview.Row.Value>
|
||||||
|
</S.Aside.Overview.Row.Container>
|
||||||
|
<S.Aside.Divider.Line />
|
||||||
|
<S.Aside.Overview.Row.Container>
|
||||||
|
<S.Aside.Overview.Row.Label>Network</S.Aside.Overview.Row.Label>
|
||||||
|
<S.Aside.Overview.Row.Value>Mainnet</S.Aside.Overview.Row.Value>
|
||||||
|
</S.Aside.Overview.Row.Container>
|
||||||
|
<S.Aside.Divider.Line />
|
||||||
|
<S.Aside.Overview.Row.Container>
|
||||||
|
<S.Aside.Overview.Row.Label>Standard</S.Aside.Overview.Row.Label>
|
||||||
|
<S.Aside.Overview.Row.Value>ERC_721</S.Aside.Overview.Row.Value>
|
||||||
|
</S.Aside.Overview.Row.Container>
|
||||||
|
<S.Aside.Divider.Line />
|
||||||
|
<S.Aside.Overview.Row.Container>
|
||||||
|
<S.Aside.Overview.Row.Label>Description</S.Aside.Overview.Row.Label>
|
||||||
|
</S.Aside.Overview.Row.Container>
|
||||||
|
<S.Aside.Overview.Description>
|
||||||
|
{nfa.description}
|
||||||
|
</S.Aside.Overview.Description>
|
||||||
|
</S.Aside.Overview.Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const PropertiesFragment: React.FC = () => {
|
||||||
|
const { nfa } = IndexedNFA.useContext();
|
||||||
|
|
||||||
|
const traitsToShow = useMemo(() => {
|
||||||
|
return [
|
||||||
|
[nfa.ENS, 'ENS'],
|
||||||
|
[getRepositoryFromURL(nfa.gitRepository.id), 'Repository'],
|
||||||
|
[nfa.externalURL, 'Domain'],
|
||||||
|
];
|
||||||
|
}, [nfa]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Flex css={{ flexDirection: 'column', gap: '$3', height: '336px' }}>
|
||||||
|
{traitsToShow.map(([value, label], index) => (
|
||||||
|
<S.Aside.Overview.Container
|
||||||
|
css={{ gap: '$1', p: '$2h $4' }}
|
||||||
|
key={index}
|
||||||
|
>
|
||||||
|
<S.Aside.Overview.Row.Value>
|
||||||
|
{value || '-'}
|
||||||
|
</S.Aside.Overview.Row.Value>
|
||||||
|
<S.Aside.Overview.Row.Label>{label}</S.Aside.Overview.Row.Label>
|
||||||
|
</S.Aside.Overview.Container>
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TabFragment: React.FC = () => {
|
||||||
|
const [tabSelected, setTabSelected] = useState<number>(0);
|
||||||
|
const handleClick = (index: number): void => {
|
||||||
|
setTabSelected(index);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TabContainer>
|
||||||
|
{['Overview', 'Properties'].map((label, index) => (
|
||||||
|
<Tab
|
||||||
|
key={index}
|
||||||
|
index={index}
|
||||||
|
label={label}
|
||||||
|
active={index === tabSelected}
|
||||||
|
onTabClick={handleClick}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</TabContainer>
|
||||||
|
{tabSelected === 0 ? <OverviewFragment /> : <PropertiesFragment />}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { useEffect, useRef, useState } from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { App } from '@/app.context';
|
||||||
|
import { Button } from '@/components';
|
||||||
|
import { parseNumberToHexColor } from '@/utils/color';
|
||||||
|
|
||||||
|
import { IndexedNFA } from '../../indexed-nfa.context';
|
||||||
|
import { IndexedNFAStyles as S } from '../../indexed-nfa.styles';
|
||||||
|
import { ButtonsFragment } from './aside-buttons.fragment';
|
||||||
|
import { Header } from './aside-header.fragment';
|
||||||
|
import { NFAInfo } from './aside-nfa-info.fragment';
|
||||||
|
import { Preview } from './aside-preview.fragment';
|
||||||
|
import { TabFragment } from './aside-tabs.fragment';
|
||||||
|
|
||||||
|
export const IndexedNFAAsideFragment: React.FC = () => {
|
||||||
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
const [top, setTop] = useState<number>();
|
||||||
|
const { nfa } = IndexedNFA.useContext();
|
||||||
|
|
||||||
|
const { backgroundColor } = App.useContext();
|
||||||
|
const background = `radial-gradient(closest-corner circle at 90% 45%, #${backgroundColor}8c 1% ,#${backgroundColor}57 20%, transparent 40%), radial-gradient(closest-corner circle at 60% 25%, #${backgroundColor} 3%, #${backgroundColor}73 30%, #181818 70%)`;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTop(ref.current?.getBoundingClientRect().top);
|
||||||
|
}, [ref]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<S.Aside.Container
|
||||||
|
ref={ref}
|
||||||
|
css={{ top, background, backdropFilter: 'blur(10px)' }}
|
||||||
|
>
|
||||||
|
<Preview />
|
||||||
|
<Header />
|
||||||
|
<NFAInfo />
|
||||||
|
<ButtonsFragment />
|
||||||
|
<Button
|
||||||
|
as={Link}
|
||||||
|
to={`/create-ap/${nfa.tokenId}`}
|
||||||
|
css={{
|
||||||
|
backgroundColor: `#${parseNumberToHexColor(nfa.color)}`,
|
||||||
|
color: 'white',
|
||||||
|
}}
|
||||||
|
>{`Host ${nfa.name} NFA`}</Button>
|
||||||
|
<TabFragment />
|
||||||
|
</S.Aside.Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
export * from './aside.fragment';
|
export * from './aside/aside.fragment';
|
||||||
export * from './main.fragment';
|
export * from './main/main.fragment';
|
||||||
export * from './skeleton.fragment';
|
export * from './skeleton.fragment';
|
||||||
|
|
|
||||||
|
|
@ -1,231 +0,0 @@
|
||||||
import React, { useMemo } from 'react';
|
|
||||||
|
|
||||||
import { Flex, Icon, IconName, ResolvedAddress, Text } from '@/components';
|
|
||||||
import { getDate, getRepositoryFromURL, getTimeSince } from '@/utils';
|
|
||||||
|
|
||||||
import { IndexedNFA } from '../indexed-nfa.context';
|
|
||||||
import { IndexedNFAStyles as S } from '../indexed-nfa.styles';
|
|
||||||
|
|
||||||
type HeaderDataProps = {
|
|
||||||
label: string;
|
|
||||||
children: React.ReactNode;
|
|
||||||
};
|
|
||||||
|
|
||||||
const HeaderData: React.FC<HeaderDataProps> = ({
|
|
||||||
label,
|
|
||||||
children,
|
|
||||||
}: HeaderDataProps) => (
|
|
||||||
<Flex css={{ gap: '$2' }}>
|
|
||||||
<Text css={{ color: '$slate11' }}>{label}</Text>
|
|
||||||
<Text css={{ color: '$slate12' }}>{children}</Text>
|
|
||||||
</Flex>
|
|
||||||
);
|
|
||||||
|
|
||||||
const Header: React.FC = () => {
|
|
||||||
const { nfa } = IndexedNFA.useContext();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<S.Main.Heading>{nfa.name}</S.Main.Heading>
|
|
||||||
<Flex css={{ justifyContent: 'space-between', alignItems: 'center' }}>
|
|
||||||
<HeaderData label="Owner">
|
|
||||||
<ResolvedAddress>{nfa.owner.id}</ResolvedAddress>
|
|
||||||
</HeaderData>
|
|
||||||
|
|
||||||
<S.Main.Divider.Elipse />
|
|
||||||
|
|
||||||
<HeaderData label="Created">{getDate(nfa.createdAt)}</HeaderData>
|
|
||||||
|
|
||||||
<S.Main.Divider.Elipse />
|
|
||||||
|
|
||||||
<HeaderData label="Access Points">
|
|
||||||
{nfa.accessPoints?.length ?? 0}
|
|
||||||
</HeaderData>
|
|
||||||
</Flex>
|
|
||||||
<S.Main.Divider.Line />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const Description: React.FC = () => {
|
|
||||||
const { nfa } = IndexedNFA.useContext();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<S.Main.SectionHeading css={{ marginTop: 0 }}>
|
|
||||||
Description
|
|
||||||
</S.Main.SectionHeading>
|
|
||||||
<S.Main.DataContainer as={S.Main.Paragraph}>
|
|
||||||
{nfa.description}
|
|
||||||
</S.Main.DataContainer>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
type DataWrapperProps = React.PropsWithChildren<{
|
|
||||||
label: string | number;
|
|
||||||
}>;
|
|
||||||
|
|
||||||
const DataWrapper: React.FC<DataWrapperProps> = ({
|
|
||||||
children,
|
|
||||||
label,
|
|
||||||
}: DataWrapperProps) => (
|
|
||||||
<S.Main.DataContainer key={label} css={{ flex: 1, minWidth: '45%' }}>
|
|
||||||
<Text css={{ color: '$slate12', fontWeight: 700 }}>{children || '-'}</Text>
|
|
||||||
<Text css={{ color: '$slate11' }}>{label}</Text>
|
|
||||||
</S.Main.DataContainer>
|
|
||||||
);
|
|
||||||
|
|
||||||
const Traits: React.FC = () => {
|
|
||||||
const { nfa } = IndexedNFA.useContext();
|
|
||||||
|
|
||||||
const traitsToShow = useMemo(() => {
|
|
||||||
return [
|
|
||||||
[nfa.ENS, 'ENS'],
|
|
||||||
[getRepositoryFromURL(nfa.gitRepository.id), 'Repository'],
|
|
||||||
['', 'Version'],
|
|
||||||
[nfa.externalURL, 'Domain'],
|
|
||||||
];
|
|
||||||
}, [nfa]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<S.Main.SectionHeading>Traits</S.Main.SectionHeading>
|
|
||||||
<S.Main.DataList>
|
|
||||||
{traitsToShow.map(([value, label]) => (
|
|
||||||
<DataWrapper key={label} label={label}>
|
|
||||||
{value}
|
|
||||||
</DataWrapper>
|
|
||||||
))}
|
|
||||||
</S.Main.DataList>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
type VerificationBannerProps = {
|
|
||||||
verified: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
const VerificationBanner: React.FC<VerificationBannerProps> = ({
|
|
||||||
verified,
|
|
||||||
}: VerificationBannerProps) => {
|
|
||||||
const [text, icon] = useMemo<[string, IconName]>(() => {
|
|
||||||
if (verified)
|
|
||||||
return ['This Non Fungible Application is Verified.', 'verified'];
|
|
||||||
return ['This Non Fungible Application is not Verified.', 'error'];
|
|
||||||
}, [verified]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<S.Main.VerificationBanner verified={verified}>
|
|
||||||
{text}
|
|
||||||
<Icon
|
|
||||||
name={icon}
|
|
||||||
css={{
|
|
||||||
fontSize: '3.5rem',
|
|
||||||
color: '$black',
|
|
||||||
position: 'absolute',
|
|
||||||
right: 'calc(8% - 1.75rem)',
|
|
||||||
zIndex: 1,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</S.Main.VerificationBanner>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const Verification: React.FC = () => {
|
|
||||||
const { nfa } = IndexedNFA.useContext();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<S.Main.SectionHeading>Verification</S.Main.SectionHeading>
|
|
||||||
<VerificationBanner verified={nfa.verified} />
|
|
||||||
<S.Main.DataList>
|
|
||||||
<DataWrapper label="Verifier">
|
|
||||||
{nfa.verifier ? (
|
|
||||||
<ResolvedAddress>{nfa.verifier?.id}</ResolvedAddress>
|
|
||||||
) : (
|
|
||||||
'-'
|
|
||||||
)}
|
|
||||||
</DataWrapper>
|
|
||||||
<DataWrapper label="Repository">
|
|
||||||
{getRepositoryFromURL(nfa.gitRepository.id)}
|
|
||||||
</DataWrapper>
|
|
||||||
</S.Main.DataList>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const AccessPoints: React.FC = () => {
|
|
||||||
const {
|
|
||||||
nfa: { accessPoints },
|
|
||||||
} = IndexedNFA.useContext();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<S.Main.SectionHeading>Frontends</S.Main.SectionHeading>
|
|
||||||
<S.Main.Table.Container>
|
|
||||||
<S.Main.Table.Root>
|
|
||||||
<colgroup>
|
|
||||||
<col span={1} style={{ width: '9.5%' }} />
|
|
||||||
<col span={1} style={{ width: '32.5%' }} />
|
|
||||||
<col span={1} style={{ width: '32.5%' }} />
|
|
||||||
<col span={1} style={{ width: '16%' }} />
|
|
||||||
<col span={1} style={{ width: '9.5%' }} />
|
|
||||||
</colgroup>
|
|
||||||
<S.Main.Table.Head>
|
|
||||||
<S.Main.Table.Row>
|
|
||||||
<S.Main.Table.Data>
|
|
||||||
<S.Main.Table.Marker />
|
|
||||||
</S.Main.Table.Data>
|
|
||||||
<S.Main.Table.Data>Domain</S.Main.Table.Data>
|
|
||||||
<S.Main.Table.Data>Owner</S.Main.Table.Data>
|
|
||||||
<S.Main.Table.Data>Created</S.Main.Table.Data>
|
|
||||||
<S.Main.Table.Data />
|
|
||||||
</S.Main.Table.Row>
|
|
||||||
</S.Main.Table.Head>
|
|
||||||
<S.Main.Table.Body>
|
|
||||||
{accessPoints && accessPoints.length > 0 ? (
|
|
||||||
accessPoints.map((item) => (
|
|
||||||
<S.Main.Table.Row key={item.id}>
|
|
||||||
<S.Main.Table.Data align="center">
|
|
||||||
<S.Main.Table.Marker
|
|
||||||
variant={item.contentVerified ? 'active' : 'inactive'}
|
|
||||||
/>
|
|
||||||
</S.Main.Table.Data>
|
|
||||||
<S.Main.Table.Data>{item.id}</S.Main.Table.Data>
|
|
||||||
<S.Main.Table.Data>
|
|
||||||
<ResolvedAddress>{item.owner.id}</ResolvedAddress>
|
|
||||||
</S.Main.Table.Data>
|
|
||||||
<S.Main.Table.Data>
|
|
||||||
{getTimeSince(item.createdAt)}
|
|
||||||
</S.Main.Table.Data>
|
|
||||||
<S.Main.Table.Data>
|
|
||||||
<Icon name="external-link" />
|
|
||||||
</S.Main.Table.Data>
|
|
||||||
</S.Main.Table.Row>
|
|
||||||
))
|
|
||||||
) : (
|
|
||||||
<S.Main.Table.Row>
|
|
||||||
<S.Main.Table.Data align="center" colSpan={5}>
|
|
||||||
<Text>No results</Text>
|
|
||||||
</S.Main.Table.Data>
|
|
||||||
</S.Main.Table.Row>
|
|
||||||
)}
|
|
||||||
</S.Main.Table.Body>
|
|
||||||
</S.Main.Table.Root>
|
|
||||||
</S.Main.Table.Container>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const IndexedNFAMainFragment: React.FC = () => {
|
|
||||||
return (
|
|
||||||
<S.Main.Container>
|
|
||||||
<Header />
|
|
||||||
<Description />
|
|
||||||
<Traits />
|
|
||||||
<Verification />
|
|
||||||
<AccessPoints />
|
|
||||||
</S.Main.Container>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
import { useQuery } from '@apollo/client';
|
||||||
|
import { ethers } from 'ethers';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
|
import Rectangle1 from '@/assets/Rectangle-199.png';
|
||||||
|
import { Flex, ResolvedAddress, Text } from '@/components';
|
||||||
|
import {
|
||||||
|
AccessPoint as AccessPointType,
|
||||||
|
getAccessPointsNFADocument,
|
||||||
|
Owner,
|
||||||
|
} from '@/graphclient';
|
||||||
|
import { useWindowScrollEnd } from '@/hooks';
|
||||||
|
import { AppLog, getTimeSince } from '@/utils';
|
||||||
|
|
||||||
|
import { IndexedNFA } from '../../indexed-nfa.context';
|
||||||
|
import { IndexedNFAStyles as S } from '../../indexed-nfa.styles';
|
||||||
|
import { SkeletonAccessPointsListFragment } from './skeleton.ap-list';
|
||||||
|
|
||||||
|
type AccessPointProps = {
|
||||||
|
data: Pick<AccessPointType, 'id' | 'contentVerified' | 'createdAt'> & {
|
||||||
|
owner: Pick<Owner, 'id'>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const AccessPoint: React.FC<AccessPointProps> = ({
|
||||||
|
data,
|
||||||
|
}: AccessPointProps) => {
|
||||||
|
const { id: name, owner, createdAt } = data;
|
||||||
|
return (
|
||||||
|
<S.Main.AccessPoint.Grid>
|
||||||
|
<S.Main.AccessPoint.Thumbnail>
|
||||||
|
{/* TODO remove for real image */}
|
||||||
|
<img src={Rectangle1} style={{ width: '7rem' }} />
|
||||||
|
</S.Main.AccessPoint.Thumbnail>
|
||||||
|
<S.Main.AccessPoint.Data.Container>
|
||||||
|
<S.Main.AccessPoint.Title>{name}</S.Main.AccessPoint.Title>
|
||||||
|
<Flex css={{ gap: '$2h', alignItems: 'center', textAlign: 'center' }}>
|
||||||
|
<Text css={{ color: '$slate11' }}>
|
||||||
|
<ResolvedAddress>{owner.id}</ResolvedAddress>
|
||||||
|
</Text>
|
||||||
|
<S.Main.Divider.Elipse />
|
||||||
|
{/* TODO get from bunny CDN */}
|
||||||
|
<Text css={{ color: '$slate11' }}>220 views</Text>
|
||||||
|
<S.Main.Divider.Elipse />
|
||||||
|
<Text css={{ color: '$slate11' }}>{getTimeSince(createdAt)}</Text>
|
||||||
|
</Flex>
|
||||||
|
</S.Main.AccessPoint.Data.Container>
|
||||||
|
</S.Main.AccessPoint.Grid>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const pageSize = 10; //Set this size to test pagination
|
||||||
|
|
||||||
|
export const AccessPointsListFragment: React.FC = () => {
|
||||||
|
const {
|
||||||
|
nfa: { tokenId },
|
||||||
|
orderDirection,
|
||||||
|
pageNumber,
|
||||||
|
endReached,
|
||||||
|
setEndReached,
|
||||||
|
setPageNumber,
|
||||||
|
} = IndexedNFA.useContext();
|
||||||
|
|
||||||
|
const handleError = (error: unknown): void => {
|
||||||
|
AppLog.errorToast(
|
||||||
|
'There was an error trying to get the access points',
|
||||||
|
error
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const {
|
||||||
|
loading: isLoading,
|
||||||
|
data: { accessPoints } = { accessPoints: [] },
|
||||||
|
error: queryError,
|
||||||
|
} = useQuery(getAccessPointsNFADocument, {
|
||||||
|
skip: tokenId === undefined,
|
||||||
|
fetchPolicy: 'cache-and-network',
|
||||||
|
variables: {
|
||||||
|
tokenId: ethers.utils.hexlify(Number(tokenId)),
|
||||||
|
orderDirection: orderDirection,
|
||||||
|
orderBy: 'createdAt',
|
||||||
|
pageSize,
|
||||||
|
skip: pageNumber * pageSize, //skip is for the pagination
|
||||||
|
},
|
||||||
|
onCompleted(data) {
|
||||||
|
if (data.accessPoints.length - accessPoints.length < pageSize)
|
||||||
|
setEndReached(true);
|
||||||
|
},
|
||||||
|
onError(error) {
|
||||||
|
handleError(error);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Update page number when there are cached tokens
|
||||||
|
setPageNumber(Math.ceil(accessPoints.length / pageSize));
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useWindowScrollEnd(() => {
|
||||||
|
if (isLoading || endReached || queryError) return;
|
||||||
|
setPageNumber(pageNumber + 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<S.Main.AccessPoint.List>
|
||||||
|
{accessPoints.map((item, index) => (
|
||||||
|
<AccessPoint key={index} data={item} />
|
||||||
|
))}
|
||||||
|
{isLoading && <SkeletonAccessPointsListFragment />}
|
||||||
|
{!isLoading && accessPoints.length === 0 && (
|
||||||
|
<S.Main.AccessPoint.NoResults>
|
||||||
|
<h2>No hosted NFAs</h2>
|
||||||
|
</S.Main.AccessPoint.NoResults>
|
||||||
|
)}
|
||||||
|
</S.Main.AccessPoint.List>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
import { OrderDirection } from '@/../.graphclient';
|
||||||
|
import { Combobox, Flex } from '@/components';
|
||||||
|
import { AppLog } from '@/utils';
|
||||||
|
|
||||||
|
import { IndexedNFA } from '../../indexed-nfa.context';
|
||||||
|
import { IndexedNFAStyles as S } from '../../indexed-nfa.styles';
|
||||||
|
|
||||||
|
type SortItem = {
|
||||||
|
value: OrderDirection;
|
||||||
|
label: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const orderResults: SortItem[] = [
|
||||||
|
{ value: 'desc', label: 'Newest' },
|
||||||
|
{ value: 'asc', label: 'Oldest' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const Header: React.FC = () => {
|
||||||
|
const { setPageNumber, setOrderDirection, setEndReached } =
|
||||||
|
IndexedNFA.useContext();
|
||||||
|
const [selectedValue, setSelectedValue] = useState<SortItem>(orderResults[0]);
|
||||||
|
|
||||||
|
const handleSortChange = (item: SortItem | undefined): void => {
|
||||||
|
if (item) {
|
||||||
|
setSelectedValue(item);
|
||||||
|
setPageNumber(0);
|
||||||
|
setEndReached(false);
|
||||||
|
setOrderDirection(item.value);
|
||||||
|
} else {
|
||||||
|
AppLog.errorToast('Error selecting sort option. Try again');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Flex css={{ justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
|
<S.Main.Heading>Hosted NFAs</S.Main.Heading>
|
||||||
|
<Combobox
|
||||||
|
items={orderResults}
|
||||||
|
selected={[selectedValue, handleSortChange]}
|
||||||
|
css={{ minWidth: '$28' }}
|
||||||
|
queryKey="label"
|
||||||
|
>
|
||||||
|
{({ Field, Options }) => (
|
||||||
|
<>
|
||||||
|
<Field
|
||||||
|
css={{
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
borderColor: '$slate6',
|
||||||
|
color: '$slate11',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{(selected) => selected?.label || 'Select'}
|
||||||
|
</Field>
|
||||||
|
<Options disableSearch css={{ minWidth: '$44', left: 'unset' }}>
|
||||||
|
{(item) => item.label}
|
||||||
|
</Options>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Combobox>
|
||||||
|
</Flex>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { IndexedNFAStyles as S } from '../../indexed-nfa.styles';
|
||||||
|
import { AccessPointsListFragment } from './main-ap-list.fragment';
|
||||||
|
import { Header } from './main-header.fragment';
|
||||||
|
|
||||||
|
export const IndexedNFAMainFragment: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<S.Main.Container>
|
||||||
|
<Header />
|
||||||
|
<AccessPointsListFragment />
|
||||||
|
</S.Main.Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { IndexedNFAStyles as S } from '../../indexed-nfa.styles';
|
||||||
|
|
||||||
|
const SkeletonAccessPoint: React.FC = () => (
|
||||||
|
<S.Main.AccessPoint.Grid>
|
||||||
|
<S.Main.AccessPoint.Thumbnail>
|
||||||
|
<S.Skeleton css={{ height: '6rem' }} />
|
||||||
|
</S.Main.AccessPoint.Thumbnail>
|
||||||
|
<S.Main.AccessPoint.Data.Container>
|
||||||
|
<S.Skeleton css={{ height: '2rem' }} />
|
||||||
|
<S.Skeleton css={{ height: '1.25rem' }} />
|
||||||
|
</S.Main.AccessPoint.Data.Container>
|
||||||
|
</S.Main.AccessPoint.Grid>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const SkeletonAccessPointsListFragment: React.FC = () => (
|
||||||
|
<S.Main.AccessPoint.List>
|
||||||
|
<SkeletonAccessPoint />
|
||||||
|
<SkeletonAccessPoint />
|
||||||
|
<SkeletonAccessPoint />
|
||||||
|
</S.Main.AccessPoint.List>
|
||||||
|
);
|
||||||
|
|
@ -1,16 +1,14 @@
|
||||||
import { IndexedNFAStyles as S } from '../indexed-nfa.styles';
|
import { IndexedNFAStyles as S } from '../indexed-nfa.styles';
|
||||||
|
import { SkeletonAccessPointsListFragment } from './main/skeleton.ap-list';
|
||||||
|
|
||||||
export const IndexedNFASkeletonFragment: React.FC = () => (
|
export const IndexedNFASkeletonFragment: React.FC = () => (
|
||||||
<S.Grid>
|
<S.Grid css={{ justifyItems: 'normal' }}>
|
||||||
<S.Aside.Container>
|
<S.Skeleton
|
||||||
<S.Skeleton css={{ aspectRatio: 1, width: '100%' }} />
|
css={{ aspectRatio: 1, width: '20rem', justifySelf: 'center' }}
|
||||||
</S.Aside.Container>
|
/>
|
||||||
<S.Main.Container css={{ justifyContent: 'stretch' }}>
|
<S.Main.Container css={{ justifyContent: 'stretch' }}>
|
||||||
<S.Skeleton css={{ height: '2.875rem' }} />
|
<S.Skeleton css={{ height: '2.875rem' }} />
|
||||||
<S.Skeleton css={{ height: '1.5rem' }} />
|
<SkeletonAccessPointsListFragment />
|
||||||
<S.Main.Divider.Line />
|
|
||||||
<S.Skeleton css={{ height: '10rem' }} />
|
|
||||||
<S.Skeleton css={{ height: '15rem' }} />
|
|
||||||
</S.Main.Container>
|
</S.Main.Container>
|
||||||
</S.Grid>
|
</S.Grid>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
import { Owner, Token } from '@/graphclient';
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
import { OrderDirection, Owner, Token } from '@/graphclient';
|
||||||
import { createContext } from '@/utils';
|
import { createContext } from '@/utils';
|
||||||
|
|
||||||
const [Provider, useContext] = createContext<IndexedNFA.Context>({
|
const [Provider, useContext] = createContext<IndexedNFA.Context>({
|
||||||
|
|
@ -10,7 +12,21 @@ const [Provider, useContext] = createContext<IndexedNFA.Context>({
|
||||||
export const IndexedNFA = {
|
export const IndexedNFA = {
|
||||||
useContext,
|
useContext,
|
||||||
Provider: ({ children, nfa }: IndexedNFA.ProviderProps): JSX.Element => {
|
Provider: ({ children, nfa }: IndexedNFA.ProviderProps): JSX.Element => {
|
||||||
return <Provider value={{ nfa }}>{children}</Provider>;
|
const [orderDirection, setOrderDirection] =
|
||||||
|
useState<OrderDirection>('desc');
|
||||||
|
const [pageNumber, setPageNumber] = useState(0);
|
||||||
|
const [endReached, setEndReached] = useState(false);
|
||||||
|
|
||||||
|
const context = {
|
||||||
|
nfa,
|
||||||
|
orderDirection,
|
||||||
|
pageNumber,
|
||||||
|
endReached,
|
||||||
|
setOrderDirection,
|
||||||
|
setPageNumber,
|
||||||
|
setEndReached,
|
||||||
|
};
|
||||||
|
return <Provider value={context}>{children}</Provider>;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -19,6 +35,12 @@ export namespace IndexedNFA {
|
||||||
nfa: Omit<Token, 'mintTransaction' | 'id' | 'owner'> & {
|
nfa: Omit<Token, 'mintTransaction' | 'id' | 'owner'> & {
|
||||||
owner: Pick<Owner, 'id'>;
|
owner: Pick<Owner, 'id'>;
|
||||||
};
|
};
|
||||||
|
orderDirection: OrderDirection;
|
||||||
|
pageNumber: number;
|
||||||
|
endReached: boolean;
|
||||||
|
setOrderDirection: (orderDirection: OrderDirection) => void;
|
||||||
|
setPageNumber: (pageNumber: number) => void;
|
||||||
|
setEndReached: (isEndReaced: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ProviderProps = {
|
export type ProviderProps = {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Skeleton } from '@/components';
|
import { Button, Flex, Skeleton, Text } from '@/components';
|
||||||
import { styled } from '@/theme';
|
import { styled } from '@/theme';
|
||||||
|
|
||||||
const Spacing = '$5';
|
const Spacing = '$6';
|
||||||
|
|
||||||
export const IndexedNFAStyles = {
|
export const IndexedNFAStyles = {
|
||||||
Grid: styled('div', {
|
Grid: styled('div', {
|
||||||
|
|
@ -16,9 +16,11 @@ export const IndexedNFAStyles = {
|
||||||
gridTemplateColumns: '20rem 1fr',
|
gridTemplateColumns: '20rem 1fr',
|
||||||
},
|
},
|
||||||
|
|
||||||
'@media (max-width: 580px)': {
|
'@media (max-width: 640px)': {
|
||||||
gridTemplateAreas: '"aside" "main"',
|
gridTemplateAreas: '"aside" "main"',
|
||||||
gridTemplateColumns: '1fr',
|
gridTemplateColumns: '1fr',
|
||||||
|
justifyItems: 'center',
|
||||||
|
padding: '0',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|
@ -32,34 +34,110 @@ export const IndexedNFAStyles = {
|
||||||
gap: Spacing,
|
gap: Spacing,
|
||||||
height: 'fit-content',
|
height: 'fit-content',
|
||||||
|
|
||||||
'@media (max-width: 580px)': {
|
borderRadius: '$lg',
|
||||||
|
padding: Spacing,
|
||||||
|
maxWidth: '24rem',
|
||||||
|
mixBlendMode: 'screen',
|
||||||
|
|
||||||
|
'@media (max-width: 640px)': {
|
||||||
position: 'static',
|
position: 'static',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
Header: {
|
||||||
|
Wrapper: styled(Flex, {
|
||||||
|
flexDirection: 'column',
|
||||||
|
gap: '$2h',
|
||||||
|
color: '$slate12',
|
||||||
|
}),
|
||||||
|
Container: styled(Flex, {
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
}),
|
||||||
|
Header: styled('h1', {
|
||||||
|
fontSize: '2.125rem',
|
||||||
|
lineHeight: 1.35,
|
||||||
|
fontWeight: 700,
|
||||||
|
|
||||||
CreateAccessPoint: {
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
}),
|
||||||
|
Badge: styled('span', {
|
||||||
|
height: 'fit-content',
|
||||||
|
width: 'fit-content',
|
||||||
|
fontSize: '$xs',
|
||||||
|
fontWeight: '$bold',
|
||||||
|
padding: '$0h $2',
|
||||||
|
borderRadius: '$full',
|
||||||
|
backgroundColor: '#131313',
|
||||||
|
display: 'flex',
|
||||||
|
gap: '$1h',
|
||||||
|
|
||||||
|
variants: {
|
||||||
|
verified: {
|
||||||
|
true: {
|
||||||
|
color: '$green10',
|
||||||
|
},
|
||||||
|
false: {
|
||||||
|
color: '$red10',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
Divider: {
|
||||||
|
Line: styled('span', {
|
||||||
|
width: '100%',
|
||||||
|
borderBottom: '1px solid $slate6',
|
||||||
|
}),
|
||||||
|
Elipse: styled('span', {
|
||||||
|
width: '0.375rem',
|
||||||
|
height: '0.375rem',
|
||||||
|
backgroundColor: '$slate8',
|
||||||
|
borderRadius: '100%',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
Button: {
|
||||||
|
Container: styled(Flex, {
|
||||||
|
gap: '$3',
|
||||||
|
fontSize: '16px',
|
||||||
|
|
||||||
|
[`${Button}`]: {
|
||||||
|
borderRadius: '0.375rem',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
Overview: {
|
||||||
Container: styled('div', {
|
Container: styled('div', {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
gap: Spacing,
|
backgroundColor: 'rgba(255, 255, 255, 0.06)',
|
||||||
padding: Spacing,
|
|
||||||
backgroundColor: '$blue1',
|
|
||||||
borderRadius: '$lg',
|
borderRadius: '$lg',
|
||||||
|
fontSize: '14px',
|
||||||
}),
|
}),
|
||||||
Heading: styled('h2', {
|
Row: {
|
||||||
fontSize: '$md',
|
Container: styled(Flex, {
|
||||||
color: '$slate12',
|
justifyContent: 'space-between',
|
||||||
}),
|
}),
|
||||||
Text: styled('p', {
|
Label: styled(Text, {
|
||||||
fontSize: '$sm',
|
color: '$slate11',
|
||||||
|
}),
|
||||||
|
Value: styled(Text, {
|
||||||
|
fontWeight: '$bold',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
Description: styled('p', {
|
||||||
color: '$slate11',
|
color: '$slate11',
|
||||||
|
overflowY: 'scroll',
|
||||||
|
pr: '1rem',
|
||||||
}),
|
}),
|
||||||
Extra: styled('a', {
|
},
|
||||||
|
Properties: {
|
||||||
|
Container: styled('div', {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
flexDirection: 'column',
|
||||||
color: '$slate11',
|
gap: '$1',
|
||||||
fontSize: '$sm',
|
padding: '$2h $4',
|
||||||
gap: '$2',
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -70,169 +148,61 @@ export const IndexedNFAStyles = {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
gap: Spacing,
|
gap: Spacing,
|
||||||
|
width: '100%',
|
||||||
}),
|
}),
|
||||||
Heading: styled('h1', {
|
Heading: styled('h2', {
|
||||||
fontSize: '2.125rem',
|
fontSize: '1.625rem',
|
||||||
lineHeight: 1.35,
|
lineHeight: 1.35,
|
||||||
fontWeight: 700,
|
fontWeight: 700,
|
||||||
}),
|
}),
|
||||||
SectionHeading: styled('h2', {
|
AccessPoint: {
|
||||||
fontSize: '$xl',
|
List: styled('div', {
|
||||||
lineHeight: 1.2,
|
display: 'flex',
|
||||||
fontWeight: 700,
|
flexDirection: 'column',
|
||||||
marginTop: Spacing,
|
gap: Spacing,
|
||||||
}),
|
}),
|
||||||
|
Grid: styled('div', {
|
||||||
|
display: 'grid',
|
||||||
|
gridTemplateAreas: '"thumbnail data"',
|
||||||
|
gap: '$4h',
|
||||||
|
alignItems: 'center',
|
||||||
|
gridTemplateColumns: '7rem 1fr',
|
||||||
|
}),
|
||||||
|
Thumbnail: styled('div', {
|
||||||
|
gridArea: 'thumbnail',
|
||||||
|
}),
|
||||||
|
Data: {
|
||||||
|
Container: styled('div', {
|
||||||
|
gridArea: 'data',
|
||||||
|
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
gap: '$2',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
Title: styled('h3', {
|
||||||
|
color: '$slate12',
|
||||||
|
fontSize: '$lg',
|
||||||
|
}),
|
||||||
|
NoResults: styled('div', {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
|
||||||
|
fontSize: '$lg',
|
||||||
|
}),
|
||||||
|
},
|
||||||
Divider: {
|
Divider: {
|
||||||
Line: styled('span', {
|
Line: styled('span', {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
borderBottom: '1px solid $slate6',
|
borderBottom: '1px solid $slate6',
|
||||||
}),
|
}),
|
||||||
Elipse: styled('span', {
|
Elipse: styled('span', {
|
||||||
width: '0.375rem',
|
minWidth: '0.375rem',
|
||||||
height: '0.375rem',
|
minHeight: '0.375rem',
|
||||||
backgroundColor: '$slate4',
|
backgroundColor: '$slate11',
|
||||||
borderRadius: '100%',
|
borderRadius: '100%',
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
Paragraph: styled('p', {
|
|
||||||
color: '$slate11',
|
|
||||||
lineHeight: 1.43,
|
|
||||||
}),
|
|
||||||
DataContainer: styled('div', {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
border: '1px solid $slate6',
|
|
||||||
borderRadius: '$lg',
|
|
||||||
padding: Spacing,
|
|
||||||
gap: `$1`,
|
|
||||||
}),
|
|
||||||
DataList: styled('div', {
|
|
||||||
display: 'flex',
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
gap: '$5',
|
|
||||||
}),
|
|
||||||
VerificationBanner: styled('div', {
|
|
||||||
position: 'relative',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
border: '1px solid $slate6',
|
|
||||||
borderRadius: '$lg',
|
|
||||||
padding: '$8 $5',
|
|
||||||
fontWeight: 700,
|
|
||||||
overflow: 'hidden',
|
|
||||||
|
|
||||||
'&:after': {
|
|
||||||
content: '""',
|
|
||||||
position: 'absolute',
|
|
||||||
right: '-$5',
|
|
||||||
top: '-$10',
|
|
||||||
bottom: '-$10',
|
|
||||||
left: '84%',
|
|
||||||
borderRadius: '80% 0 0 80%',
|
|
||||||
},
|
|
||||||
|
|
||||||
variants: {
|
|
||||||
verified: {
|
|
||||||
true: {
|
|
||||||
borderColor: '$green11',
|
|
||||||
color: '$green11',
|
|
||||||
'&:after': {
|
|
||||||
backgroundColor: '$green11',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
false: {
|
|
||||||
borderColor: '$red11',
|
|
||||||
color: '$red11',
|
|
||||||
'&:after': {
|
|
||||||
backgroundColor: '$red11',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
Table: {
|
|
||||||
Container: styled('div', {
|
|
||||||
border: '1px solid $slate6',
|
|
||||||
borderRadius: '10px',
|
|
||||||
padding: '0 $5',
|
|
||||||
|
|
||||||
maxHeight: '15.125rem',
|
|
||||||
overflow: 'auto',
|
|
||||||
}),
|
|
||||||
Root: styled('table', {
|
|
||||||
width: 'calc(100% + 2 * $space$5)',
|
|
||||||
margin: '0 -$5',
|
|
||||||
}),
|
|
||||||
Head: styled('thead', {
|
|
||||||
position: 'sticky',
|
|
||||||
top: 0,
|
|
||||||
backgroundColor: '$black',
|
|
||||||
|
|
||||||
'&:after': {
|
|
||||||
position: 'absolute',
|
|
||||||
content: '""',
|
|
||||||
bottom: 0,
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
borderBottom: '1px solid $slate6',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
Row: styled('tr'),
|
|
||||||
Data: styled('td', {
|
|
||||||
padding: '$3',
|
|
||||||
maxWidth: '10rem',
|
|
||||||
overflow: 'hidden',
|
|
||||||
textOverflow: 'ellipsis',
|
|
||||||
whiteSpace: 'nowrap',
|
|
||||||
}),
|
|
||||||
Body: styled('tbody', {
|
|
||||||
tr: {
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: '$slate6',
|
|
||||||
cursor: 'pointer',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
Marker: styled('span', {
|
|
||||||
display: 'block',
|
|
||||||
margin: 'auto',
|
|
||||||
width: '0.5625rem',
|
|
||||||
height: '0.5625rem',
|
|
||||||
borderRadius: '$full',
|
|
||||||
backgroundColor: '$slate6',
|
|
||||||
|
|
||||||
variants: {
|
|
||||||
variant: {
|
|
||||||
active: {
|
|
||||||
backgroundColor: '$green11',
|
|
||||||
},
|
|
||||||
inactive: {
|
|
||||||
backgroundColor: '$slate8',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
text: {
|
|
||||||
true: {
|
|
||||||
fontSize: '$xs',
|
|
||||||
padding: '0 $2',
|
|
||||||
width: 'fit-content',
|
|
||||||
height: 'fit-content',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
compoundVariants: [
|
|
||||||
{
|
|
||||||
variant: 'active',
|
|
||||||
text: true,
|
|
||||||
css: {
|
|
||||||
color: '$green11',
|
|
||||||
backgroundColor: '$green3',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
Skeleton: styled(Skeleton, {
|
Skeleton: styled(Skeleton, {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import { ethers } from 'ethers';
|
import { ethers } from 'ethers';
|
||||||
|
import { useEffect } from 'react';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { App } from '@/app.context';
|
||||||
import { getNFADetailDocument } from '@/graphclient';
|
import { getNFADetailDocument } from '@/graphclient';
|
||||||
import { AppLog } from '@/utils';
|
import { AppLog } from '@/utils';
|
||||||
|
import { parseNumberToHexColor } from '@/utils/color';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
IndexedNFAAsideFragment,
|
IndexedNFAAsideFragment,
|
||||||
|
|
@ -15,8 +18,15 @@ import { IndexedNFAStyles as S } from './indexed-nfa.styles';
|
||||||
|
|
||||||
export const IndexedNFAView: React.FC = () => {
|
export const IndexedNFAView: React.FC = () => {
|
||||||
const { id } = useParams<{ id: string }>();
|
const { id } = useParams<{ id: string }>();
|
||||||
|
const { setBackgroundColor } = App.useContext();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
setBackgroundColor('000000');
|
||||||
|
};
|
||||||
|
}, [setBackgroundColor]);
|
||||||
|
|
||||||
const handleError = (error: unknown): void => {
|
const handleError = (error: unknown): void => {
|
||||||
AppLog.errorToast(
|
AppLog.errorToast(
|
||||||
`It was not possible to find the NFA with id "${id}"`,
|
`It was not possible to find the NFA with id "${id}"`,
|
||||||
|
|
@ -32,6 +42,8 @@ export const IndexedNFAView: React.FC = () => {
|
||||||
},
|
},
|
||||||
onCompleted(data) {
|
onCompleted(data) {
|
||||||
if (!data.token) handleError(new Error('Token not found'));
|
if (!data.token) handleError(new Error('Token not found'));
|
||||||
|
if (data.token?.color)
|
||||||
|
setBackgroundColor(parseNumberToHexColor(data.token.color));
|
||||||
},
|
},
|
||||||
onError(error) {
|
onError(error) {
|
||||||
handleError(error);
|
handleError(error);
|
||||||
|
|
@ -42,11 +54,6 @@ export const IndexedNFAView: React.FC = () => {
|
||||||
return <IndexedNFASkeletonFragment />;
|
return <IndexedNFASkeletonFragment />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data.token) {
|
|
||||||
//TODO add 404 page
|
|
||||||
return <div>Token not found</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<IndexedNFA.Provider nfa={data.token}>
|
<IndexedNFA.Provider nfa={data.token}>
|
||||||
<S.Grid>
|
<S.Grid>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './tabs';
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { Flex } from '@/components';
|
||||||
|
import { styled } from '@/theme';
|
||||||
|
|
||||||
|
export const TabsStyles = {
|
||||||
|
Container: styled(Flex, {
|
||||||
|
width: '100%',
|
||||||
|
}),
|
||||||
|
Tab: {
|
||||||
|
Container: styled(Flex, {
|
||||||
|
flexDirection: 'column',
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'center',
|
||||||
|
cursor: 'pointer',
|
||||||
|
|
||||||
|
variants: {
|
||||||
|
active: {
|
||||||
|
true: {
|
||||||
|
color: 'white',
|
||||||
|
},
|
||||||
|
false: {
|
||||||
|
color: '$slate8',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
Label: styled('span', {
|
||||||
|
padding: '$2h',
|
||||||
|
}),
|
||||||
|
Line: styled('span', {
|
||||||
|
width: '100%',
|
||||||
|
borderRadius: '3px',
|
||||||
|
|
||||||
|
variants: {
|
||||||
|
active: {
|
||||||
|
true: {
|
||||||
|
color: 'white',
|
||||||
|
borderBottom: '3px solid white',
|
||||||
|
},
|
||||||
|
false: {
|
||||||
|
color: '$slate8',
|
||||||
|
borderBottom: '2px solid $slate8',
|
||||||
|
mt: '0.046875rem',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { forwardStyledRef } from '@/theme';
|
||||||
|
|
||||||
|
import { TabsStyles as S } from './tabs.styles';
|
||||||
|
|
||||||
|
type TabProps = {
|
||||||
|
label: string;
|
||||||
|
index: number;
|
||||||
|
onTabClick: (index: number) => void;
|
||||||
|
} & React.ComponentPropsWithRef<typeof S.Tab.Container>;
|
||||||
|
|
||||||
|
export const Tab = forwardStyledRef<HTMLDivElement, TabProps>(
|
||||||
|
({ label, index, onTabClick, ...props }, ref) => {
|
||||||
|
const { active } = props;
|
||||||
|
const handleClick = (): void => {
|
||||||
|
onTabClick(index);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<S.Tab.Container ref={ref} {...props} onClick={handleClick}>
|
||||||
|
<S.Tab.Label>{label}</S.Tab.Label>
|
||||||
|
<S.Tab.Line active={active} />
|
||||||
|
</S.Tab.Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
type TabContainerProps = {
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TabContainer: React.FC<TabContainerProps> = ({
|
||||||
|
children,
|
||||||
|
}: TabContainerProps) => {
|
||||||
|
return <S.Container>{children}</S.Container>;
|
||||||
|
};
|
||||||
|
|
@ -6,7 +6,7 @@ import { useGithubStore } from '@/store';
|
||||||
import { Mint } from '@/views/mint/mint.context';
|
import { Mint } from '@/views/mint/mint.context';
|
||||||
|
|
||||||
import { GithubRepositorySelectionStyles as S } from './github-repository-selection.styles';
|
import { GithubRepositorySelectionStyles as S } from './github-repository-selection.styles';
|
||||||
import { RepositoriesList } from './repositories-list';
|
import { RepositoriesListFragment } from './repositories-list';
|
||||||
import { UserOrgsCombobox } from './users-orgs-combobox';
|
import { UserOrgsCombobox } from './users-orgs-combobox';
|
||||||
|
|
||||||
export const Loading: React.FC = () => (
|
export const Loading: React.FC = () => (
|
||||||
|
|
@ -68,7 +68,7 @@ export const GithubRepositoryConnection: React.FC = () => {
|
||||||
queryUserAndOrganizations === 'loading' ? (
|
queryUserAndOrganizations === 'loading' ? (
|
||||||
<Loading />
|
<Loading />
|
||||||
) : (
|
) : (
|
||||||
<RepositoriesList searchValue={searchValue} />
|
<RepositoriesListFragment searchValue={searchValue} />
|
||||||
)}
|
)}
|
||||||
</S.Container>
|
</S.Container>
|
||||||
</S.Card.Body>
|
</S.Card.Body>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './repositories-list.fragment';
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
import { useEffect, useMemo } from 'react';
|
import { useEffect, useMemo } from 'react';
|
||||||
|
|
||||||
import { Flex } from '@/components';
|
|
||||||
import { githubActions, useAppDispatch, useGithubStore } from '@/store';
|
import { githubActions, useAppDispatch, useGithubStore } from '@/store';
|
||||||
import { Mint } from '@/views/mint/mint.context';
|
import { Mint } from '@/views/mint/mint.context';
|
||||||
|
|
||||||
|
import { RepositoiresListStyles as S } from './repositories-list.styles';
|
||||||
import { Repository } from './repository';
|
import { Repository } from './repository';
|
||||||
|
|
||||||
type RepositoriesListProps = {
|
type RepositoriesListProps = {
|
||||||
searchValue: string;
|
searchValue: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const RepositoriesList: React.FC<RepositoriesListProps> = ({
|
export const RepositoriesListFragment: React.FC<RepositoriesListProps> = ({
|
||||||
searchValue,
|
searchValue,
|
||||||
}: RepositoriesListProps) => {
|
}: RepositoriesListProps) => {
|
||||||
const { selectedUserOrg } = Mint.useContext();
|
const { selectedUserOrg } = Mint.useContext();
|
||||||
|
|
@ -37,15 +37,7 @@ export const RepositoriesList: React.FC<RepositoriesListProps> = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<S.Container>
|
||||||
css={{
|
|
||||||
height: '$60',
|
|
||||||
overflowX: 'hidden',
|
|
||||||
overflowY: 'scroll',
|
|
||||||
flexDirection: 'column',
|
|
||||||
pr: '$3h',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{filteredRepositories.length > 0 ? (
|
{filteredRepositories.length > 0 ? (
|
||||||
filteredRepositories.map((repo, index, { length }) => (
|
filteredRepositories.map((repo, index, { length }) => (
|
||||||
<Repository
|
<Repository
|
||||||
|
|
@ -57,12 +49,8 @@ export const RepositoriesList: React.FC<RepositoriesListProps> = ({
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
// TODO: update this after designs are done
|
// TODO: update this after designs are done
|
||||||
<div
|
<S.Message>Nothing found.</S.Message>
|
||||||
className={`relative cursor-default select-none pt-2 px-3.5 pb-4 text-slate11 text-center`}
|
|
||||||
>
|
|
||||||
Nothing found.
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</Flex>
|
</S.Container>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { Flex } from '@/components';
|
||||||
|
import { styled } from '@/theme';
|
||||||
|
|
||||||
|
export const RepositoiresListStyles = {
|
||||||
|
Container: styled(Flex, {
|
||||||
|
height: '$60',
|
||||||
|
overflowX: 'hidden',
|
||||||
|
overflowY: 'scroll',
|
||||||
|
flexDirection: 'column',
|
||||||
|
pr: '$3h',
|
||||||
|
}),
|
||||||
|
Message: styled('div', {
|
||||||
|
position: 'relative',
|
||||||
|
cursor: 'default',
|
||||||
|
userSelect: 'none',
|
||||||
|
p: '$2 $3h $4 $3h',
|
||||||
|
color: '$slate11',
|
||||||
|
textAlign: 'center',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
@ -5,16 +5,11 @@ export const MintStyles = {
|
||||||
Container: styled(Flex, {
|
Container: styled(Flex, {
|
||||||
height: '100%',
|
height: '100%',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
|
minHeight: '85vh',
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
|
||||||
'@md': {
|
'@md': {
|
||||||
//to align on center
|
alignItems: 'center',
|
||||||
position: 'absolute',
|
|
||||||
top: '50%',
|
|
||||||
transform: 'translateY(-50%)',
|
|
||||||
},
|
|
||||||
|
|
||||||
'@lg': {
|
|
||||||
flexDirection: 'row',
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ export const VerifyNfaStepStyles = {
|
||||||
Text: styled(Text, {
|
Text: styled(Text, {
|
||||||
color: '$slate11',
|
color: '$slate11',
|
||||||
fontSize: '$sm',
|
fontSize: '$sm',
|
||||||
|
lineHeight: '1.25rem',
|
||||||
}),
|
}),
|
||||||
VerifyContainer: styled(Card.Text, {
|
VerifyContainer: styled(Card.Text, {
|
||||||
p: '$4',
|
p: '$4',
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ export const NftCard: React.FC<NftCardProps> = ({
|
||||||
onClick,
|
onClick,
|
||||||
isLoading,
|
isLoading,
|
||||||
}: NftCardProps) => {
|
}: NftCardProps) => {
|
||||||
const size = '26.5rem';
|
const size = '100%';
|
||||||
const {
|
const {
|
||||||
form: {
|
form: {
|
||||||
appName: {
|
appName: {
|
||||||
|
|
@ -48,7 +48,15 @@ export const NftCard: React.FC<NftCardProps> = ({
|
||||||
} = useMintFormContext();
|
} = useMintFormContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomCardContainer css={{ p: '$0' }}>
|
<CustomCardContainer
|
||||||
|
css={{
|
||||||
|
p: '$0',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
padding: 0,
|
||||||
|
overflow: 'hidden',
|
||||||
|
}}
|
||||||
|
>
|
||||||
<NFAPreview
|
<NFAPreview
|
||||||
color={logoColor}
|
color={logoColor}
|
||||||
logo={appLogo}
|
logo={appLogo}
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,29 @@
|
||||||
import { ConnectKitButton } from 'connectkit';
|
import { ConnectKitButton } from 'connectkit';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import { useAccount } from 'wagmi';
|
||||||
|
|
||||||
import { Stepper } from '@/components';
|
import { Stepper } from '@/components';
|
||||||
|
|
||||||
import { ButtonConnection } from '../button-connection';
|
import { ButtonConnection } from '../button-connection';
|
||||||
|
|
||||||
export const ConnectWalletButton: React.FC = () => {
|
export const ConnectWalletButton: React.FC = () => {
|
||||||
|
const { address } = useAccount();
|
||||||
const { nextStep } = Stepper.useContext();
|
const { nextStep } = Stepper.useContext();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (address) nextStep();
|
||||||
|
}, [address, nextStep]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConnectKitButton.Custom>
|
<ConnectKitButton.Custom>
|
||||||
{({ isConnected, show, address }) => {
|
{({ show }) => {
|
||||||
if (isConnected && address) {
|
return (
|
||||||
nextStep();
|
<ButtonConnection
|
||||||
} else {
|
icon={'ethereum'}
|
||||||
return (
|
label={'Connect Wallet'}
|
||||||
<ButtonConnection
|
onClick={show}
|
||||||
icon={'ethereum'}
|
/>
|
||||||
label={'Connect Wallet'}
|
);
|
||||||
onClick={show}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
</ConnectKitButton.Custom>
|
</ConnectKitButton.Custom>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
/* eslint-disable no-undef */
|
|
||||||
/** @type {import('tailwindcss').Config} */
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
content: ['./src/**/*.tsx'],
|
|
||||||
safelist: [
|
|
||||||
{
|
|
||||||
pattern: /(bg|border|text)-(slate)(4|11|12)/,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
pattern: /w-(0|[1-9][0-9]?|100)/,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
theme: {
|
|
||||||
extend: {
|
|
||||||
colors: {
|
|
||||||
//TODO if we're gonna have ligth mode we should add also the light colors cause tailwind doesn't have them
|
|
||||||
slate4: 'rgba(38, 41, 43, 1)',
|
|
||||||
slate5: 'rgba(43, 47, 49, 1)',
|
|
||||||
slate6: 'rgba(49, 53, 56, 1)',
|
|
||||||
slate7: 'rgba(58, 63, 66, 1)',
|
|
||||||
slate11: 'rgba(155, 161, 166, 1)',
|
|
||||||
slate12: 'rgba(236, 237, 238, 1)',
|
|
||||||
green4: 'rgba(17, 49, 35, 1)',
|
|
||||||
green11: 'rgba(76, 195, 138, 1)',
|
|
||||||
red4: 'rgba(72, 26, 29, 1)',
|
|
||||||
red9: 'rgba(229, 72, 77, 1)',
|
|
||||||
red11: 'rgba(255, 99, 105, 1)',
|
|
||||||
},
|
|
||||||
borderRadius: {
|
|
||||||
xhl: '1.25rem',
|
|
||||||
},
|
|
||||||
maxWidth: {
|
|
||||||
70: '70%',
|
|
||||||
},
|
|
||||||
space: {
|
|
||||||
'1h': '0.375rem',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: [],
|
|
||||||
};
|
|
||||||
200
ui/yarn.lock
200
ui/yarn.lock
|
|
@ -4037,30 +4037,11 @@ acorn-jsx@^5.3.2:
|
||||||
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
|
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
|
||||||
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
||||||
|
|
||||||
acorn-node@^1.8.2:
|
|
||||||
version "1.8.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8"
|
|
||||||
integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==
|
|
||||||
dependencies:
|
|
||||||
acorn "^7.0.0"
|
|
||||||
acorn-walk "^7.0.0"
|
|
||||||
xtend "^4.0.2"
|
|
||||||
|
|
||||||
acorn-walk@^7.0.0:
|
|
||||||
version "7.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
|
|
||||||
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
|
|
||||||
|
|
||||||
acorn-walk@^8.1.1:
|
acorn-walk@^8.1.1:
|
||||||
version "8.2.0"
|
version "8.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
|
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
|
||||||
integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
|
integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
|
||||||
|
|
||||||
acorn@^7.0.0:
|
|
||||||
version "7.4.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
|
|
||||||
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
|
|
||||||
|
|
||||||
acorn@^8.4.1, acorn@^8.8.0:
|
acorn@^8.4.1, acorn@^8.8.0:
|
||||||
version "8.8.2"
|
version "8.8.2"
|
||||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
|
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
|
||||||
|
|
@ -4190,11 +4171,6 @@ arg@^4.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
|
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
|
||||||
integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
|
integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
|
||||||
|
|
||||||
arg@^5.0.2:
|
|
||||||
version "5.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
|
|
||||||
integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==
|
|
||||||
|
|
||||||
argparse@^2.0.1:
|
argparse@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
|
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
|
||||||
|
|
@ -4310,18 +4286,6 @@ auto-bind@~4.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-4.0.0.tgz#e3589fc6c2da8f7ca43ba9f84fa52a744fc997fb"
|
resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-4.0.0.tgz#e3589fc6c2da8f7ca43ba9f84fa52a744fc997fb"
|
||||||
integrity sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==
|
integrity sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==
|
||||||
|
|
||||||
autoprefixer@^10.4.13:
|
|
||||||
version "10.4.13"
|
|
||||||
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.13.tgz#b5136b59930209a321e9fa3dca2e7c4d223e83a8"
|
|
||||||
integrity sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==
|
|
||||||
dependencies:
|
|
||||||
browserslist "^4.21.4"
|
|
||||||
caniuse-lite "^1.0.30001426"
|
|
||||||
fraction.js "^4.2.0"
|
|
||||||
normalize-range "^0.1.2"
|
|
||||||
picocolors "^1.0.0"
|
|
||||||
postcss-value-parser "^4.2.0"
|
|
||||||
|
|
||||||
available-typed-arrays@^1.0.5:
|
available-typed-arrays@^1.0.5:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7"
|
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7"
|
||||||
|
|
@ -4655,7 +4619,7 @@ browserify-zlib@^0.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
pako "~1.0.5"
|
pako "~1.0.5"
|
||||||
|
|
||||||
browserslist@^4.21.3, browserslist@^4.21.4, browserslist@^4.21.5:
|
browserslist@^4.21.3, browserslist@^4.21.5:
|
||||||
version "4.21.5"
|
version "4.21.5"
|
||||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7"
|
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7"
|
||||||
integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==
|
integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==
|
||||||
|
|
@ -4781,11 +4745,6 @@ camel-case@4.1.2, camel-case@^4.1.2:
|
||||||
pascal-case "^3.1.2"
|
pascal-case "^3.1.2"
|
||||||
tslib "^2.0.3"
|
tslib "^2.0.3"
|
||||||
|
|
||||||
camelcase-css@^2.0.1:
|
|
||||||
version "2.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5"
|
|
||||||
integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
|
|
||||||
|
|
||||||
camelcase@^5.0.0:
|
camelcase@^5.0.0:
|
||||||
version "5.3.1"
|
version "5.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
|
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
|
||||||
|
|
@ -4801,7 +4760,7 @@ camelize@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.1.tgz#89b7e16884056331a35d6b5ad064332c91daa6c3"
|
resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.1.tgz#89b7e16884056331a35d6b5ad064332c91daa6c3"
|
||||||
integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==
|
integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==
|
||||||
|
|
||||||
caniuse-lite@^1.0.30001426, caniuse-lite@^1.0.30001449:
|
caniuse-lite@^1.0.30001449:
|
||||||
version "1.0.30001462"
|
version "1.0.30001462"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001462.tgz#b2e801e37536d453731286857c8520d3dcee15fe"
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001462.tgz#b2e801e37536d453731286857c8520d3dcee15fe"
|
||||||
integrity sha512-PDd20WuOBPiasZ7KbFnmQRyuLE7cFXW2PVd7dmALzbkUXEP46upAuCDm9eY9vho8fgNMGmbAX92QBZHzcnWIqw==
|
integrity sha512-PDd20WuOBPiasZ7KbFnmQRyuLE7cFXW2PVd7dmALzbkUXEP46upAuCDm9eY9vho8fgNMGmbAX92QBZHzcnWIqw==
|
||||||
|
|
@ -4905,7 +4864,7 @@ check-error@^1.0.2:
|
||||||
resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
|
resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
|
||||||
integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==
|
integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==
|
||||||
|
|
||||||
chokidar@3.5.3, chokidar@^3.5.3:
|
chokidar@3.5.3:
|
||||||
version "3.5.3"
|
version "3.5.3"
|
||||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
|
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
|
||||||
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
|
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
|
||||||
|
|
@ -5003,7 +4962,7 @@ color-name@1.1.3:
|
||||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
|
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
|
||||||
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
|
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
|
||||||
|
|
||||||
color-name@^1.1.4, color-name@~1.1.4:
|
color-name@~1.1.4:
|
||||||
version "1.1.4"
|
version "1.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||||
|
|
@ -5198,11 +5157,6 @@ css-to-react-native@^3.0.0:
|
||||||
css-color-keywords "^1.0.0"
|
css-color-keywords "^1.0.0"
|
||||||
postcss-value-parser "^4.0.2"
|
postcss-value-parser "^4.0.2"
|
||||||
|
|
||||||
cssesc@^3.0.0:
|
|
||||||
version "3.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
|
|
||||||
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
|
|
||||||
|
|
||||||
csstype@^3.0.2:
|
csstype@^3.0.2:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9"
|
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9"
|
||||||
|
|
@ -5304,11 +5258,6 @@ define-properties@^1.1.3, define-properties@^1.1.4:
|
||||||
has-property-descriptors "^1.0.0"
|
has-property-descriptors "^1.0.0"
|
||||||
object-keys "^1.1.1"
|
object-keys "^1.1.1"
|
||||||
|
|
||||||
defined@^1.0.0:
|
|
||||||
version "1.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf"
|
|
||||||
integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==
|
|
||||||
|
|
||||||
delay@^5.0.0:
|
delay@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d"
|
resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d"
|
||||||
|
|
@ -5357,20 +5306,6 @@ detect-node@^2.0.4, detect-node@^2.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1"
|
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1"
|
||||||
integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==
|
integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==
|
||||||
|
|
||||||
detective@^5.2.1:
|
|
||||||
version "5.2.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.1.tgz#6af01eeda11015acb0e73f933242b70f24f91034"
|
|
||||||
integrity sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==
|
|
||||||
dependencies:
|
|
||||||
acorn-node "^1.8.2"
|
|
||||||
defined "^1.0.0"
|
|
||||||
minimist "^1.2.6"
|
|
||||||
|
|
||||||
didyoumean@^1.2.2:
|
|
||||||
version "1.2.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"
|
|
||||||
integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==
|
|
||||||
|
|
||||||
diff-sequences@^29.4.3:
|
diff-sequences@^29.4.3:
|
||||||
version "29.4.3"
|
version "29.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.4.3.tgz#9314bc1fabe09267ffeca9cbafc457d8499a13f2"
|
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.4.3.tgz#9314bc1fabe09267ffeca9cbafc457d8499a13f2"
|
||||||
|
|
@ -5407,11 +5342,6 @@ dir-glob@^3.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
path-type "^4.0.0"
|
path-type "^4.0.0"
|
||||||
|
|
||||||
dlv@^1.1.3:
|
|
||||||
version "1.1.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79"
|
|
||||||
integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==
|
|
||||||
|
|
||||||
dnscache@1.0.2:
|
dnscache@1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/dnscache/-/dnscache-1.0.2.tgz#fd3c24d66c141625f594c77be7a8dafee2a66c8a"
|
resolved "https://registry.yarnpkg.com/dnscache/-/dnscache-1.0.2.tgz#fd3c24d66c141625f594c77be7a8dafee2a66c8a"
|
||||||
|
|
@ -6128,7 +6058,7 @@ fast-diff@^1.1.2:
|
||||||
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
|
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
|
||||||
integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
|
integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
|
||||||
|
|
||||||
fast-glob@^3.2.12, fast-glob@^3.2.9:
|
fast-glob@^3.2.9:
|
||||||
version "3.2.12"
|
version "3.2.12"
|
||||||
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
|
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
|
||||||
integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==
|
integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==
|
||||||
|
|
@ -6367,11 +6297,6 @@ formik@^2.2.9:
|
||||||
tiny-warning "^1.0.2"
|
tiny-warning "^1.0.2"
|
||||||
tslib "^1.10.0"
|
tslib "^1.10.0"
|
||||||
|
|
||||||
fraction.js@^4.2.0:
|
|
||||||
version "4.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950"
|
|
||||||
integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==
|
|
||||||
|
|
||||||
framer-motion@^6.3.11:
|
framer-motion@^6.3.11:
|
||||||
version "6.5.1"
|
version "6.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-6.5.1.tgz#802448a16a6eb764124bf36d8cbdfa6dd6b931a7"
|
resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-6.5.1.tgz#802448a16a6eb764124bf36d8cbdfa6dd6b931a7"
|
||||||
|
|
@ -7390,11 +7315,6 @@ lie@3.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
immediate "~3.0.5"
|
immediate "~3.0.5"
|
||||||
|
|
||||||
lilconfig@^2.0.5, lilconfig@^2.0.6:
|
|
||||||
version "2.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52"
|
|
||||||
integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==
|
|
||||||
|
|
||||||
lines-and-columns@^1.1.6:
|
lines-and-columns@^1.1.6:
|
||||||
version "1.2.4"
|
version "1.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
|
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
|
||||||
|
|
@ -7630,7 +7550,7 @@ meros@^1.2.1:
|
||||||
resolved "https://registry.yarnpkg.com/meros/-/meros-1.2.1.tgz#056f7a76e8571d0aaf3c7afcbe7eb6407ff7329e"
|
resolved "https://registry.yarnpkg.com/meros/-/meros-1.2.1.tgz#056f7a76e8571d0aaf3c7afcbe7eb6407ff7329e"
|
||||||
integrity sha512-R2f/jxYqCAGI19KhAvaxSOxALBMkaXWH2a7rOyqQw+ZmizX5bKkEYWLzdhC+U82ZVVPVp6MCXe3EkVligh+12g==
|
integrity sha512-R2f/jxYqCAGI19KhAvaxSOxALBMkaXWH2a7rOyqQw+ZmizX5bKkEYWLzdhC+U82ZVVPVp6MCXe3EkVligh+12g==
|
||||||
|
|
||||||
micromatch@^4.0.0, micromatch@^4.0.4, micromatch@^4.0.5:
|
micromatch@^4.0.0, micromatch@^4.0.4:
|
||||||
version "4.0.5"
|
version "4.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
|
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
|
||||||
integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
|
integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
|
||||||
|
|
@ -7900,11 +7820,6 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||||
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
||||||
|
|
||||||
normalize-range@^0.1.2:
|
|
||||||
version "0.1.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
|
|
||||||
integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
|
|
||||||
|
|
||||||
nullthrows@^1.1.1:
|
nullthrows@^1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1"
|
resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1"
|
||||||
|
|
@ -7920,11 +7835,6 @@ object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||||
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
|
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
|
||||||
|
|
||||||
object-hash@^3.0.0:
|
|
||||||
version "3.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9"
|
|
||||||
integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==
|
|
||||||
|
|
||||||
object-inspect@1.10.3:
|
object-inspect@1.10.3:
|
||||||
version "1.10.3"
|
version "1.10.3"
|
||||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.10.3.tgz#c2aa7d2d09f50c99375704f7a0adf24c5782d369"
|
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.10.3.tgz#c2aa7d2d09f50c99375704f7a0adf24c5782d369"
|
||||||
|
|
@ -8261,11 +8171,6 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.0, picomatc
|
||||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||||
|
|
||||||
pify@^2.3.0:
|
|
||||||
version "2.3.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
|
|
||||||
integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==
|
|
||||||
|
|
||||||
pify@^3.0.0:
|
pify@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
|
resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
|
||||||
|
|
@ -8345,51 +8250,12 @@ popmotion@11.0.3:
|
||||||
style-value-types "5.0.0"
|
style-value-types "5.0.0"
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
postcss-import@^14.1.0:
|
postcss-value-parser@^4.0.2:
|
||||||
version "14.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-14.1.0.tgz#a7333ffe32f0b8795303ee9e40215dac922781f0"
|
|
||||||
integrity sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==
|
|
||||||
dependencies:
|
|
||||||
postcss-value-parser "^4.0.0"
|
|
||||||
read-cache "^1.0.0"
|
|
||||||
resolve "^1.1.7"
|
|
||||||
|
|
||||||
postcss-js@^4.0.0:
|
|
||||||
version "4.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.1.tgz#61598186f3703bab052f1c4f7d805f3991bee9d2"
|
|
||||||
integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==
|
|
||||||
dependencies:
|
|
||||||
camelcase-css "^2.0.1"
|
|
||||||
|
|
||||||
postcss-load-config@^3.1.4:
|
|
||||||
version "3.1.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.4.tgz#1ab2571faf84bb078877e1d07905eabe9ebda855"
|
|
||||||
integrity sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==
|
|
||||||
dependencies:
|
|
||||||
lilconfig "^2.0.5"
|
|
||||||
yaml "^1.10.2"
|
|
||||||
|
|
||||||
postcss-nested@6.0.0:
|
|
||||||
version "6.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.0.0.tgz#1572f1984736578f360cffc7eb7dca69e30d1735"
|
|
||||||
integrity sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==
|
|
||||||
dependencies:
|
|
||||||
postcss-selector-parser "^6.0.10"
|
|
||||||
|
|
||||||
postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.11:
|
|
||||||
version "6.0.11"
|
|
||||||
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz#2e41dc39b7ad74046e1615185185cd0b17d0c8dc"
|
|
||||||
integrity sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==
|
|
||||||
dependencies:
|
|
||||||
cssesc "^3.0.0"
|
|
||||||
util-deprecate "^1.0.2"
|
|
||||||
|
|
||||||
postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.2.0:
|
|
||||||
version "4.2.0"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
|
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
|
||||||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||||
|
|
||||||
postcss@^8.0.9, postcss@^8.4.18, postcss@^8.4.21:
|
postcss@^8.4.18:
|
||||||
version "8.4.21"
|
version "8.4.21"
|
||||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4"
|
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4"
|
||||||
integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==
|
integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==
|
||||||
|
|
@ -8620,11 +8486,6 @@ quick-format-unescaped@^4.0.3:
|
||||||
resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7"
|
resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7"
|
||||||
integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==
|
integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==
|
||||||
|
|
||||||
quick-lru@^5.1.1:
|
|
||||||
version "5.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
|
|
||||||
integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
|
|
||||||
|
|
||||||
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0:
|
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
|
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
|
||||||
|
|
@ -8736,13 +8597,6 @@ react@^18.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
loose-envify "^1.1.0"
|
loose-envify "^1.1.0"
|
||||||
|
|
||||||
read-cache@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774"
|
|
||||||
integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==
|
|
||||||
dependencies:
|
|
||||||
pify "^2.3.0"
|
|
||||||
|
|
||||||
readable-stream@^3.1.1, readable-stream@^3.5.0, readable-stream@^3.6.0:
|
readable-stream@^3.1.1, readable-stream@^3.5.0, readable-stream@^3.6.0:
|
||||||
version "3.6.1"
|
version "3.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.1.tgz#f9f9b5f536920253b3d26e7660e7da4ccff9bb62"
|
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.1.tgz#f9f9b5f536920253b3d26e7660e7da4ccff9bb62"
|
||||||
|
|
@ -8886,7 +8740,7 @@ resolve-from@^4.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
|
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
|
||||||
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
|
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
|
||||||
|
|
||||||
resolve@^1.1.7, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.22.1:
|
resolve@^1.14.2, resolve@^1.17.0, resolve@^1.22.1:
|
||||||
version "1.22.1"
|
version "1.22.1"
|
||||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
|
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
|
||||||
integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
|
integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
|
||||||
|
|
@ -9374,35 +9228,6 @@ symbol-observable@^4.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-4.0.0.tgz#5b425f192279e87f2f9b937ac8540d1984b39205"
|
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-4.0.0.tgz#5b425f192279e87f2f9b937ac8540d1984b39205"
|
||||||
integrity sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==
|
integrity sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==
|
||||||
|
|
||||||
tailwindcss@^3.2.4:
|
|
||||||
version "3.2.7"
|
|
||||||
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.2.7.tgz#5936dd08c250b05180f0944500c01dce19188c07"
|
|
||||||
integrity sha512-B6DLqJzc21x7wntlH/GsZwEXTBttVSl1FtCzC8WP4oBc/NKef7kaax5jeihkkCEWc831/5NDJ9gRNDK6NEioQQ==
|
|
||||||
dependencies:
|
|
||||||
arg "^5.0.2"
|
|
||||||
chokidar "^3.5.3"
|
|
||||||
color-name "^1.1.4"
|
|
||||||
detective "^5.2.1"
|
|
||||||
didyoumean "^1.2.2"
|
|
||||||
dlv "^1.1.3"
|
|
||||||
fast-glob "^3.2.12"
|
|
||||||
glob-parent "^6.0.2"
|
|
||||||
is-glob "^4.0.3"
|
|
||||||
lilconfig "^2.0.6"
|
|
||||||
micromatch "^4.0.5"
|
|
||||||
normalize-path "^3.0.0"
|
|
||||||
object-hash "^3.0.0"
|
|
||||||
picocolors "^1.0.0"
|
|
||||||
postcss "^8.0.9"
|
|
||||||
postcss-import "^14.1.0"
|
|
||||||
postcss-js "^4.0.0"
|
|
||||||
postcss-load-config "^3.1.4"
|
|
||||||
postcss-nested "6.0.0"
|
|
||||||
postcss-selector-parser "^6.0.11"
|
|
||||||
postcss-value-parser "^4.2.0"
|
|
||||||
quick-lru "^5.1.1"
|
|
||||||
resolve "^1.22.1"
|
|
||||||
|
|
||||||
tapable@^2.2.0:
|
tapable@^2.2.0:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
|
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
|
||||||
|
|
@ -9763,7 +9588,7 @@ utf8@^3.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1"
|
resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1"
|
||||||
integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==
|
integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==
|
||||||
|
|
||||||
util-deprecate@^1.0.1, util-deprecate@^1.0.2:
|
util-deprecate@^1.0.1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||||
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
||||||
|
|
@ -10052,11 +9877,6 @@ yallist@^4.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||||
|
|
||||||
yaml@^1.10.2:
|
|
||||||
version "1.10.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
|
||||||
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
|
||||||
|
|
||||||
yargs-parser@20.2.4:
|
yargs-parser@20.2.4:
|
||||||
version "20.2.4"
|
version "20.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54"
|
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue