chore(dashboard-v2): move components from skynet-storybook repo
This commit is contained in:
parent
4871422060
commit
7959328bcb
|
@ -25,6 +25,7 @@
|
|||
"react": "^17.0.1",
|
||||
"react-dom": "^17.0.1",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-use": "^17.3.2",
|
||||
"tailwindcss": "^3.0.22"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
import PropTypes from 'prop-types'
|
||||
|
||||
/**
|
||||
* Primary UI component for user interaction
|
||||
*/
|
||||
export const Button = ({ primary, label, ...props }) => {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={`min-w-button min-h-button rounded-full font-sans uppercase tracking-wide text-button
|
||||
${primary ? 'bg-primary' : 'bg-white border-2 border-black'}`}
|
||||
{...props}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
Button.propTypes = {
|
||||
/**
|
||||
* Is this the principal call to action on the page?
|
||||
*/
|
||||
primary: PropTypes.bool,
|
||||
/**
|
||||
* What background color to use
|
||||
*/
|
||||
backgroundColor: PropTypes.string,
|
||||
/**
|
||||
* Button contents
|
||||
*/
|
||||
label: PropTypes.string.isRequired,
|
||||
/**
|
||||
* Optional click handler
|
||||
*/
|
||||
onClick: PropTypes.func,
|
||||
}
|
||||
|
||||
Button.defaultProps = {
|
||||
primary: false,
|
||||
onClick: undefined,
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
import { Button } from './Button'
|
||||
|
||||
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
|
||||
export default {
|
||||
title: 'SkynetLibrary/Button',
|
||||
component: Button,
|
||||
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
|
||||
argTypes: {
|
||||
backgroundColor: { control: 'color' },
|
||||
},
|
||||
}
|
||||
|
||||
// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
|
||||
const Template = (args) => <Button {...args} />
|
||||
|
||||
export const Primary = Template.bind({})
|
||||
// More on args: https://storybook.js.org/docs/react/writing-stories/args
|
||||
Primary.args = {
|
||||
primary: true,
|
||||
label: 'Button',
|
||||
}
|
||||
|
||||
export const Secondary = Template.bind({})
|
||||
Secondary.args = {
|
||||
label: 'Button',
|
||||
}
|
||||
|
||||
export const Large = Template.bind({})
|
||||
Large.args = {
|
||||
size: 'large',
|
||||
label: 'Button',
|
||||
}
|
||||
|
||||
export const Small = Template.bind({})
|
||||
Small.args = {
|
||||
size: 'small',
|
||||
label: 'Button',
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './Button'
|
|
@ -0,0 +1,65 @@
|
|||
import { useRef, useState } from 'react'
|
||||
import { useClickAway } from 'react-use'
|
||||
import PropTypes from 'prop-types'
|
||||
import styled, { css, keyframes } from 'styled-components'
|
||||
|
||||
import { ChevronDownIcon } from '../Icons'
|
||||
|
||||
const dropDown = keyframes`
|
||||
0% {
|
||||
transform: scaleY(0);
|
||||
}
|
||||
80% {
|
||||
transform: scaleY(1.1);
|
||||
}
|
||||
100% {
|
||||
transform: scaleY(1);
|
||||
}
|
||||
`
|
||||
|
||||
const Container = styled.div.attrs({ className: `relative inline-flex` })``
|
||||
|
||||
const Trigger = styled.button.attrs({
|
||||
className: 'flex items-center',
|
||||
})``
|
||||
|
||||
const TriggerIcon = styled(ChevronDownIcon).attrs({
|
||||
className: 'transition-transform text-primary',
|
||||
})`
|
||||
transform: ${({ open }) => (open ? 'rotateX(180deg)' : 'none')};
|
||||
`
|
||||
|
||||
const Flyout = styled.div.attrs(({ open }) => ({
|
||||
className: `absolute top-full right-0 p-0
|
||||
border rounded border-palette-100
|
||||
bg-white shadow-md shadow-palette-200/50
|
||||
${open ? 'visible' : 'invisible'}`,
|
||||
}))`
|
||||
animation: ${({ open }) =>
|
||||
open
|
||||
? css`
|
||||
${dropDown} 0.1s ease-in-out
|
||||
`
|
||||
: 'none'};
|
||||
`
|
||||
|
||||
export const DropdownMenu = ({ title, children }) => {
|
||||
const [open, setOpen] = useState(false)
|
||||
const menuRef = useRef()
|
||||
|
||||
useClickAway(menuRef, () => setOpen(false))
|
||||
|
||||
return (
|
||||
<Container ref={menuRef}>
|
||||
<Trigger onClick={() => setOpen((open) => !open)}>
|
||||
{title} <TriggerIcon open={open} />
|
||||
</Trigger>
|
||||
<Flyout open={open}>{children}</Flyout>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
DropdownMenu.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
children: PropTypes.node.isRequired,
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
import { Panel } from '../Panel'
|
||||
import { DropdownMenu, DropdownMenuLink } from '.'
|
||||
import { CogIcon, LockClosedIcon } from '../Icons'
|
||||
|
||||
export default {
|
||||
title: 'SkynetLibrary/DropdownMenu',
|
||||
component: DropdownMenu,
|
||||
subcomponents: {
|
||||
DropdownMenuLink,
|
||||
},
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<Panel style={{ margin: 50, textAlign: 'center' }}>
|
||||
<Story />
|
||||
</Panel>
|
||||
),
|
||||
],
|
||||
}
|
||||
|
||||
export const NavigationDropdown = () => (
|
||||
<DropdownMenu title="My account">
|
||||
<DropdownMenuLink href="/settings" icon={CogIcon} label="Settings" active />
|
||||
<DropdownMenuLink href="/logout" icon={LockClosedIcon} label="Log out" />
|
||||
</DropdownMenu>
|
||||
)
|
|
@ -0,0 +1,25 @@
|
|||
import styled from 'styled-components'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
const DropdownLink = styled.a.attrs({
|
||||
className: `m-0 border-t border-palette-200/50 h-[60px]
|
||||
whitespace-nowrap transition-colors text-current
|
||||
hover:bg-palette-100/50 flex items-center
|
||||
pr-8 pl-6 py-4 gap-4 first:border-0`,
|
||||
})``
|
||||
|
||||
export const DropdownMenuLink = ({ active, icon: Icon, label, ...props }) => (
|
||||
<>
|
||||
<DropdownLink {...props}>
|
||||
{Icon ? <Icon className={active ? 'text-primary' : 'text-current'} /> : null}
|
||||
{label}
|
||||
</DropdownLink>
|
||||
</>
|
||||
)
|
||||
|
||||
DropdownMenuLink.propTypes = {
|
||||
label: PropTypes.oneOfType([PropTypes.node, PropTypes.string]).isRequired,
|
||||
active: PropTypes.bool,
|
||||
icon: PropTypes.func,
|
||||
children: PropTypes.node.isRequired,
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
export * from './DropdownMenu'
|
||||
export * from './DropdownMenuLink'
|
|
@ -0,0 +1,60 @@
|
|||
import PropTypes from 'prop-types'
|
||||
|
||||
/**
|
||||
* Primary UI component for user interaction
|
||||
*/
|
||||
export const IconButton = ({ primary, size, icon, ...props }) => {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={`${
|
||||
size === 'small'
|
||||
? 'h-iconButtonSm w-buttonIconSm'
|
||||
: size === 'large'
|
||||
? 'h-iconButtonLg w-iconButtonLg'
|
||||
: 'w-iconButton h-iconButton'
|
||||
} rounded-full
|
||||
inline-flex justify-center items-center
|
||||
${primary ? 'bg-primary' : null}`}
|
||||
{...props}
|
||||
>
|
||||
<div
|
||||
className={
|
||||
size === 'small'
|
||||
? 'h-buttonIconSm w-buttonIconSm'
|
||||
: size === 'large'
|
||||
? 'h-buttonIconLg w-buttonIconLg'
|
||||
: 'h-buttonIcon w-buttonIcon'
|
||||
}
|
||||
>
|
||||
{icon}
|
||||
</div>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
IconButton.propTypes = {
|
||||
/**
|
||||
* Is this the principal call to action on the page?
|
||||
*/
|
||||
primary: PropTypes.bool,
|
||||
/**
|
||||
* How large should the button be?
|
||||
*/
|
||||
size: PropTypes.oneOf(['small', 'medium', 'large']),
|
||||
/**
|
||||
* Icon component
|
||||
*/
|
||||
icon: PropTypes.element.isRequired,
|
||||
/**
|
||||
* Optional click handler
|
||||
*/
|
||||
onClick: PropTypes.func,
|
||||
}
|
||||
|
||||
IconButton.defaultProps = {
|
||||
backgroundColor: null,
|
||||
primary: false,
|
||||
size: 'medium',
|
||||
onClick: undefined,
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
import { IconButton } from './IconButton'
|
||||
import { ArrowRightIcon } from '../Icons'
|
||||
|
||||
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
|
||||
export default {
|
||||
title: 'SkynetLibrary/IconButton',
|
||||
component: IconButton,
|
||||
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
|
||||
argTypes: {
|
||||
backgroundColor: { control: 'color' },
|
||||
},
|
||||
}
|
||||
|
||||
// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
|
||||
const Template = (args) => <IconButton {...args} />
|
||||
|
||||
export const Primary = Template.bind({})
|
||||
// More on args: https://storybook.js.org/docs/react/writing-stories/args
|
||||
Primary.args = {
|
||||
primary: true,
|
||||
icon: <ArrowRightIcon />,
|
||||
}
|
||||
|
||||
export const Secondary = Template.bind({})
|
||||
Secondary.args = {
|
||||
icon: <ArrowRightIcon />,
|
||||
}
|
||||
|
||||
export const Large = Template.bind({})
|
||||
Large.args = {
|
||||
size: 'large',
|
||||
icon: <ArrowRightIcon />,
|
||||
}
|
||||
|
||||
export const Small = Template.bind({})
|
||||
Small.args = {
|
||||
size: 'small',
|
||||
icon: <ArrowRightIcon />,
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './IconButton'
|
|
@ -0,0 +1,46 @@
|
|||
import PropTypes from 'prop-types'
|
||||
|
||||
/**
|
||||
* Primary UI component for user interaction
|
||||
*/
|
||||
export const IconButtonText = ({ primary, label, icon, ...props }) => {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={`flex justify-center items-center w-iconButtonTextWidth py-iconButtonTextY`}
|
||||
{...props}
|
||||
>
|
||||
<div className={`h-buttonTextIcon w-buttonTextIcon ${primary ? 'text-primary' : 'text-palette-600'}`}>{icon}</div>
|
||||
<p
|
||||
className={'ml-iconButtonTextTextLeft tracking-wide text-iconButtonText font-sans font-light text-palette-600'}
|
||||
>
|
||||
{label}
|
||||
</p>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
IconButtonText.propTypes = {
|
||||
/**
|
||||
* Is this the principal call to action on the page?
|
||||
*/
|
||||
primary: PropTypes.bool,
|
||||
/**
|
||||
* Button Label
|
||||
*/
|
||||
label: PropTypes.string.isRequired,
|
||||
/**
|
||||
* Icon component
|
||||
*/
|
||||
icon: PropTypes.element.isRequired,
|
||||
/**
|
||||
* Optional click handler
|
||||
*/
|
||||
onClick: PropTypes.func,
|
||||
}
|
||||
|
||||
IconButtonText.defaultProps = {
|
||||
primary: false,
|
||||
label: '',
|
||||
onClick: undefined,
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
import { IconButtonText } from './IconButtonText'
|
||||
import { CogIcon } from '../Icons'
|
||||
|
||||
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
|
||||
export default {
|
||||
title: 'SkynetLibrary/IconButtonText',
|
||||
component: IconButtonText,
|
||||
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
|
||||
argTypes: {
|
||||
backgroundColor: { control: 'color' },
|
||||
},
|
||||
}
|
||||
|
||||
// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
|
||||
const Template = (args) => <IconButtonText {...args} />
|
||||
|
||||
export const Primary = Template.bind({})
|
||||
// More on args: https://storybook.js.org/docs/react/writing-stories/args
|
||||
Primary.args = {
|
||||
primary: true,
|
||||
label: 'Settings',
|
||||
icon: <CogIcon />,
|
||||
}
|
||||
|
||||
export const Secondary = Template.bind({})
|
||||
Secondary.args = {
|
||||
label: 'Settings',
|
||||
icon: <CogIcon />,
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './IconButtonText'
|
|
@ -0,0 +1,37 @@
|
|||
import { Panel } from '../Panel'
|
||||
import * as icons from '.'
|
||||
|
||||
export default {
|
||||
title: 'SkynetLibrary/Icons',
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div style={{ margin: 50 }}>
|
||||
<Story />
|
||||
</div>
|
||||
),
|
||||
],
|
||||
}
|
||||
|
||||
export const DefaultSizeIcon = () => <icons.SkynetLogoIcon />
|
||||
|
||||
export const LargeIcon = () => <icons.SkynetLogoIcon size={60} />
|
||||
|
||||
export const AllIcons = () => {
|
||||
const sizes = [24, 32, 60]
|
||||
|
||||
return (
|
||||
<>
|
||||
{Object.entries(icons).map(([iconName, IconComponent]) => (
|
||||
<Panel key={`panel-${iconName}`}>
|
||||
<pre>{iconName}</pre>
|
||||
|
||||
<div style={{ padding: 10, border: '1px dashed #fafafa', display: 'flex', alignItems: 'center', gap: 50 }}>
|
||||
{sizes.map((size) => (
|
||||
<IconComponent key={`${iconName}-${size}`} size={size} />
|
||||
))}
|
||||
</div>
|
||||
</Panel>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
import { withIconProps } from '../withIconProps'
|
||||
|
||||
export const ArrowRightIcon = withIconProps(({ size, ...props }) => (
|
||||
<svg width={size} height={size} viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" {...props}>
|
||||
<path
|
||||
d="M10 15h9.616L16.3 11.71l1.409-1.42 4.995 4.954a1 1 0 0 1 .09 1.32l-.084.094-5 5.046-1.42-1.408 3.265-3.295L10 17v-2z"
|
||||
fill="currentColor"
|
||||
fillRule="nonzero"
|
||||
/>
|
||||
</svg>
|
||||
))
|
|
@ -0,0 +1,14 @@
|
|||
import { withIconProps } from '../withIconProps'
|
||||
|
||||
export const ChevronDownIcon = withIconProps(({ size, ...props }) => (
|
||||
<svg width={size} height={size} viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" {...props}>
|
||||
<path
|
||||
d="M21.5 14.005 16.546 19 11.5 14"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
fill="none"
|
||||
fillRule="evenodd"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
))
|
|
@ -0,0 +1,11 @@
|
|||
import { withIconProps } from '../withIconProps'
|
||||
|
||||
export const CogIcon = withIconProps(({ size, ...props }) => (
|
||||
<svg width={size} height={size} viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" {...props}>
|
||||
<path
|
||||
d="M16 4a3 3 0 0 1 3 3v.086c.001.26.156.493.404.6a.647.647 0 0 0 .709-.123l.204-.195a3 3 0 0 1 4.1 4.38l-.052.051a.65.65 0 0 0-.13.717 1 1 0 0 1 .047.13l.012.06.045.062c.1.12.242.2.397.225l.094.007H25a3 3 0 0 1 0 6h-.086a.654.654 0 0 0-.6.404.647.647 0 0 0 .123.709l.195.204a3 3 0 0 1-4.38 4.1l-.051-.052a.654.654 0 0 0-.727-.126.649.649 0 0 0-.394.591V25a3 3 0 0 1-6 0v-.067c-.006-.266-.175-.502-.484-.618a.647.647 0 0 0-.709.122l-.204.195a3 3 0 0 1-4.1-4.38l.052-.051a.654.654 0 0 0 .126-.727.649.649 0 0 0-.591-.394H7a3 3 0 0 1 0-6h.067c.266-.006.502-.175.618-.484a.647.647 0 0 0-.122-.709l-.195-.204a3 3 0 0 1 4.38-4.1l.051.052a.65.65 0 0 0 .717.13 1 1 0 0 1 .13-.047l.06-.013.062-.044c.12-.1.2-.242.225-.397L13 7.17V7a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v.174a2.65 2.65 0 0 1-1.606 2.425A1 1 0 0 1 13 9.68l-.032.043a2.654 2.654 0 0 1-2.433-.537l-.142-.129-.06-.06a1 1 0 1 0-1.416 1.416l.068.068c.757.774.967 1.932.554 2.864l-.073.177A2.66 2.66 0 0 1 7.09 15.08H7a1 1 0 0 0 0 2h.174a2.646 2.646 0 0 1 2.42 1.596 2.654 2.654 0 0 1-.537 2.931l-.06.06a1 1 0 1 0 1.416 1.416l.068-.068c.774-.757 1.932-.967 2.864-.554l.177.073a2.66 2.66 0 0 1 1.558 2.376V25a1 1 0 0 0 2 0v-.174a2.646 2.646 0 0 1 1.596-2.42 2.654 2.654 0 0 1 2.931.537l.06.06a1 1 0 1 0 1.416-1.416l-.068-.068a2.646 2.646 0 0 1-.534-2.913A2.651 2.651 0 0 1 24.91 17H25a1 1 0 0 0 0-2h-.174a2.65 2.65 0 0 1-2.425-1.606A1 1 0 0 1 22.32 13l-.043-.032a2.654 2.654 0 0 1 .537-2.433l.129-.142.06-.06a1 1 0 1 0-1.416-1.416l-.068.068a2.646 2.646 0 0 1-2.913.534A2.651 2.651 0 0 1 17 7.09V7a1 1 0 0 0-1-1zm0 6a4 4 0 1 1 0 8 4 4 0 0 1 0-8zm0 2a2 2 0 1 0 0 4 2 2 0 0 0 0-4z"
|
||||
fill="currentColor"
|
||||
fillRule="nonzero"
|
||||
/>
|
||||
</svg>
|
||||
))
|
|
@ -0,0 +1,11 @@
|
|||
import { withIconProps } from '../withIconProps'
|
||||
|
||||
export const InfoIcon = withIconProps(({ size, ...props }) => (
|
||||
<svg width={size} height={size} viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" {...props}>
|
||||
<path
|
||||
d="M16 5c6.075 0 11 4.925 11 11s-4.925 11-11 11S5 22.075 5 16 9.925 5 16 5zm0 2a9 9 0 1 0 0 18 9 9 0 0 0 0-18zm0 6a1 1 0 0 1 .993.883L17 14v7a1 1 0 0 1-1.993.117L15 21v-7a1 1 0 0 1 1-1zm.01-3a1 1 0 0 1 .117 1.993L16 12a1 1 0 0 1-.117-1.993L16.01 10z"
|
||||
fill="currentColor"
|
||||
fillRule="nonzero"
|
||||
/>
|
||||
</svg>
|
||||
))
|
|
@ -0,0 +1,11 @@
|
|||
import { withIconProps } from '../withIconProps'
|
||||
|
||||
export const LockClosedIcon = withIconProps(({ size, ...props }) => (
|
||||
<svg width={size} height={size} viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" {...props}>
|
||||
<path
|
||||
d="M14.083 6.383A5 5 0 0 1 19.53 7.46a5.09 5.09 0 0 1 1.31 2.29 1.002 1.002 0 0 1-1.94.5 3.08 3.08 0 0 0-.78-1.38A3 3 0 0 0 13 11v2h8a3 3 0 0 1 3 3v7a3 3 0 0 1-3 3H11a3 3 0 0 1-3-3v-7a3 3 0 0 1 3-3v-2a5 5 0 0 1 3.083-4.617zM21 15H11a1 1 0 0 0-1 1v7a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1v-7a1 1 0 0 0-1-1zm-4 2v5h-2v-5h2z"
|
||||
fill="currentColor"
|
||||
fillRule="nonzero"
|
||||
/>
|
||||
</svg>
|
||||
))
|
|
@ -0,0 +1,8 @@
|
|||
import { withIconProps } from '../withIconProps'
|
||||
|
||||
export const SkynetLogoIcon = withIconProps(({ size, ...props }) => (
|
||||
<svg role="img" width={size} fill="#00C65E" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" {...props}>
|
||||
<title>Skynet</title>
|
||||
<path d="m-.0004 6.4602 21.3893 11.297c.561.2935.6633 1.0532.1999 1.4846h-.011a10.0399 10.0399 0 0 1-2.2335 1.5307c-6.912 3.4734-14.9917-1.838-14.5438-9.5605l2.8601 1.9752c.856 4.508 5.6187 7.1094 9.8742 5.3932zm8.6477 3.1509 14.3661 5.6785a.8704.8704 0 0 1 .5197 1.0466v.0182c-.1537.5377-.7668.7938-1.2575.5252zm5.2896-7.4375c2.7093-.2325 6.0946.7869 8.1116 3.3871 1.699 2.1951 2.0497 4.8772 1.9298 7.6465v-.007c-.0478.5874-.6494.9616-1.1975.745l-9.7652-3.8596 9.0656 2.4313a7.296 7.296 0 0 0-1.0677-4.5631c-2.9683-4.7678-9.9847-4.5344-12.6297.4201a7.5048 7.5048 0 0 0-.398.8831L5.5546 7.9614c.069-.1017.1417-.198.2144-.2962.1163-.2416.2417-.487.3798-.7268 1.6118-2.7911 4.3102-4.4338 7.1558-4.6973.2108-.0182.4215-.049.6323-.0672z"></path>
|
||||
</svg>
|
||||
))
|
|
@ -0,0 +1,6 @@
|
|||
export * from './icons/ChevronDownIcon'
|
||||
export * from './icons/CogIcon'
|
||||
export * from './icons/LockClosedIcon'
|
||||
export * from './icons/SkynetLogoIcon'
|
||||
export * from './icons/ArrowRightIcon'
|
||||
export * from './icons/InfoIcon'
|
|
@ -0,0 +1,19 @@
|
|||
import PropTypes from 'prop-types'
|
||||
|
||||
const propTypes = {
|
||||
/**
|
||||
* Size of the icon's bounding box.
|
||||
*/
|
||||
size: PropTypes.number,
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
size: 32,
|
||||
}
|
||||
|
||||
export const withIconProps = (IconComponent) => {
|
||||
IconComponent.propTypes = propTypes
|
||||
IconComponent.defaultProps = defaultProps
|
||||
|
||||
return IconComponent
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import styled from 'styled-components'
|
||||
|
||||
import { PageContainer } from '../PageContainer'
|
||||
|
||||
const NavBarContainer = styled.div.attrs({
|
||||
className: `grid sticky top-0 bg-white`,
|
||||
})``
|
||||
|
||||
const NavBarBody = styled.nav.attrs({
|
||||
className: 'grid h-[80px] font-sans font-light text-sm',
|
||||
})`
|
||||
grid-template-columns: auto max-content 1fr;
|
||||
`
|
||||
|
||||
export const NavBar = (props) => (
|
||||
<NavBarContainer>
|
||||
<PageContainer>
|
||||
<NavBarBody {...props} />
|
||||
</PageContainer>
|
||||
</NavBarContainer>
|
||||
)
|
|
@ -0,0 +1,25 @@
|
|||
import { NavBar, NavBarLink, NavBarSection } from '.'
|
||||
|
||||
export default {
|
||||
title: 'SkynetLibrary/NavBar',
|
||||
component: NavBar,
|
||||
subcomponents: {
|
||||
NavBarSection,
|
||||
NavBarLink,
|
||||
},
|
||||
}
|
||||
|
||||
const Template = (props) => (
|
||||
<NavBar {...props}>
|
||||
<NavBarSection>
|
||||
<NavBarLink href="/dashboard" active>
|
||||
Dashboard
|
||||
</NavBarLink>
|
||||
<NavBarLink href="/files">Files</NavBarLink>
|
||||
<NavBarLink href="/payments">Payments</NavBarLink>
|
||||
</NavBarSection>
|
||||
</NavBar>
|
||||
)
|
||||
|
||||
export const DashboardTopNavigation = Template.bind({})
|
||||
DashboardTopNavigation.args = {}
|
|
@ -0,0 +1,19 @@
|
|||
import PropTypes from 'prop-types'
|
||||
import styled from 'styled-components'
|
||||
|
||||
export const NavBarLink = styled.a.attrs(({ active }) => ({
|
||||
className: `
|
||||
min-w-[168px]
|
||||
flex h-full items-center justify-center
|
||||
border-x border-x-palette-100 border-b-2
|
||||
text-palette-600 transition-colors hover:bg-palette-100/50
|
||||
${active ? 'border-b-primary' : 'border-b-palette-200/50'}
|
||||
`,
|
||||
}))``
|
||||
|
||||
NavBarLink.propTypes = {
|
||||
/**
|
||||
* When set to true, an additional indicator will be rendered showing the item as active.
|
||||
*/
|
||||
active: PropTypes.bool,
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
import styled from 'styled-components'
|
||||
|
||||
export const NavBarSection = styled.div.attrs({ className: 'flex items-center' })``
|
|
@ -0,0 +1,3 @@
|
|||
export * from './NavBar'
|
||||
export * from './NavBarSection'
|
||||
export * from './NavBarLink'
|
|
@ -0,0 +1,13 @@
|
|||
import PropTypes from 'prop-types'
|
||||
import styled from 'styled-components'
|
||||
|
||||
export const PageContainer = styled.div.attrs({
|
||||
className: `mx-auto w-page md:w-page-md lg:w-page-lg xl:w-page-xl`,
|
||||
})``
|
||||
|
||||
PageContainer.propTypes = {
|
||||
/**
|
||||
* Optional `class` attribute.
|
||||
*/
|
||||
className: PropTypes.string,
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './PageContainer'
|
|
@ -0,0 +1,33 @@
|
|||
import PropTypes from 'prop-types'
|
||||
import styled from 'styled-components'
|
||||
|
||||
const PanelBody = styled.div.attrs({
|
||||
className: 'p-6 bg-white rounded',
|
||||
})``
|
||||
|
||||
const PanelTitle = styled.h6.attrs({
|
||||
className: 'uppercase text-xs text-palette-400 h-8 flex items-center',
|
||||
})``
|
||||
|
||||
/**
|
||||
* Besides documented props, it accepts all HMTL attributes a `<div>` element does.
|
||||
*
|
||||
* These additional props will be rendered onto the panel's body element.
|
||||
*/
|
||||
export const Panel = ({ title, ...props }) => (
|
||||
<div>
|
||||
{title && <PanelTitle>{title}</PanelTitle>}
|
||||
<PanelBody {...props} />
|
||||
</div>
|
||||
)
|
||||
|
||||
Panel.propTypes = {
|
||||
/**
|
||||
* Label of the panel
|
||||
*/
|
||||
title: PropTypes.string,
|
||||
}
|
||||
|
||||
Panel.defaultProps = {
|
||||
title: '',
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
import { Panel } from './Panel'
|
||||
|
||||
export default {
|
||||
title: 'SkynetLibrary/Panel',
|
||||
component: Panel,
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div className="inset-0 bg-palette-100 p-6">
|
||||
<div style={{ maxWidth: 800 }}>
|
||||
<Story />
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
],
|
||||
}
|
||||
|
||||
const SampleContent = () => (
|
||||
<>
|
||||
<p>This is the first paragraph</p>
|
||||
<p>This is the second paragraph</p>
|
||||
<p>This is the third paragraph</p>
|
||||
</>
|
||||
)
|
||||
|
||||
const Template = (args) => (
|
||||
<Panel {...args}>
|
||||
<SampleContent />
|
||||
</Panel>
|
||||
)
|
||||
|
||||
export const RawPanel = Template.bind({})
|
||||
RawPanel.args = {}
|
||||
|
||||
export const TitledPanel = Template.bind({})
|
||||
TitledPanel.args = {
|
||||
title: 'Latest activity',
|
||||
}
|
||||
|
||||
export const InlinePanelsExample = () => (
|
||||
<div className="grid gap-4 grid-flow-col auto-cols-fr">
|
||||
<Panel title="Upload" className="w-50">
|
||||
<SampleContent />
|
||||
</Panel>
|
||||
<Panel title="Usage" className="w-50">
|
||||
<SampleContent />
|
||||
</Panel>
|
||||
</div>
|
||||
)
|
||||
|
||||
export const FullWidthPanelsExample = () => (
|
||||
<>
|
||||
<Panel title="Latest activity">
|
||||
<SampleContent />
|
||||
</Panel>
|
||||
<Panel title="Payment history">
|
||||
<SampleContent />
|
||||
</Panel>
|
||||
</>
|
||||
)
|
||||
|
||||
export const CustomPanelBackground = Template.bind({})
|
||||
CustomPanelBackground.args = {
|
||||
className: 'bg-red-500',
|
||||
title: 'Background below should be red',
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './Panel'
|
|
@ -0,0 +1 @@
|
|||
export * from './PopoverMenu'
|
|
@ -0,0 +1,102 @@
|
|||
import { Children, cloneElement, useEffect, useMemo, useRef } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { useClickAway } from 'react-use'
|
||||
import styled, { css, keyframes } from 'styled-components'
|
||||
|
||||
import { ChevronDownIcon } from '../Icons'
|
||||
import { useCallbacks, useSelectReducer } from './hooks'
|
||||
import { SelectOption } from './SelectOption'
|
||||
|
||||
const dropDown = keyframes`
|
||||
0% {
|
||||
transform: scaleY(0);
|
||||
}
|
||||
80% {
|
||||
transform: scaleY(1.1);
|
||||
}
|
||||
100% {
|
||||
transform: scaleY(1);
|
||||
}
|
||||
`
|
||||
|
||||
const Container = styled.div.attrs({ className: 'relative inline-flex' })``
|
||||
|
||||
const Trigger = styled.button.attrs(({ placeholder }) => ({
|
||||
className: `flex items-center cursor-pointer ${placeholder ? 'text-palette-300' : ''}`,
|
||||
}))``
|
||||
|
||||
const TriggerIcon = styled(ChevronDownIcon).attrs({
|
||||
className: 'transition-transform text-primary',
|
||||
})`
|
||||
transform: ${({ open }) => (open ? 'rotateX(180deg)' : 'none')};
|
||||
`
|
||||
|
||||
const Flyout = styled.ul.attrs(({ open }) => ({
|
||||
className: `absolute top-[20px] right-0
|
||||
p-0 h-0 border rounded bg-white
|
||||
overflow-hidden pointer-events-none
|
||||
shadow-md shadow-palette-200/50
|
||||
${open ? 'pointer-events-auto h-auto overflow-visible border-primary' : ''}
|
||||
${open ? 'visible' : 'invisible'}`,
|
||||
}))`
|
||||
animation: ${({ open }) =>
|
||||
open
|
||||
? css`
|
||||
${dropDown} 0.1s ease-in-out
|
||||
`
|
||||
: 'none'};
|
||||
`
|
||||
|
||||
export const Select = ({ defaultValue, children, onChange, placeholder }) => {
|
||||
const selectRef = useRef()
|
||||
const options = useMemo(() => Children.toArray(children).filter(({ type }) => type === SelectOption), [children])
|
||||
const [state, dispatch] = useSelectReducer({ defaultValue, placeholder, options })
|
||||
const { close, toggle, selectOption } = useCallbacks(state, dispatch)
|
||||
|
||||
useClickAway(selectRef, close)
|
||||
|
||||
useEffect(() => {
|
||||
if (state.selectedOptionIndex > -1) {
|
||||
onChange(options[state.selectedOptionIndex].props.value)
|
||||
}
|
||||
}, [onChange, options, state.selectedOptionIndex])
|
||||
|
||||
const activeOption = options[state.selectedOptionIndex]
|
||||
const activeLabel = activeOption?.props?.label ?? null
|
||||
|
||||
return (
|
||||
<Container ref={selectRef}>
|
||||
<Trigger placeholder={!activeLabel && placeholder} onClick={toggle}>
|
||||
{activeLabel ?? placeholder} <TriggerIcon open={state.open} />
|
||||
</Trigger>
|
||||
<Flyout role="listbox" open={state.open}>
|
||||
{options.map((item, index) =>
|
||||
cloneElement(item, {
|
||||
...item.props,
|
||||
onClick: () => selectOption(index),
|
||||
selected: state.selectedOptionIndex === index,
|
||||
})
|
||||
)}
|
||||
</Flyout>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
Select.propTypes = {
|
||||
/**
|
||||
* `<SelectOption>` elements.
|
||||
*/
|
||||
children: PropTypes.node.isRequired,
|
||||
/**
|
||||
* Default value to be selected upon rendering.
|
||||
*/
|
||||
defaultValue: PropTypes.string,
|
||||
/**
|
||||
* Callback for every change.
|
||||
*/
|
||||
onChange: PropTypes.func,
|
||||
/**
|
||||
* Placeholder to be displayed when no option is selected.
|
||||
*/
|
||||
placeholder: PropTypes.string,
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
import { Panel } from '../Panel'
|
||||
import { Select, SelectOption } from '.'
|
||||
|
||||
export default {
|
||||
title: 'SkynetLibrary/Select',
|
||||
component: Select,
|
||||
subcomponents: {
|
||||
SelectOption,
|
||||
},
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<Panel style={{ margin: 50, textAlign: 'center' }}>
|
||||
<Story />
|
||||
</Panel>
|
||||
),
|
||||
],
|
||||
}
|
||||
|
||||
const Template = (props) => (
|
||||
<Select {...props}>
|
||||
<SelectOption value="name-asc" label="A-Z" />
|
||||
<SelectOption value="name-desc" label="Z-A" />
|
||||
<SelectOption value="size-desc" label="Biggest size" />
|
||||
<SelectOption value="size-asc" label="Smallest size" />
|
||||
<SelectOption value="date-desc" label="Latest" />
|
||||
<SelectOption value="date-asc" label="Oldest" />
|
||||
</Select>
|
||||
)
|
||||
Template.args = {}
|
||||
|
||||
export const NoDefaultNoPlaceholder = Template.bind({})
|
||||
NoDefaultNoPlaceholder.args = {
|
||||
onChange: console.info.bind(console, 'onChange'),
|
||||
}
|
||||
|
||||
export const WithPlaceholder = Template.bind({})
|
||||
WithPlaceholder.args = {
|
||||
placeholder: 'Select...',
|
||||
onChange: console.info.bind(console, 'onChange'),
|
||||
}
|
||||
|
||||
export const WithDefautValue = Template.bind({})
|
||||
WithDefautValue.args = {
|
||||
defaultValue: 'size-desc',
|
||||
placeholder: 'Select...',
|
||||
onChange: console.info.bind(console, 'onChange'),
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
import PropTypes from 'prop-types'
|
||||
import styled from 'styled-components'
|
||||
|
||||
const Option = styled.li.attrs(({ selected }) => ({
|
||||
className: `m-0 px-4 whitespace-nowrap py-1 px-4 cursor-pointer
|
||||
transition-colors hover:bg-palette-100/50
|
||||
${selected ? 'pl-3.5 border-l-2 border-l-primary' : ''}`,
|
||||
}))``
|
||||
|
||||
export const SelectOption = ({ selected, label, ...props }) => (
|
||||
<Option selected={selected} role="option" {...props}>
|
||||
{label}
|
||||
</Option>
|
||||
)
|
||||
|
||||
SelectOption.propTypes = {
|
||||
/**
|
||||
* Label for the option
|
||||
*/
|
||||
label: PropTypes.string.isRequired,
|
||||
|
||||
/** Value represented by the option */
|
||||
value: PropTypes.string.isRequired,
|
||||
|
||||
/**
|
||||
* Indicates an option is currently selected. **Controlled by parent `<Select>` component**.
|
||||
*/
|
||||
selected: PropTypes.bool,
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
import { useCallback, useReducer } from 'react'
|
||||
|
||||
const initialState = {
|
||||
open: false,
|
||||
selectedOptionIndex: -1,
|
||||
}
|
||||
|
||||
const withDefaultValue = (state, { defaultValue, options, placeholder }) => {
|
||||
let index = -1
|
||||
|
||||
if (!defaultValue) {
|
||||
if (!placeholder) {
|
||||
// If no default value and no placeholder are provided, select first option.
|
||||
// TODO: might need to look for the first *available* option.
|
||||
index = 0
|
||||
}
|
||||
} else {
|
||||
index = options.findIndex((option) => {
|
||||
if (!option || !option.props) {
|
||||
return false
|
||||
}
|
||||
|
||||
return option.props.value === defaultValue
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
selectedOptionIndex: index,
|
||||
}
|
||||
}
|
||||
|
||||
const stateReducer = (state, action) => {
|
||||
switch (action.type) {
|
||||
case 'close':
|
||||
return {
|
||||
...state,
|
||||
open: false,
|
||||
}
|
||||
case 'open':
|
||||
return {
|
||||
...state,
|
||||
open: true,
|
||||
}
|
||||
case 'selectOption':
|
||||
return {
|
||||
...state,
|
||||
open: false,
|
||||
selectedOptionIndex: action.index,
|
||||
}
|
||||
default:
|
||||
return {
|
||||
...state,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const useSelectReducer = ({ defaultValue, options, placeholder }) =>
|
||||
useReducer(stateReducer, withDefaultValue(initialState, { defaultValue, options, placeholder }))
|
||||
|
||||
export const useCallbacks = (state, dispatch) => {
|
||||
const close = useCallback(() => {
|
||||
if (state.open) {
|
||||
dispatch({ type: 'close' })
|
||||
}
|
||||
}, [dispatch, state.open])
|
||||
|
||||
const toggle = useCallback(() => {
|
||||
dispatch({ type: state.open ? 'close' : 'open' })
|
||||
}, [dispatch, state.open])
|
||||
|
||||
const selectOption = useCallback(
|
||||
(optionIndex) => {
|
||||
if (optionIndex !== state.selectedOptionIndex) {
|
||||
dispatch({ type: 'selectOption', index: optionIndex })
|
||||
}
|
||||
},
|
||||
[dispatch, state.selectedOptionIndex]
|
||||
)
|
||||
|
||||
return {
|
||||
close,
|
||||
selectOption,
|
||||
toggle,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
export * from './Select'
|
||||
export * from './SelectOption'
|
|
@ -0,0 +1,40 @@
|
|||
.react-switch-checkbox {
|
||||
height: 0;
|
||||
width: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.react-switch-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
cursor: pointer;
|
||||
width: 44px;
|
||||
height: 22px;
|
||||
background: white;
|
||||
border-radius: 11px;
|
||||
@apply border-palette-200;
|
||||
border-width: 1px;
|
||||
position: relative;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.react-switch-label .react-switch-button {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 8px;
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
.react-switch-checkbox:checked + .react-switch-label .react-switch-button {
|
||||
left: calc(100% - 2px);
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
.react-switch-label:active .react-switch-button {
|
||||
width: 20px;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
import PropTypes from 'prop-types'
|
||||
import './Switch.css'
|
||||
|
||||
/**
|
||||
* Primary UI component for user interaction
|
||||
*/
|
||||
export const Switch = ({ isOn, handleToggle }) => {
|
||||
return (
|
||||
<>
|
||||
<input
|
||||
checked={isOn}
|
||||
onChange={handleToggle}
|
||||
className="react-switch-checkbox"
|
||||
id={`react-switch-new`}
|
||||
type="checkbox"
|
||||
/>
|
||||
<label className={'react-switch-label'} htmlFor={`react-switch-new`}>
|
||||
<span className={`react-switch-button ${isOn ? 'bg-primary' : 'bg-palette-200'}`} />
|
||||
</label>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Switch.propTypes = {
|
||||
/**
|
||||
* Switch's current value
|
||||
*/
|
||||
isOn: PropTypes.bool,
|
||||
/**
|
||||
* Function to execute on change
|
||||
*/
|
||||
handleToggle: PropTypes.func,
|
||||
}
|
||||
|
||||
Switch.defaultProps = {
|
||||
isOn: false,
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
import { Switch } from './Switch'
|
||||
|
||||
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
|
||||
export default {
|
||||
title: 'SkynetLibrary/Switch',
|
||||
component: Switch,
|
||||
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
|
||||
}
|
||||
|
||||
// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
|
||||
const Template = (args) => <Switch {...args} />
|
||||
|
||||
export const SwitchTrue = Template.bind({})
|
||||
// More on args: https://storybook.js.org/docs/react/writing-stories/args
|
||||
SwitchTrue.args = {
|
||||
isOn: true,
|
||||
}
|
||||
export const SwitchFalse = Template.bind({})
|
||||
// More on args: https://storybook.js.org/docs/react/writing-stories/args
|
||||
SwitchFalse.args = {
|
||||
isOn: false,
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './Switch'
|
|
@ -0,0 +1,20 @@
|
|||
import styled from 'styled-components'
|
||||
|
||||
const Container = styled.div.attrs({
|
||||
className: 'p-1 max-w-full overflow-x-auto',
|
||||
})``
|
||||
|
||||
const StyledTable = styled.table.attrs({
|
||||
className: 'table-auto w-full border-separate',
|
||||
})`
|
||||
border-spacing: 0;
|
||||
`
|
||||
|
||||
/**
|
||||
* Accepts all HMTL attributes a `<table>` element does.
|
||||
*/
|
||||
export const Table = (props) => (
|
||||
<Container>
|
||||
<StyledTable {...props} />
|
||||
</Container>
|
||||
)
|
|
@ -0,0 +1,93 @@
|
|||
import { CogIcon } from '../Icons'
|
||||
|
||||
import { IconButton } from '../IconButton'
|
||||
import { Table, TableBody, TableHead, TableCell, TableRow, TableHeadCell } from './'
|
||||
|
||||
export default {
|
||||
title: 'SkynetLibrary/Table',
|
||||
component: Table,
|
||||
subcomponents: {
|
||||
TableBody,
|
||||
TableHead,
|
||||
TableCell,
|
||||
TableRow,
|
||||
TableHeadCell,
|
||||
},
|
||||
}
|
||||
|
||||
const DATA = [
|
||||
{
|
||||
name: 'At_vereo_eos_censes',
|
||||
type: '.mp4',
|
||||
size: '2.45 MB',
|
||||
uploaded: 'a few seconds ago',
|
||||
skylink: '_HyFqH632Rmy99c93idTtBVXeRDgaDAAWg6Bmm5P1izriu',
|
||||
},
|
||||
{
|
||||
name: 'Miriam Klein IV',
|
||||
type: '.pdf',
|
||||
size: '7.52 MB',
|
||||
uploaded: '01/04/2021; 17:11',
|
||||
skylink: '_izriuHyFqH632Rmy99c93idTtBVXeRDgaDAAWg6Bmm5P1',
|
||||
},
|
||||
{
|
||||
name: 'tmp/QmWR6eVDVkwhAYq7X99w4xT9KNKBzwK39Fj1PDmr4ZnzMm/QmWR6eVDVkwhAYq7X99w4xT9KNKBzwK39Fj1PDmr4ZnzMm',
|
||||
type: '.doc',
|
||||
size: '8.15 MB',
|
||||
uploaded: '10/26/2020; 7:21',
|
||||
skylink: '_VXeRDgaDAAWg6Bmm5P1izriuHyFqH632Rmy99c93idTtB',
|
||||
},
|
||||
{
|
||||
name: 'Perm_London',
|
||||
type: '.avi',
|
||||
size: '225.6 MB',
|
||||
uploaded: '09/12/2020; 19:28',
|
||||
skylink: '_eRDgaDAAWg6Bmm5P1izriuHyFqH632Rmy99c93idTtBVX',
|
||||
},
|
||||
{
|
||||
name: 'Santa_Clara',
|
||||
type: '.pdf',
|
||||
size: '7.52 MB',
|
||||
uploaded: '09/12/2020; 19:23',
|
||||
skylink: '_AWg6Bmm5P1izriuHyFqH632Rmy99c93idTtBVXeRDgaDA',
|
||||
},
|
||||
{
|
||||
name: 'Marysa_Labrone',
|
||||
type: '.doc',
|
||||
size: '8.15 MB',
|
||||
uploaded: '09/12/2020; 19:21',
|
||||
skylink: '_P1izriuHyFqH632Rmy99c93idTtBVXeRDgaDAAWg6Bmm5',
|
||||
},
|
||||
]
|
||||
|
||||
const Template = (args) => (
|
||||
<Table {...args}>
|
||||
<TableHead>
|
||||
<TableRow noHoverEffect>
|
||||
<TableHeadCell>Name</TableHeadCell>
|
||||
<TableHeadCell>Type</TableHeadCell>
|
||||
<TableHeadCell align="right">Size</TableHeadCell>
|
||||
<TableHeadCell>Uploaded</TableHeadCell>
|
||||
<TableHeadCell>Skylink</TableHeadCell>
|
||||
<TableHeadCell>Activity</TableHeadCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{DATA.map(({ name, type, size, uploaded, skylink }) => (
|
||||
<TableRow key={skylink}>
|
||||
<TableCell maxWidth="200px">{name}</TableCell>
|
||||
<TableCell>{type}</TableCell>
|
||||
<TableCell align="right">{size}</TableCell>
|
||||
<TableCell>{uploaded}</TableCell>
|
||||
<TableCell>{skylink}</TableCell>
|
||||
<TableCell>
|
||||
<IconButton icon={<CogIcon width={24} color="#0d0d0d" />}></IconButton>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
)
|
||||
|
||||
export const RegularTable = Template.bind({})
|
||||
RegularTable.args = {}
|
|
@ -0,0 +1,6 @@
|
|||
import styled from 'styled-components'
|
||||
|
||||
/**
|
||||
* Accepts all HMTL attributes a `<tbody>` element does.
|
||||
*/
|
||||
export const TableBody = styled.tbody``
|
|
@ -0,0 +1,13 @@
|
|||
import styled from 'styled-components'
|
||||
|
||||
/**
|
||||
* Accepts all HMTL attributes a `<td>` element does.
|
||||
*/
|
||||
export const TableCell = styled.td.attrs({
|
||||
className: `px-6 py-4 h-tableRow truncate
|
||||
text-palette-600 even:text-palette-400
|
||||
first:rounded-l-sm last:rounded-r-sm`,
|
||||
})`
|
||||
text-align: ${({ align }) => align ?? 'left'};
|
||||
max-width: ${({ maxWidth }) => maxWidth ?? 'none'};
|
||||
`
|
|
@ -0,0 +1,6 @@
|
|||
import styled from 'styled-components'
|
||||
|
||||
/**
|
||||
* Accepts all HMTL attributes a `<thead>` element does.
|
||||
*/
|
||||
export const TableHead = styled.thead``
|
|
@ -0,0 +1,13 @@
|
|||
import styled from 'styled-components'
|
||||
|
||||
/**
|
||||
* Accepts all HMTL attributes a `<th>` element does.
|
||||
*/
|
||||
export const TableHeadCell = styled.th.attrs({
|
||||
className: `px-6 py-2.5 truncate h-tableRow
|
||||
text-palette-600 font-sans font-light text-xs
|
||||
first:rounded-l-sm last:rounded-r-sm`,
|
||||
})`
|
||||
text-align: ${({ align }) => align ?? 'left'};
|
||||
max-width: ${({ maxWidth }) => maxWidth ?? 'none'};
|
||||
`
|
|
@ -0,0 +1,20 @@
|
|||
import PropTypes from 'prop-types'
|
||||
import styled from 'styled-components'
|
||||
|
||||
/**
|
||||
* Besides documented props, it accepts all HMTL attributes a `<tr>` element does.
|
||||
*/
|
||||
export const TableRow = styled.tr.attrs(({ noHoverEffect }) => ({
|
||||
className: `bg-palette-100/50 odd:bg-white ${noHoverEffect ? '' : 'hover:bg-palette-200/20'}`,
|
||||
}))``
|
||||
|
||||
/**
|
||||
* Allows disabling `hover` effect on a row. Useful for `<thead>` row.
|
||||
*/
|
||||
TableRow.propTypes = {
|
||||
noHoverEffect: PropTypes.bool,
|
||||
}
|
||||
|
||||
TableRow.defaultProps = {
|
||||
noHoverEffect: false,
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
export * from './Table'
|
||||
export * from './TableHead'
|
||||
export * from './TableHeadCell'
|
||||
export * from './TableBody'
|
||||
export * from './TableRow'
|
||||
export * from './TableCell'
|
|
@ -0,0 +1,38 @@
|
|||
import { useEffect, useState } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import styled from 'styled-components'
|
||||
|
||||
const Wrapper = styled.div.attrs({
|
||||
className: 'absolute left-0 bottom-0 w-full h-0.5 bg-palette-200',
|
||||
})``
|
||||
|
||||
const Indicator = styled.div.attrs({
|
||||
className: 'absolute h-0.5 bottom-0 bg-primary duration-200 ease-in-out',
|
||||
})`
|
||||
will-change: left, width;
|
||||
`
|
||||
|
||||
export const ActiveTabIndicator = ({ tabRef }) => {
|
||||
const [position, setPosition] = useState(0)
|
||||
const [width, setWidth] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
if (!tabRef?.current) {
|
||||
return
|
||||
}
|
||||
|
||||
const { offsetLeft, offsetWidth } = tabRef.current
|
||||
setPosition(offsetLeft)
|
||||
setWidth(offsetWidth)
|
||||
}, [tabRef])
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<Indicator style={{ left: position, width: `${width}px` }} />
|
||||
</Wrapper>
|
||||
)
|
||||
}
|
||||
|
||||
ActiveTabIndicator.propTypes = {
|
||||
tabRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.instanceOf(Element) })]),
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
import { forwardRef } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import styled from 'styled-components'
|
||||
|
||||
export const StyledTab = styled.button.attrs(({ active, variant }) => ({
|
||||
className: `m-0 px-2 pb-2
|
||||
text-tab text-left font-sans
|
||||
transition-colors hover:text-palette-500
|
||||
${active ? 'font-semibold text-palette-600' : 'font-light text-palette-300'}
|
||||
${variant === 'regular' ? 'sm:min-w-[180px]' : ''}`,
|
||||
}))``
|
||||
|
||||
export const Tab = forwardRef(({ active, title, id, variant, ...props }, ref) => (
|
||||
<StyledTab
|
||||
ref={ref}
|
||||
role="tab"
|
||||
type="button"
|
||||
ariaSelected={`${active ? 'true' : 'false'}`}
|
||||
ariaControls={`tabpanel-${id}`}
|
||||
id={`tab-${id}`}
|
||||
active={active}
|
||||
variant={variant}
|
||||
{...props}
|
||||
>
|
||||
{title}
|
||||
</StyledTab>
|
||||
))
|
||||
|
||||
Tab.displayName = 'Tab'
|
||||
|
||||
Tab.propTypes = {
|
||||
/**
|
||||
* Used by `Tabs` component to control the `active` property, and also
|
||||
* in the HTML markup for accessibility purposes.
|
||||
*
|
||||
* Should be set to the same value as related `TabPanel`'s `tabId` prop.
|
||||
*/
|
||||
id: PropTypes.string.isRequired,
|
||||
/**
|
||||
* Used as a label.
|
||||
*/
|
||||
title: PropTypes.string.isRequired,
|
||||
/**
|
||||
* Controlled by `Tabs` component.
|
||||
*/
|
||||
active: PropTypes.bool,
|
||||
/**
|
||||
* Controlled by `Tabs` component.
|
||||
*/
|
||||
variant: PropTypes.string,
|
||||
}
|
||||
|
||||
Tab.defaultProps = {
|
||||
variant: 'regular',
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
import PropTypes from 'prop-types'
|
||||
|
||||
/**
|
||||
* Besides documented props, it accepts all HMTL attributes a `<div>` element does.
|
||||
*/
|
||||
export const TabPanel = ({ children, active, tabId, ...props }) => {
|
||||
if (!active) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div role="tabpanel" id={`tabpanel-${tabId}`} aria-labelledby={`tab-${tabId}`} {...props}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
TabPanel.propTypes = {
|
||||
/**
|
||||
* Used by `Tabs` component to control the `active` property, and also
|
||||
* in the HTML markup for accessibility purposes.
|
||||
*
|
||||
* Should be set to the same value as related `Tab`'s `id` prop.
|
||||
*/
|
||||
tabId: PropTypes.string.isRequired,
|
||||
children: PropTypes.node,
|
||||
/**
|
||||
* Controlled by `Tabs` component.
|
||||
*/
|
||||
active: PropTypes.bool,
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
import { cloneElement, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import { ActiveTabIndicator } from './ActiveTabIndicator'
|
||||
import { usePrefixedTabIds, useTabsChildren } from './hooks'
|
||||
|
||||
const Container = styled.div.attrs({
|
||||
className: 'tabs-container',
|
||||
})``
|
||||
|
||||
const Header = styled.div.attrs({
|
||||
className: 'relative flex justify-start overflow-hidden',
|
||||
})``
|
||||
|
||||
const TabList = styled.div.attrs(({ variant }) => ({
|
||||
role: 'tablist',
|
||||
className: `relative inline-grid grid-flow-col auto-cols-fr
|
||||
${variant === 'regular' ? 'w-full sm:w-auto' : 'w-full'}`,
|
||||
}))``
|
||||
|
||||
const Divider = styled.div.attrs({
|
||||
'aria-hidden': 'true',
|
||||
className: 'absolute bottom-0 w-screen border-b border-b-palette-200',
|
||||
})`
|
||||
right: calc(-100vw - 2px);
|
||||
`
|
||||
|
||||
const Body = styled.div``
|
||||
|
||||
/**
|
||||
* Besides documented props, it accepts all HMTL attributes a `<div>` element does.
|
||||
*/
|
||||
export const Tabs = ({ defaultTab, children, variant }) => {
|
||||
const getTabId = usePrefixedTabIds()
|
||||
const { tabs, panels, tabsRefs } = useTabsChildren(children, getTabId)
|
||||
const defaultTabId = useMemo(() => getTabId(defaultTab || tabs[0].props.id), [getTabId, defaultTab, tabs])
|
||||
const [activeTabId, setActiveTabId] = useState(defaultTabId)
|
||||
const [activeTabRef, setActiveTabRef] = useState(tabsRefs[activeTabId])
|
||||
const isActive = (id) => id === activeTabId
|
||||
const onTabChange = useCallback(
|
||||
(id) => {
|
||||
setActiveTabId(id)
|
||||
},
|
||||
[setActiveTabId]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
// Refresh active tab indicator whenever active tab changes.
|
||||
setActiveTabRef(tabsRefs[activeTabId])
|
||||
}, [setActiveTabRef, tabsRefs, activeTabId])
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Header>
|
||||
<TabList variant={variant}>
|
||||
{tabs.map((tab) => {
|
||||
const tabId = getTabId(tab.props.id)
|
||||
|
||||
return cloneElement(tab, {
|
||||
ref: tabsRefs[tabId],
|
||||
id: tabId,
|
||||
variant,
|
||||
active: isActive(tabId),
|
||||
onClick: () => onTabChange(tabId),
|
||||
})
|
||||
})}
|
||||
<Divider />
|
||||
<ActiveTabIndicator tabRef={activeTabRef} />
|
||||
</TabList>
|
||||
</Header>
|
||||
<Body>
|
||||
{panels.map((panel) => {
|
||||
const tabId = getTabId(panel.props.tabId)
|
||||
|
||||
return cloneElement(panel, {
|
||||
...panel.props,
|
||||
tabId,
|
||||
active: isActive(tabId),
|
||||
})
|
||||
})}
|
||||
</Body>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
Tabs.propTypes = {
|
||||
/**
|
||||
* Should include `<Tab />` and `<TabPanel />` components.
|
||||
*/
|
||||
children: PropTypes.node.isRequired,
|
||||
/**
|
||||
* ID of the `<Tab />` which should be open by default
|
||||
*/
|
||||
defaultTab: PropTypes.string,
|
||||
/**
|
||||
* `regular` (default) will make the tabs only take as much space as they need
|
||||
*
|
||||
* `fill` will make the tabs spread throughout the available width
|
||||
*/
|
||||
variant: PropTypes.oneOf(['regular', 'fill']),
|
||||
}
|
||||
|
||||
Tabs.defaultProps = {
|
||||
variant: 'regular',
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
import { Tab, TabPanel, Tabs } from './'
|
||||
|
||||
export default {
|
||||
title: 'SkynetLibrary/Tabs',
|
||||
component: Tabs,
|
||||
subcomponents: { Tab, TabPanel },
|
||||
}
|
||||
|
||||
const Template = (props) => (
|
||||
<>
|
||||
<Tabs {...props}>
|
||||
<Tab id="uploads" title="Uploads" />
|
||||
<Tab id="downloads" title="Downloads" />
|
||||
<TabPanel tabId="uploads">
|
||||
<ul>
|
||||
<li>Upload #1</li>
|
||||
<li>Upload #2</li>
|
||||
<li>Upload #3</li>
|
||||
<li>Upload #4</li>
|
||||
</ul>
|
||||
</TabPanel>
|
||||
<TabPanel tabId="downloads">
|
||||
<ul>
|
||||
<li>Download #1</li>
|
||||
<li>Download #2</li>
|
||||
<li>Download #3</li>
|
||||
<li>Download #4</li>
|
||||
</ul>
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
</>
|
||||
)
|
||||
|
||||
const RegularTabs = Template.bind({})
|
||||
|
||||
const FillingTabs = Template.bind({})
|
||||
FillingTabs.args = {
|
||||
variant: 'fill',
|
||||
}
|
||||
|
||||
const FillingTabsInNarrowContainer = Template.bind({})
|
||||
FillingTabsInNarrowContainer.args = {
|
||||
variant: 'fill',
|
||||
defaultTab: 'downloads',
|
||||
}
|
||||
FillingTabsInNarrowContainer.decorators = [
|
||||
(Story) => (
|
||||
<div style={{ width: 360, background: '#fafafa', padding: 10, border: '1px solid #eee' }}>
|
||||
<Story />
|
||||
</div>
|
||||
),
|
||||
]
|
||||
|
||||
const MultipleTabsComponents = Template.bind({})
|
||||
MultipleTabsComponents.args = {
|
||||
variant: 'fill',
|
||||
}
|
||||
MultipleTabsComponents.decorators = [
|
||||
(Story) => (
|
||||
<div style={{ width: 360, background: '#fafafa', padding: 10, border: '1px solid #eee' }}>
|
||||
<Story />
|
||||
<Story />
|
||||
</div>
|
||||
),
|
||||
]
|
||||
|
||||
export { RegularTabs, FillingTabs, FillingTabsInNarrowContainer, MultipleTabsComponents }
|
|
@ -0,0 +1,33 @@
|
|||
import { Children, createRef, useCallback, useMemo } from 'react'
|
||||
|
||||
import { Tab } from './Tab'
|
||||
import { TabPanel } from './TabPanel'
|
||||
|
||||
export const usePrefixedTabIds = () => {
|
||||
const seed = useMemo(() => Math.random().toString().split('.')[1], [])
|
||||
|
||||
return useCallback((id) => `${seed}-${id}`, [seed])
|
||||
}
|
||||
|
||||
export const useTabsChildren = (children, prefixId) => {
|
||||
const childrenArray = useMemo(() => Children.toArray(children), [children])
|
||||
const tabs = useMemo(() => childrenArray.filter(({ type }) => type === Tab), [childrenArray])
|
||||
const panels = useMemo(() => childrenArray.filter(({ type }) => type === TabPanel), [childrenArray])
|
||||
const tabsRefs = useMemo(
|
||||
() =>
|
||||
tabs.reduce(
|
||||
(refs, tab) => ({
|
||||
...refs,
|
||||
[prefixId(tab.props.id)]: createRef(),
|
||||
}),
|
||||
{}
|
||||
),
|
||||
[tabs, prefixId]
|
||||
)
|
||||
|
||||
return {
|
||||
tabs,
|
||||
panels,
|
||||
tabsRefs,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
export * from './Tab'
|
||||
export * from './Tabs'
|
||||
export * from './TabPanel'
|
|
@ -0,0 +1,31 @@
|
|||
import PropTypes from 'prop-types'
|
||||
|
||||
/**
|
||||
* Primary UI component for user interaction
|
||||
*/
|
||||
export const TextIndicator = ({ variant }) => {
|
||||
return (
|
||||
<div
|
||||
className={`flex justify-center items-center w-textIndicator h-textIndicator text-textIndicator font-sans uppercase tracking-wide text-button bg-opacity-10 ${
|
||||
variant === 'success'
|
||||
? 'text-primary bg-primary'
|
||||
: variant === 'next'
|
||||
? 'text-next bg-next'
|
||||
: 'text-error bg-error'
|
||||
}`}
|
||||
>
|
||||
{variant === 'success' ? 'success' : variant === 'next' ? 'next' : 'error'}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
TextIndicator.propTypes = {
|
||||
/**
|
||||
* Variant of text indicator
|
||||
*/
|
||||
variant: PropTypes.oneOf(['success', 'next', 'error']),
|
||||
}
|
||||
|
||||
TextIndicator.defaultProps = {
|
||||
variant: 'success',
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
import { TextIndicator } from './TextIndicator'
|
||||
|
||||
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
|
||||
export default {
|
||||
title: 'SkynetLibrary/TextIndicator',
|
||||
component: TextIndicator,
|
||||
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
|
||||
}
|
||||
|
||||
// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
|
||||
const Template = (args) => <TextIndicator {...args} />
|
||||
|
||||
export const Success = Template.bind({})
|
||||
// More on args: https://storybook.js.org/docs/react/writing-stories/args
|
||||
Success.args = {
|
||||
variant: 'success',
|
||||
}
|
||||
|
||||
export const Next = Template.bind({})
|
||||
Next.args = {
|
||||
variant: 'next',
|
||||
}
|
||||
|
||||
export const Error = Template.bind({})
|
||||
Error.args = {
|
||||
variant: 'error',
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './TextIndicator'
|
|
@ -0,0 +1,30 @@
|
|||
import PropTypes from 'prop-types'
|
||||
|
||||
/**
|
||||
* Primary UI component for user interaction
|
||||
*/
|
||||
export const TextInputBasic = ({ label, placeholder }) => {
|
||||
return (
|
||||
<div className={''}>
|
||||
<p className={'font-sans uppercase text-palette-300 text-inputLabel mb-textInputLabelBottom'}>{label}</p>
|
||||
<input
|
||||
placeholder={placeholder}
|
||||
className={
|
||||
'w-full bg-palette-100 h-textInput px-textInputBasicX focus:outline-none bg-transparent ' +
|
||||
'placeholder-palette-400 text-content tracking-inputPlaceholder text-textInput'
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
TextInputBasic.propTypes = {
|
||||
/**
|
||||
* Icon to place in text input
|
||||
*/
|
||||
label: PropTypes.string,
|
||||
/**
|
||||
* Input placeholder
|
||||
*/
|
||||
placeholder: PropTypes.string,
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
import { TextInputBasic } from './TextInputBasic'
|
||||
|
||||
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
|
||||
export default {
|
||||
title: 'SkynetLibrary/TextInputBasic',
|
||||
component: TextInputBasic,
|
||||
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
|
||||
}
|
||||
|
||||
// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
|
||||
const Template = (args) => <TextInputBasic {...args} />
|
||||
|
||||
export const Input = Template.bind({})
|
||||
// More on args: https://storybook.js.org/docs/react/writing-stories/args
|
||||
Input.args = {
|
||||
label: 'Display Name',
|
||||
placeholder: 'Your Name',
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './TextInputBasic'
|
|
@ -0,0 +1,35 @@
|
|||
import PropTypes from 'prop-types'
|
||||
|
||||
/**
|
||||
* Primary UI component for user interaction
|
||||
*/
|
||||
export const TextInputIcon = ({ icon, position, placeholder }) => {
|
||||
return (
|
||||
<div className={'flex flex-row items-center px-textInputIcon h-textInput rounded-full bg-palette-100'}>
|
||||
{position === 'left' ? <div className={'w-buttonIconLg h-buttonIconLg'}>{icon}</div> : null}
|
||||
<input
|
||||
placeholder={placeholder}
|
||||
className={
|
||||
'w-full focus:outline-none mx-textInputHorizontal rounded-full bg-transparent ' +
|
||||
'placeholder-palette-400 text-content tracking-inputPlaceholder text-textInput'
|
||||
}
|
||||
/>
|
||||
{position === 'right' ? <div className={'w-buttonIconLg h-buttonIconLg'}>{icon}</div> : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
TextInputIcon.propTypes = {
|
||||
/**
|
||||
* Icon to place in text input
|
||||
*/
|
||||
icon: PropTypes.element,
|
||||
/**
|
||||
* Side to place icon
|
||||
*/
|
||||
position: PropTypes.oneOf(['left', 'right']),
|
||||
/**
|
||||
* Input placeholder
|
||||
*/
|
||||
placeholder: PropTypes.string,
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
import { TextInputIcon } from './TextInputIcon'
|
||||
import { CogIcon } from '../Icons'
|
||||
|
||||
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
|
||||
export default {
|
||||
title: 'SkynetLibrary/TextInputIcon',
|
||||
component: TextInputIcon,
|
||||
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
|
||||
}
|
||||
|
||||
// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
|
||||
const Template = (args) => <TextInputIcon {...args} />
|
||||
|
||||
export const IconLeft = Template.bind({})
|
||||
// More on args: https://storybook.js.org/docs/react/writing-stories/args
|
||||
IconLeft.args = {
|
||||
icon: <CogIcon />,
|
||||
position: 'left',
|
||||
placeholder: 'Search',
|
||||
}
|
||||
|
||||
export const IconRight = Template.bind({})
|
||||
IconRight.args = {
|
||||
icon: <CogIcon />,
|
||||
position: 'right',
|
||||
placeholder: 'Search',
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './TextInputIcon'
|
|
@ -1,3 +1,18 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
html {
|
||||
@apply font-content bg-palette-200 bg-opacity-20;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
@apply font-sans;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,8 @@ module.exports = {
|
|||
content: ["Source\\ Sans\\ Pro", ...defaultTheme.fontFamily.sans],
|
||||
},
|
||||
fontSize: {
|
||||
tab: ["18px", "28px"],
|
||||
body: ['21px', { lineHeight: '1.58' }],
|
||||
tab: ['18px', '28px'],
|
||||
},
|
||||
backgroundColor: ["disabled"],
|
||||
textColor: ["disabled"],
|
||||
|
@ -53,6 +54,9 @@ module.exports = {
|
|||
"page-lg": "896px",
|
||||
"page-xl": "1312px",
|
||||
},
|
||||
minWidth: {
|
||||
button: '112px',
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
|
|
|
@ -1107,7 +1107,7 @@
|
|||
core-js-pure "^3.20.2"
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.8", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.16.7", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
|
||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.8", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.16.7", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
|
||||
version "7.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941"
|
||||
integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==
|
||||
|
@ -3318,6 +3318,11 @@
|
|||
dependencies:
|
||||
"@types/istanbul-lib-report" "*"
|
||||
|
||||
"@types/js-cookie@^2.2.6":
|
||||
version "2.2.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.7.tgz#226a9e31680835a6188e887f3988e60c04d3f6a3"
|
||||
integrity sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==
|
||||
|
||||
"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
|
||||
version "7.0.9"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"
|
||||
|
@ -3989,6 +3994,11 @@
|
|||
"@webassemblyjs/wast-parser" "1.9.0"
|
||||
"@xtuc/long" "4.2.2"
|
||||
|
||||
"@xobotyi/scrollbar-width@^1.9.5":
|
||||
version "1.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz#80224a6919272f405b87913ca13b92929bdf3c4d"
|
||||
integrity sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==
|
||||
|
||||
"@xtuc/ieee754@^1.2.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
|
||||
|
@ -5982,6 +5992,14 @@ css-declaration-sorter@^6.0.3:
|
|||
dependencies:
|
||||
timsort "^0.3.0"
|
||||
|
||||
css-in-js-utils@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz#3b472b398787291b47cfe3e44fecfdd9e914ba99"
|
||||
integrity sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==
|
||||
dependencies:
|
||||
hyphenate-style-name "^1.0.2"
|
||||
isobject "^3.0.1"
|
||||
|
||||
css-loader@^3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645"
|
||||
|
@ -6167,7 +6185,7 @@ csstype@^2.5.7:
|
|||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.19.tgz#feeb5aae89020bb389e1f63669a5ed490e391caa"
|
||||
integrity sha512-ZVxXaNy28/k3kJg0Fou5MiYpp88j7H9hLZp8PDC3jV0WFjfH5E9xHb56L0W59cPbKbcHXeP4qyT8PrHp8t6LcQ==
|
||||
|
||||
csstype@^3.0.2:
|
||||
csstype@^3.0.2, csstype@^3.0.6:
|
||||
version "3.0.10"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.10.tgz#2ad3a7bed70f35b965707c092e5f30b327c290e5"
|
||||
integrity sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==
|
||||
|
@ -7546,11 +7564,21 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
|
|||
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
|
||||
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
|
||||
|
||||
fast-shallow-equal@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz#d4dcaf6472440dcefa6f88b98e3251e27f25628b"
|
||||
integrity sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==
|
||||
|
||||
fastest-levenshtein@^1.0.12:
|
||||
version "1.0.12"
|
||||
resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2"
|
||||
integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==
|
||||
|
||||
fastest-stable-stringify@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz#3757a6774f6ec8de40c4e86ec28ea02417214c76"
|
||||
integrity sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==
|
||||
|
||||
fastq@^1.13.0, fastq@^1.6.0:
|
||||
version "1.13.0"
|
||||
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c"
|
||||
|
@ -9190,6 +9218,11 @@ human-signals@^2.1.0:
|
|||
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
|
||||
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
|
||||
|
||||
hyphenate-style-name@^1.0.2:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d"
|
||||
integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==
|
||||
|
||||
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
|
||||
version "0.4.24"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||
|
@ -9312,6 +9345,13 @@ inline-style-parser@0.1.1:
|
|||
resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1"
|
||||
integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==
|
||||
|
||||
inline-style-prefixer@^6.0.0:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-6.0.1.tgz#c5c0e43ba8831707afc5f5bbfd97edf45c1fa7ae"
|
||||
integrity sha512-AsqazZ8KcRzJ9YPN1wMH2aNM7lkWQ8tSPrW5uDk1ziYwiAPWSZnUsC7lfZq+BDqLqz0B4Pho5wscWcJzVvRzDQ==
|
||||
dependencies:
|
||||
css-in-js-utils "^2.0.0"
|
||||
|
||||
inquirer@^7.0.0:
|
||||
version "7.3.3"
|
||||
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003"
|
||||
|
@ -10018,6 +10058,11 @@ jpeg-js@^0.4.0:
|
|||
resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.3.tgz#6158e09f1983ad773813704be80680550eff977b"
|
||||
integrity sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q==
|
||||
|
||||
js-cookie@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8"
|
||||
integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==
|
||||
|
||||
js-string-escape@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef"
|
||||
|
@ -11003,6 +11048,20 @@ nan@^2.12.1, nan@^2.14.2:
|
|||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee"
|
||||
integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==
|
||||
|
||||
nano-css@^5.3.1:
|
||||
version "5.3.4"
|
||||
resolved "https://registry.yarnpkg.com/nano-css/-/nano-css-5.3.4.tgz#40af6a83a76f84204f346e8ccaa9169cdae9167b"
|
||||
integrity sha512-wfcviJB6NOxDIDfr7RFn/GlaN7I/Bhe4d39ZRCJ3xvZX60LVe2qZ+rDqM49nm4YT81gAjzS+ZklhKP/Gnfnubg==
|
||||
dependencies:
|
||||
css-tree "^1.1.2"
|
||||
csstype "^3.0.6"
|
||||
fastest-stable-stringify "^2.0.2"
|
||||
inline-style-prefixer "^6.0.0"
|
||||
rtl-css-js "^1.14.0"
|
||||
sourcemap-codec "^1.4.8"
|
||||
stacktrace-js "^2.0.2"
|
||||
stylis "^4.0.6"
|
||||
|
||||
nanoid@^3.1.23, nanoid@^3.2.0:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35"
|
||||
|
@ -12870,6 +12929,31 @@ react-textarea-autosize@^8.3.0:
|
|||
use-composed-ref "^1.0.0"
|
||||
use-latest "^1.0.0"
|
||||
|
||||
react-universal-interface@^0.6.2:
|
||||
version "0.6.2"
|
||||
resolved "https://registry.yarnpkg.com/react-universal-interface/-/react-universal-interface-0.6.2.tgz#5e8d438a01729a4dbbcbeeceb0b86be146fe2b3b"
|
||||
integrity sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==
|
||||
|
||||
react-use@^17.3.2:
|
||||
version "17.3.2"
|
||||
resolved "https://registry.yarnpkg.com/react-use/-/react-use-17.3.2.tgz#448abf515f47c41c32455024db28167cb6e53be8"
|
||||
integrity sha512-bj7OD0/1wL03KyWmzFXAFe425zziuTf7q8olwCYBfOeFHY1qfO1FAMjROQLsLZYwG4Rx63xAfb7XAbBrJsZmEw==
|
||||
dependencies:
|
||||
"@types/js-cookie" "^2.2.6"
|
||||
"@xobotyi/scrollbar-width" "^1.9.5"
|
||||
copy-to-clipboard "^3.3.1"
|
||||
fast-deep-equal "^3.1.3"
|
||||
fast-shallow-equal "^1.0.0"
|
||||
js-cookie "^2.2.1"
|
||||
nano-css "^5.3.1"
|
||||
react-universal-interface "^0.6.2"
|
||||
resize-observer-polyfill "^1.5.1"
|
||||
screenfull "^5.1.0"
|
||||
set-harmonic-interval "^1.0.1"
|
||||
throttle-debounce "^3.0.1"
|
||||
ts-easing "^0.2.0"
|
||||
tslib "^2.1.0"
|
||||
|
||||
react@^17.0.1:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
|
||||
|
@ -13210,6 +13294,11 @@ requires-port@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
||||
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
|
||||
|
||||
resize-observer-polyfill@^1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
|
||||
integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
|
||||
|
||||
resolve-alpn@^1.0.0:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9"
|
||||
|
@ -13318,6 +13407,13 @@ rsvp@^4.8.4:
|
|||
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734"
|
||||
integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==
|
||||
|
||||
rtl-css-js@^1.14.0:
|
||||
version "1.15.0"
|
||||
resolved "https://registry.yarnpkg.com/rtl-css-js/-/rtl-css-js-1.15.0.tgz#680ed816e570a9ebccba9e1cd0f202c6a8bb2dc0"
|
||||
integrity sha512-99Cu4wNNIhrI10xxUaABHsdDqzalrSRTie4GeCmbGVuehm4oj+fIy8fTzB+16pmKe8Bv9rl+hxIBez6KxExTew==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.1.2"
|
||||
|
||||
run-async@^2.4.0:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
|
||||
|
@ -13435,6 +13531,11 @@ schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1:
|
|||
ajv "^6.12.5"
|
||||
ajv-keywords "^3.5.2"
|
||||
|
||||
screenfull@^5.1.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-5.2.0.tgz#6533d524d30621fc1283b9692146f3f13a93d1ba"
|
||||
integrity sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==
|
||||
|
||||
semver-diff@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b"
|
||||
|
@ -13530,6 +13631,11 @@ set-blocking@^2.0.0, set-blocking@~2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
||||
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
|
||||
|
||||
set-harmonic-interval@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz#e1773705539cdfb80ce1c3d99e7f298bb3995249"
|
||||
integrity sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==
|
||||
|
||||
set-value@^2.0.0, set-value@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
|
||||
|
@ -13788,6 +13894,11 @@ source-map-url@^0.4.0:
|
|||
resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56"
|
||||
integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==
|
||||
|
||||
source-map@0.5.6:
|
||||
version "0.5.6"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
|
||||
integrity sha1-dc449SvwczxafwwRjYEzSiu19BI=
|
||||
|
||||
source-map@0.7.3, source-map@^0.7.3, source-map@~0.7.2:
|
||||
version "0.7.3"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
|
||||
|
@ -13803,6 +13914,11 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
|
|||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||
|
||||
sourcemap-codec@^1.4.8:
|
||||
version "1.4.8"
|
||||
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
|
||||
integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
|
||||
|
||||
space-separated-tokens@^1.0.0:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899"
|
||||
|
@ -13883,6 +13999,13 @@ stable@^0.1.8:
|
|||
resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
|
||||
integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==
|
||||
|
||||
stack-generator@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/stack-generator/-/stack-generator-2.0.5.tgz#fb00e5b4ee97de603e0773ea78ce944d81596c36"
|
||||
integrity sha512-/t1ebrbHkrLrDuNMdeAcsvynWgoH/i4o8EGGfX7dEYDoTXOYVAkEpFdtshlvabzc6JlJ8Kf9YdFEoz7JkzGN9Q==
|
||||
dependencies:
|
||||
stackframe "^1.1.1"
|
||||
|
||||
stack-trace@^0.0.10:
|
||||
version "0.0.10"
|
||||
resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
|
||||
|
@ -13893,6 +14016,23 @@ stackframe@^1.1.1:
|
|||
resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.1.tgz#1033a3473ee67f08e2f2fc8eba6aef4f845124e1"
|
||||
integrity sha512-h88QkzREN/hy8eRdyNhhsO7RSJ5oyTqxxmmn0dzBIMUclZsjpfmrsg81vp8mjjAs2vAZ72nyWxRUwSwmh0e4xg==
|
||||
|
||||
stacktrace-gps@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/stacktrace-gps/-/stacktrace-gps-3.0.4.tgz#7688dc2fc09ffb3a13165ebe0dbcaf41bcf0c69a"
|
||||
integrity sha512-qIr8x41yZVSldqdqe6jciXEaSCKw1U8XTXpjDuy0ki/apyTn/r3w9hDAAQOhZdxvsC93H+WwwEu5cq5VemzYeg==
|
||||
dependencies:
|
||||
source-map "0.5.6"
|
||||
stackframe "^1.1.1"
|
||||
|
||||
stacktrace-js@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/stacktrace-js/-/stacktrace-js-2.0.2.tgz#4ca93ea9f494752d55709a081d400fdaebee897b"
|
||||
integrity sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==
|
||||
dependencies:
|
||||
error-stack-parser "^2.0.6"
|
||||
stack-generator "^2.0.5"
|
||||
stacktrace-gps "^3.0.4"
|
||||
|
||||
state-toggle@^1.0.0:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe"
|
||||
|
@ -14193,6 +14333,11 @@ stylehacks@^5.0.3:
|
|||
browserslist "^4.16.6"
|
||||
postcss-selector-parser "^6.0.4"
|
||||
|
||||
stylis@^4.0.6:
|
||||
version "4.0.13"
|
||||
resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.13.tgz#f5db332e376d13cc84ecfe5dace9a2a51d954c91"
|
||||
integrity sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag==
|
||||
|
||||
subscriptions-transport-ws@^0.9.18:
|
||||
version "0.9.19"
|
||||
resolved "https://registry.yarnpkg.com/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.19.tgz#10ca32f7e291d5ee8eb728b9c02e43c52606cdcf"
|
||||
|
@ -14642,6 +14787,11 @@ ts-dedent@^2.0.0, ts-dedent@^2.2.0:
|
|||
resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5"
|
||||
integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==
|
||||
|
||||
ts-easing@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/ts-easing/-/ts-easing-0.2.0.tgz#c8a8a35025105566588d87dbda05dd7fbfa5a4ec"
|
||||
integrity sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==
|
||||
|
||||
ts-node@^9:
|
||||
version "9.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d"
|
||||
|
@ -14674,7 +14824,7 @@ tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0:
|
|||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
||||
tslib@^2, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.3.0, tslib@~2.3.0:
|
||||
tslib@^2, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@~2.3.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
|
||||
integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
|
||||
|
|
Reference in New Issue