feat: responsive version (#113)

* feat: wip - responsive version

* chore(config): update eslint config

* fix: align drop zone footer

* fix: add prop for immutable colors

* fix: container width issue on tablet

* chore: change class name convention

* chore: add missing error styles on mobile

* style(viewport): add 100vh fix for safari

* style: update bottom info padding on mobile

* perf: remove getInitialProps function and dependencies

* chore(deps): update sharp to v0.25.0

* chore: delete unused hook

* docs: add @miguellteixeira as a contributor

* test(cypress): update page load wait

* feat(responsive): update code modal for mobile

* feat(responsive): update background images and light/dark toggle color

* feat(responsive): add about us modal on mobile

* feat(responsive): update sharable image

Co-authored-by: Miguel Teixeira <teixeira.silva.miguel@gmail.com>
This commit is contained in:
Rui Saraiva 2020-09-10 17:57:57 +01:00 committed by GitHub
parent e573eaee20
commit 20f009e848
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 1492 additions and 337 deletions

View File

@ -51,6 +51,16 @@
"code",
"review"
]
},
{
"login": "miguellteixeira",
"name": "Miguel Teixeira",
"avatar_url": "https://avatars1.githubusercontent.com/u/17954325?v=4",
"profile": "https://github.com/miguellteixeira",
"contributions": [
"code",
"review"
]
}
],
"contributorsPerLine": 7

View File

@ -28,6 +28,7 @@
"@typescript-eslint/member-delimiter-style": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/ban-ts-ignore": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-extra-semi": "off",

View File

@ -5,8 +5,14 @@
"stylelint-config-css-modules",
"stylelint-config-prettier"
],
"plugins": ["stylelint-prettier"],
"plugins": ["stylelint-scss", "stylelint-prettier"],
"rules": {
"prettier/prettier": true
"prettier/prettier": true,
"at-rule-no-unknown": [
true,
{
"ignoreAtRules": ["mixin", "include"]
}
]
}
}

View File

@ -7,7 +7,7 @@
A small online tool to help you generate your favicon in all the sizes and formats you need.
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-4-orange.svg?style=flat-square)](#contributors-)
[![All Contributors](https://img.shields.io/badge/all_contributors-5-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->
![Release](https://github.com/ruisaraiva19/favycon/workflows/Release/badge.svg)
![Lint](https://github.com/ruisaraiva19/favycon/workflows/Lint/badge.svg)
@ -110,14 +110,15 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<!-- markdownlint-disable -->
<table>
<tr>
<td align="center"><a href="https://ruisaraiva.com"><img src="https://avatars2.githubusercontent.com/u/7356098?v=4" width="100px;" alt=""/><br /><sub><b>Rui Saraiva</b></sub></a><br /><a href="#infra-ruisaraiva19" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/ruisaraiva19/favycon/commits?author=ruisaraiva19" title="Code">💻</a> <a href="https://github.com/ruisaraiva19/favycon/commits?author=ruisaraiva19" title="Documentation">📖</a> <a href="#question-ruisaraiva19" title="Answering Questions">💬</a> <a href="#maintenance-ruisaraiva19" title="Maintenance">🚧</a></td>
<td align="center"><a href="https://github.com/eduardoPinto12"><img src="https://avatars1.githubusercontent.com/u/45365656?v=4" width="100px;" alt=""/><br /><sub><b>Eduardo Pinto</b></sub></a><br /><a href="https://github.com/ruisaraiva19/favycon/commits?author=eduardoPinto12" title="Code">💻</a> <a href="https://github.com/ruisaraiva19/favycon/pulls?q=is%3Apr+reviewed-by%3AeduardoPinto12" title="Reviewed Pull Requests">👀</a></td>
<td align="center"><a href="https://github.com/otsugua"><img src="https://avatars2.githubusercontent.com/u/9093629?v=4" width="100px;" alt=""/><br /><sub><b>Augusto Lopes</b></sub></a><br /><a href="#design-otsugua" title="Design">🎨</a></td>
<td align="center"><a href="https://rgllm.com"><img src="https://avatars3.githubusercontent.com/u/9056941?v=4" width="100px;" alt=""/><br /><sub><b>Rogério Moreira</b></sub></a><br /><a href="https://github.com/ruisaraiva19/favycon/commits?author=rgllm" title="Code">💻</a> <a href="https://github.com/ruisaraiva19/favycon/pulls?q=is%3Apr+reviewed-by%3Argllm" title="Reviewed Pull Requests">👀</a></td>
<td align="center"><a href="https://ruisaraiva.com"><img src="https://avatars2.githubusercontent.com/u/7356098?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rui Saraiva</b></sub></a><br /><a href="#infra-ruisaraiva19" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/toolslab/favycon/commits?author=ruisaraiva19" title="Code">💻</a> <a href="https://github.com/toolslab/favycon/commits?author=ruisaraiva19" title="Documentation">📖</a> <a href="#question-ruisaraiva19" title="Answering Questions">💬</a> <a href="#maintenance-ruisaraiva19" title="Maintenance">🚧</a></td>
<td align="center"><a href="https://github.com/eduardoPinto12"><img src="https://avatars1.githubusercontent.com/u/45365656?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Eduardo Pinto</b></sub></a><br /><a href="https://github.com/toolslab/favycon/commits?author=eduardoPinto12" title="Code">💻</a> <a href="https://github.com/toolslab/favycon/pulls?q=is%3Apr+reviewed-by%3AeduardoPinto12" title="Reviewed Pull Requests">👀</a></td>
<td align="center"><a href="https://github.com/otsugua"><img src="https://avatars2.githubusercontent.com/u/9093629?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Augusto Lopes</b></sub></a><br /><a href="#design-otsugua" title="Design">🎨</a></td>
<td align="center"><a href="https://rgllm.com"><img src="https://avatars3.githubusercontent.com/u/9056941?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rogério Moreira</b></sub></a><br /><a href="https://github.com/toolslab/favycon/commits?author=rgllm" title="Code">💻</a> <a href="https://github.com/toolslab/favycon/pulls?q=is%3Apr+reviewed-by%3Argllm" title="Reviewed Pull Requests">👀</a></td>
<td align="center"><a href="https://github.com/miguellteixeira"><img src="https://avatars1.githubusercontent.com/u/17954325?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Miguel Teixeira</b></sub></a><br /><a href="https://github.com/toolslab/favycon/commits?author=miguellteixeira" title="Code">💻</a> <a href="https://github.com/toolslab/favycon/pulls?q=is%3Apr+reviewed-by%3Amiguellteixeira" title="Reviewed Pull Requests">👀</a></td>
</tr>
</table>
<!-- markdownlint-enable -->
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->

View File

@ -2,4 +2,5 @@
.root {
padding: 0;
overflow: hidden;
}

View File

@ -10,18 +10,24 @@
border-radius: 4px;
transition: all 0.2s ease;
@include breakpoint-md {
padding: 9px 12px;
}
&:hover,
&:focus,
&:active {
outline: none;
}
&:hover {
transform: translate3d(0, -2px, 0);
}
@media (pointer: fine) {
&:hover {
transform: translate3d(0, -2px, 0);
}
&:active {
transform: translate3d(0, 0, 0);
&:active {
transform: translate3d(0, 0, 0);
}
}
}
@ -52,14 +58,34 @@
padding: 5px 0;
background: transparent;
border: 1px solid transparent;
@include breakpoint-md {
padding: 9px 0;
}
}
:global(.dark-mode) .transparent {
@include breakpoint-md {
background: $dark-grey;
}
}
.modalClose {
composes: base;
padding: 5px 16px;
background-color: $off-white;
border: 1px solid $light-grey;
border-radius: 18px;
}
.regularTransparent {
composes: transparent;
composes: base;
padding: 0;
font-size: $font-size-regular-body;
line-height: $line-height-regular-body;
text-decoration: none;
background: transparent;
border: 1px solid transparent;
border: 0;
}
@ -89,6 +115,10 @@
:global(.dark-mode) .gray {
color: $grey-dark;
@include breakpoint-md {
color: $off-white-dark;
}
}
.white {
@ -150,3 +180,13 @@
border-color: $green-hover;
}
}
.bgDarkGray {
background: $dark-grey;
border-color: $dark-grey;
&:hover {
background: $darker-grey;
border-color: $darker-grey;
}
}

View File

@ -6,10 +6,10 @@ import styles from './index.module.scss'
type ButtonProps = {
children: PropTypes.ReactNodeLike
variant: 'primary' | 'transparent' | 'regularTransparent'
variant: 'primary' | 'transparent' | 'regularTransparent' | 'modalClose'
weight: 'regular' | 'medium' | 'semiBold' | 'bold'
color: 'black' | 'gray' | 'white' | 'link'
background: 'bgLink' | 'bgGreen'
background: 'bgLink' | 'bgGreen' | 'bgDarkGray'
}
const Button = ({

View File

@ -72,19 +72,23 @@
.sun,
.moon {
path {
fill: #657584;
fill: $grey-dark;
}
}
}
:global(.light-mode) .label {
&:hover path {
fill: $link;
@media (pointer: fine) {
&:hover path {
fill: $link;
}
}
}
:global(.dark-mode) .label {
&:hover path {
fill: $link-dark;
@media (pointer: fine) {
&:hover path {
fill: $link-dark;
}
}
}

View File

@ -9,10 +9,28 @@
border-radius: 8px;
box-shadow: 0 2px 4px rgba($black, 0.12);
transition: background 0.2s ease;
@include breakpoint-md {
max-width: 100%;
height: 100%;
border-radius: 0;
}
&.transparent {
@include breakpoint-md {
background: transparent;
}
}
}
:global(.dark-mode) .root {
background: $dark-black;
&.transparent {
@include breakpoint-md {
background: transparent;
}
}
}
.container {
@ -25,6 +43,21 @@
pointer-events: none;
opacity: 0.32;
}
@include breakpoint-md {
display: flex;
flex-direction: column;
width: 100%;
height: calc(100% - 68px);
margin-top: 68px;
border-radius: 0;
}
&.transparent {
@include breakpoint-md {
padding: 0;
}
}
}
.dashed {
@ -67,6 +100,13 @@
border-radius: 6px;
transition: background 0.2s ease;
@include breakpoint-md {
flex-grow: 1;
margin-bottom: 0;
background: transparent;
border-radius: 0;
}
&:hover {
cursor: pointer;
@ -79,6 +119,10 @@
:global(.dark-mode) .dropZoneWrapper {
background: $dark-grey;
@include breakpoint-md {
background: transparent;
}
&:hover {
.dashed rect {
stroke: $off-white-dark;
@ -95,6 +139,32 @@
}
}
.dropZoneFooter {
transition: background 0.2s ease;
@include breakpoint-md {
padding: 16px 24px 24px;
padding-bottom: env(safe-area-inset-bottom);
background: rgba($white, 0.88);
border-radius: 16px 16px 0 0;
box-shadow: 0 -2px 4px rgba($black, 0.12);
@supports (padding: max(1px)) {
padding-bottom: max(24px, env(safe-area-inset-bottom));
}
p {
font-size: 15px;
}
}
}
:global(.dark-mode) .dropZoneFooter {
@include breakpoint-md {
background: rgba($dark-black, 0.88);
}
}
.dropZone {
position: relative;
z-index: 2;
@ -126,25 +196,56 @@
&.dragActive {
height: 48px;
}
@include breakpoint-md {
font-size: 16px;
font-weight: 600;
line-height: 28px;
color: $off-white-dark;
}
&.mobileUploadText {
@include breakpoint-md-up {
display: none;
}
}
&.desktopUploadText {
/* smartphones, touchscreens */
@media (hover: none) and (pointer: coarse) {
display: none;
}
@include breakpoint-md {
display: none;
}
}
}
:global(.dark-mode) .imageUploadText {
color: $white-dark;
@include breakpoint-md {
color: $off-white-dark;
}
}
.info {
display: flex;
align-items: center;
align-items: flex-start;
margin-top: 8px;
letter-spacing: 0.2px;
svg {
flex: 0 0 20px;
margin-right: 8px;
@include breakpoint-md {
height: 24px;
}
}
strong {
padding: 0 4px;
// padding: 0 4px;
font-weight: 700;
}
}
@ -209,6 +310,7 @@
.imageInfo {
display: flex;
flex-wrap: wrap;
padding: 16px 0;
border-top: 1px solid $light-grey;
transition: all 0.2s ease;
@ -222,17 +324,16 @@
padding: 8px 0 16px;
border-top: 1px solid $light-grey;
transition: all 0.2s ease;
@include breakpoint-md {
padding: 24px 0;
}
}
:global(.dark-mode) .imageOptionsWrapper {
border-top: 1px solid $dark-grey;
}
.imageOptions {
display: flex;
padding: 8px 0 16px;
}
.imageInfoItem {
display: flex;
align-items: center;
@ -241,6 +342,24 @@
span {
margin-right: 8px;
}
@include breakpoint-md {
margin-top: 8px;
margin-bottom: 8px;
}
}
.imageOptions {
display: flex;
flex-wrap: wrap;
padding: 8px 0 16px;
.imageInfoItem {
@include breakpoint-md {
margin-top: 0;
margin-bottom: 24px;
}
}
}
.pwaCheck {
@ -259,6 +378,10 @@
align-items: center;
justify-content: center;
margin: 16px 0 12px;
@include breakpoint-md {
align-items: flex-end;
}
}
.preview {
@ -269,15 +392,39 @@
background: $white;
box-shadow: 0 2px 4px rgba($black, 0.12);
@include breakpoint-md {
width: 96px;
height: 96px;
margin-right: 0;
}
img {
width: 40px;
height: 40px;
object-fit: contain;
@include breakpoint-md {
width: 96px;
height: 96px;
}
}
&.circle,
&.circle img {
border-radius: 24px;
@include breakpoint-md {
width: 52px;
height: 52px;
border-radius: 26px;
}
}
&.circle {
@include breakpoint-md {
z-index: 1;
transform: translate3d(21px, 3px, 0);
}
}
&.square,
@ -285,12 +432,31 @@
width: 48px;
height: 48px;
border-radius: 4px;
@include breakpoint-md {
width: 96px;
height: 96px;
border-radius: 8px;
}
}
&.rounded,
&.rounded img {
margin-right: 0;
border-radius: 14px;
@include breakpoint-md {
width: 40px;
height: 40px;
border-radius: 13px;
}
}
&.rounded {
@include breakpoint-md {
z-index: 1;
transform: translate3d(-12px, 3px, 0);
}
}
}
@ -339,14 +505,32 @@
padding: 23px 24px 24px 24px;
border-top: 1px solid $light-grey;
transition: all 0.2s ease;
&.spaceBetween {
justify-content: space-between;
}
@include breakpoint-md {
flex-direction: column-reverse;
padding: 11px 24px 12px 24px;
border-top: 1px solid transparent;
> * {
margin-bottom: 12px;
}
}
@include breakpoint-xs {
align-items: stretch;
}
}
:global(.dark-mode) .imageFooter {
border-top: 1px solid $dark-grey;
}
.spaceBetween {
justify-content: space-between;
@include breakpoint-md {
border-top: 1px solid transparent;
}
}
.makeNewOne {
@ -377,12 +561,20 @@
.imageGenerate {
margin-left: 24px;
@include breakpoint-md {
margin-left: 0;
}
}
.modalContainer {
max-width: 730px;
height: 100%;
margin: 0 auto;
@include breakpoint-md {
padding-top: 20px;
}
}
.modalHeader {
@ -392,13 +584,23 @@
margin-bottom: 10px;
}
.modalCode {
height: 100%;
max-height: 488px;
padding: 28px;
color: $white;
background: $darker-grey;
border-radius: 8px;
.modalHeaderMobile {
display: none;
padding: 36px 32px 8px;
margin-bottom: 0;
@include breakpoint-md {
display: flex;
background: $dark-black;
border-top-left-radius: 20px;
border-top-right-radius: 20px;
}
}
.modalHeaderDesktop {
@include breakpoint-md {
display: none;
}
}
.overlay {
@ -422,8 +624,8 @@
width: 100%;
max-width: 730px;
height: 100%;
max-height: 536px;
padding: 0;
max-height: 538px;
padding: 2px 0 0;
overflow: auto;
background: transparent;
border: none;
@ -431,6 +633,11 @@
outline: none;
transform: translate(-50%, -50%);
-webkit-overflow-scrolling: touch;
@include breakpoint-md {
max-height: 100vh;
padding: 0;
}
}
.copyWrapper {
@ -460,3 +667,73 @@
:global(.dark-mode) .copyWrapper::before {
color: $off-white-dark;
}
.modalCode {
position: relative;
height: 100%;
max-height: 488px;
padding: 28px;
color: $white;
background: $dark-black;
border-radius: 8px;
@include breakpoint-md {
max-height: calc(100% - 84px);
border-radius: 0;
}
&::before {
z-index: 2;
@include breakpoint-md {
position: absolute;
right: -1px;
bottom: 28px;
left: 0;
height: 136px;
content: '';
background: linear-gradient(to bottom, rgba($dark-black, 0), rgba($dark-black, 1));
}
}
.copyWrapper {
z-index: 3;
display: none;
@include breakpoint-md {
position: absolute;
right: 24px;
bottom: 80px;
left: 24px;
display: block;
button {
width: 100%;
}
}
}
pre {
position: relative;
z-index: 1;
@include breakpoint-md {
max-height: calc(100% - 68px);
padding-bottom: 104px;
}
}
pre code {
@include breakpoint-md {
white-space: pre-wrap;
}
}
}
.modalCodeTitle {
display: none;
@include breakpoint-md {
display: block;
margin-bottom: 20px;
}
}

View File

@ -23,6 +23,8 @@ import { Button } from 'components/button'
import { SvgCheck } from 'components/svgs/svg-check'
import { SvgError } from 'components/svgs/svg-error'
import { Checkbox } from 'components/checkbox'
import { useToggle } from 'hooks/use-toggle'
import { useMediaQueryContext } from 'components/media-query-provider'
import styles from './index.module.scss'
@ -31,11 +33,12 @@ const Clipboard = dynamic(() => import('react-clipboard.js'))
type DragAndDropProps = {
onFile: (hasFile: boolean) => void
onGenerate: (image: File, pwa: boolean) => Promise<ArrayBuffer>
onGenerate: (image: File, pwa: boolean, darkMode: boolean) => Promise<ArrayBuffer>
onError: (message: string) => void
}
const DragAndDrop = ({ onFile, onGenerate, onError }: DragAndDropProps) => {
const { isMobile } = useMediaQueryContext()
const [imageSizes, setImageSizes] = useState({ width: 0, height: 0 })
const [image, setImage] = useState<File>()
const [imageBase64, setImageBase64] = useState('')
@ -48,8 +51,8 @@ const DragAndDrop = ({ onFile, onGenerate, onError }: DragAndDropProps) => {
const [is310px, setIs310px] = useState(false)
const [is512px, setIs512px] = useState(false)
const [isLoading, setIsLoading] = useState(false)
const [pwa, setPwa] = useState(false)
const [darkMode, setDarkMode] = useState(false)
const [pwa, togglePwa] = useToggle(false)
const [darkMode, toggleDarkMode] = useToggle(false)
const [zipData, setZipData] = useState<ArrayBuffer>()
const [isModalOpen, setIsModalOpen] = useState(false)
const [copied, setCopied] = useState(false)
@ -84,10 +87,11 @@ const DragAndDrop = ({ onFile, onGenerate, onError }: DragAndDropProps) => {
if (image) {
reader.readAsDataURL(image)
const matches = /(.+)(\..+)$/.exec(image.name) as RegExpExecArray
const name = matches[1].length > 30 ? `${matches[1].slice(0, 30)}..` : matches[1].slice(0, 30)
const length = isMobile ? 15 : 30
const name = matches[1].length > length ? `${matches[1].slice(0, length)}..` : matches[1].slice(0, length)
setImageData({ name, extension: matches[2] })
}
}, [image, zipData, generateImgFromCanvas])
}, [image, zipData, generateImgFromCanvas, isMobile])
useEffect(() => {
if (!image) {
@ -110,10 +114,10 @@ const DragAndDrop = ({ onFile, onGenerate, onError }: DragAndDropProps) => {
const generateFavicon = async (file: File) => {
try {
setIsLoading(true)
const zip = await onGenerate(file, pwa)
const zip = await onGenerate(file, pwa, darkMode)
setZipData(zip)
} catch (error) {
console.log(error)
onError(error.message || 'Something went wrong. Please try again.')
} finally {
setIsLoading(false)
}
@ -171,8 +175,12 @@ const DragAndDrop = ({ onFile, onGenerate, onError }: DragAndDropProps) => {
const [isHover, setIsHover] = useState(false)
return (
<div className={styles.root}>
<div className={classnames(styles.container, { [styles.loading]: isLoading })}>
<div className={classnames(styles.root, { [styles.transparent]: !image })}>
<div
className={classnames(styles.container, {
[styles.loading]: isLoading,
[styles.transparent]: !image,
})}>
{!image && !zipData && (
<>
<div
@ -188,7 +196,22 @@ const DragAndDrop = ({ onFile, onGenerate, onError }: DragAndDropProps) => {
<Typography
variant="regularBody"
weight="medium"
className={classnames(styles.imageUploadText, { [styles.dragActive]: isDragActive })}
className={classnames(styles.imageUploadText, styles.mobileUploadText, {
[styles.dragActive]: isDragActive,
})}
data-cy="drag-and-drop-text">
<span>
Generate all the sizes for your
<br />
favicon. Tap to upload a file.
</span>
</Typography>
<Typography
variant="regularBody"
weight="medium"
className={classnames(styles.imageUploadText, styles.desktopUploadText, {
[styles.dragActive]: isDragActive,
})}
data-cy="drag-and-drop-text">
<CSSTransition in={!isDragActive} timeout={200} classNames="collapse" unmountOnExit>
<span>Drag &amp;&nbsp;</span>
@ -211,13 +234,17 @@ const DragAndDrop = ({ onFile, onGenerate, onError }: DragAndDropProps) => {
</Typography>
</div>
</div>
{/* <button onClick={() => setInProp(true)}>toggle</button> */}
<Typography variant="regularBody" weight="medium" className={styles.info}>
<SvgInfo /> We recommend a square <strong>PNG</strong> or <strong>SVG</strong> with at least 310px
</Typography>
<Typography variant="regularBody" weight="medium" className={styles.info}>
<SvgInfo /> No data or images are stored
</Typography>
<div className={styles.dropZoneFooter}>
<Typography variant="regularBody" weight="medium" className={styles.info}>
<SvgInfo />{' '}
<span>
We recommend a square <strong>PNG</strong> or <strong>SVG</strong> with at least 310px
</span>
</Typography>
<Typography variant="regularBody" weight="medium" className={styles.info}>
<SvgInfo /> No data or images are stored
</Typography>
</div>
</>
)}
{image && !zipData && (
@ -279,7 +306,7 @@ const DragAndDrop = ({ onFile, onGenerate, onError }: DragAndDropProps) => {
name="pwa"
id="pwa"
disabled={PWADisabled}
onChange={() => setPwa(!pwa)}
onChange={togglePwa}
data-cy="preview-pwa-compatible">
<Typography variant="regularBody" weight="semiBold" muted={PWADisabled}>
PWA compatible
@ -295,13 +322,13 @@ const DragAndDrop = ({ onFile, onGenerate, onError }: DragAndDropProps) => {
name="dark"
id="dark"
disabled
onChange={() => setDarkMode(!darkMode)}
onChange={toggleDarkMode}
data-cy="preview-dark-mode-version">
<Typography variant="regularBody" weight="semiBold" muted>
Dark Mode version
</Typography>
<Typography variant="footer" weight="semiBold" color="green" muted>
Available soon
Coming soon
</Typography>
</Checkbox>
</div>
@ -384,7 +411,19 @@ const DragAndDrop = ({ onFile, onGenerate, onError }: DragAndDropProps) => {
closeTimeoutMS={200}
contentLabel="Code generated">
<div className={styles.modalContainer}>
<div className={styles.modalHeader}>
<div className={classnames(styles.modalHeader, styles.modalHeaderMobile)}>
<Typography variant="extraLargeTitle" weight="extraBold" color="white" colorImmutable>
Code
</Typography>
<Button
variant="modalClose"
color="white"
background="bgDarkGray"
onClick={() => setIsModalOpen(false)}>
Close
</Button>
</div>
<div className={classnames(styles.modalHeader, styles.modalHeaderDesktop)}>
<Typography variant="title" weight="bold">
Insert the following code in the &lt;head&gt; section of your pages:
</Typography>
@ -400,7 +439,25 @@ const DragAndDrop = ({ onFile, onGenerate, onError }: DragAndDropProps) => {
</Clipboard>
</div>
<div className={styles.modalCode}>
<Typography
variant="title"
weight="bold"
color="white"
colorImmutable
className={styles.modalCodeTitle}>
Insert the following code in the &lt;head&gt; section of your pages:
</Typography>
<CodeHighlight template={headTemplate(undefined, isSvg, pwa)} />
<Clipboard
component="div"
data-clipboard-text={headTemplate(undefined, isSvg, pwa)}
onSuccess={onCopy}>
<div className={classnames(styles.copyWrapper)}>
<Button color="white" background="bgLink">
{copied ? 'Copied!' : 'Copy code'}
</Button>
</div>
</Clipboard>
</div>
</div>
</Modal>

View File

@ -4,6 +4,7 @@
position: absolute;
top: 26px;
right: 72px;
z-index: 10;
display: flex;
align-items: center;
padding: 6px 13px 6px 16px;
@ -11,6 +12,21 @@
border-radius: 8px;
box-shadow: 0 2px 4px rgba($black, 0.12);
@include breakpoint-md {
top: 13px;
right: 12px;
left: 12px;
justify-content: center;
max-width: 400px;
margin: auto;
}
.content {
@include breakpoint-md {
font-size: 14px;
}
}
svg {
margin-left: 13px;
}

View File

@ -33,7 +33,12 @@ const FavyconError = ({ error, clearError }: FavyconErrorProps) => {
return (
<CSSTransition in={showError} timeout={300} classNames="error" unmountOnExit>
<div className={classnames(styles.error)}>
<Typography variant="regularBody" color="white" weight="semiBold">
<Typography
className={classnames(styles.content)}
variant="regularBody"
color="white"
colorImmutable={true}
weight="semiBold">
{error}
</Typography>
<svg height={20} width={20}>

View File

@ -1,8 +1,50 @@
@import '../../styles/variables.scss';
.root {
position: relative;
width: 100%;
max-width: 350px;
@include breakpoint-md {
position: absolute;
top: 32px;
right: 72px;
z-index: 3;
display: block;
width: 80px;
max-width: 100%;
}
}
.bodyMobile {
display: none;
@include breakpoint-md {
display: block;
}
}
.bodyDesktop {
@include breakpoint-md {
display: none;
}
}
.modalBodyScroll {
height: calc(100% - 96px);
overflow: auto;
}
.button {
color: $black !important;
background: $light-grey !important;
border: 1px solid $light-grey !important;
}
:global(.dark-mode) .button {
color: $off-white-dark !important;
background: $dark-grey !important;
border: 1px solid $dark-grey !important;
}
.firstParagraph {
@ -14,11 +56,15 @@
margin-top: 16px;
margin-bottom: 60px;
letter-spacing: 0.2px;
@include breakpoint-md {
margin-bottom: 24px;
}
}
:global(.dark-mode) .firstParagraph,
:global(.dark-mode) .secondParagraph {
color: $white-dark;
color: $white-dark !important;
}
.peopleButton {
@ -47,6 +93,10 @@
color: $link;
}
}
@include breakpoint-md {
margin-top: 12px;
}
}
:global(.dark-mode) .footer {
@ -91,27 +141,83 @@
box-shadow: 0 2px 4px rgba($black, 0.12);
transform: translate(-50%, -50%);
-webkit-overflow-scrolling: touch;
@include breakpoint-md {
height: 100%;
max-height: 100vh;
padding-top: 20px;
background: transparent;
border-radius: 0;
}
}
:global(.dark-mode) .content {
background: $dark-black;
@include breakpoint-md {
background: transparent;
}
}
.modalContainer {
max-width: 572px;
padding: 0 16px;
margin: 0 auto;
background: $white;
@include breakpoint-md {
height: 100%;
padding: 0;
border-top-left-radius: 20px;
border-top-right-radius: 20px;
> * {
padding: 0 32px;
}
}
}
:global(.dark-mode) .modalContainer {
background: $dark-black;
}
.modalHeaderTop {
display: flex;
align-items: center;
justify-content: space-between;
padding: 28px 0 16px;
}
.modalHeaderMobile {
display: none;
@include breakpoint-md {
display: block;
}
}
.modalHeader {
padding-top: 48px;
text-align: center;
@include breakpoint-md {
text-align: left;
}
}
.logoMobile {
width: 52px;
height: 52px;
}
.logo {
width: 96px;
height: 96px;
margin-bottom: 16px;
@include breakpoint-md {
display: none;
}
}
.title {
@ -122,6 +228,12 @@
margin-bottom: 24px;
}
:global(.dark-mode) .subTitle {
@include breakpoint-md {
color: $white-dark !important;
}
}
.hr {
padding: 0;
margin: 0;
@ -138,6 +250,10 @@
display: flex;
width: calc(50% - 15px);
margin-top: 24px;
@include breakpoint-xs {
width: 100%;
}
}
.personAvatar {
@ -145,6 +261,12 @@
margin-right: 16px;
}
:global(.dark-mode) .personRole {
@include breakpoint-md {
color: $white-dark !important;
}
}
.personTwitter {
color: #55acee;
text-decoration: none;
@ -180,4 +302,8 @@
padding-bottom: 48px;
margin-top: 12px;
text-align: center;
@include breakpoint-md {
text-align: left;
}
}

View File

@ -8,6 +8,7 @@ import { SvgTwitter } from 'components/svgs/svg-twitter'
import styles from './index.module.scss'
import { SvgFavycon } from 'components/svgs/svg-favycon'
import { Button } from 'components/button'
const Modal = dynamic(() => import('react-modal'))
@ -34,30 +35,40 @@ const people = [
},
]
const FavyconInfo = () => {
const FavyconInfo = ({
className,
...props
}: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>) => {
const [isModalOpen, setIsModalOpen] = useState(false)
return (
<div className={styles.root}>
<ToolTitle />
<Typography variant="largeBody" weight="medium" className={styles.firstParagraph}>
A small online tool to help you generate your favicon in all the sizes and formats you need.
</Typography>
<Typography variant="largeBody" weight="medium" className={styles.secondParagraph}>
Just drag &amp; drop an image and you will then get a downloadable file alongside some documentation on how to
add the favicons.
</Typography>
<hr />
<Typography variant="footer" weight="semiBold" color="gray" className={styles.footer}>
Created by{' '}
<button className={styles.peopleButton} onClick={() => setIsModalOpen(true)}>
{people.length} people
</button>{' '}
on their 2020s worldwide quarantine. Background image from{' '}
<a href="https://unsplash.com/photos/bBiuSdck8tU" target="_blank" rel="noopener noreferrer">
Unsplash
</a>
.
</Typography>
<div className={classnames(styles.root, className)} {...props}>
<div className={styles.bodyMobile}>
<Button variant="modalClose" className={styles.button} onClick={() => setIsModalOpen(true)}>
About
</Button>
</div>
<div className={styles.bodyDesktop}>
<ToolTitle />
<Typography variant="largeBody" weight="medium" className={styles.firstParagraph}>
A small online tool to help you generate your favicon in all the sizes and formats you need.
</Typography>
<Typography variant="largeBody" weight="medium" className={styles.secondParagraph}>
Just drag &amp; drop an image and you will then get a downloadable file alongside some documentation on how to
add the favicons.
</Typography>
<hr />
<Typography variant="footer" weight="semiBold" color="gray" className={styles.footer}>
Created by{' '}
<button className={styles.peopleButton} onClick={() => setIsModalOpen(true)}>
{people.length} people
</button>{' '}
on their 2020s worldwide quarantine. Background image from{' '}
<a href="https://unsplash.com" target="_blank" rel="noopener noreferrer">
Unsplash
</a>
.
</Typography>
</div>
<Modal
ariaHideApp={false}
isOpen={isModalOpen}
@ -67,64 +78,91 @@ const FavyconInfo = () => {
closeTimeoutMS={200}
contentLabel="About Us">
<div className={styles.modalContainer}>
<div className={styles.modalHeader}>
{/* <img src="/favicon.svg" alt="Favycon logo" className={styles.logo} /> */}
<SvgFavycon className={styles.logo} />
<Typography variant="largeTitle" weight="bold" className={styles.title}>
Behind the curtains
</Typography>
<Typography variant="largeBody" weight="medium" className={styles.subTitle}>
For new updates be sure to follow these guys on Twitter.
</Typography>
<div className={styles.modalHeaderMobile}>
<div className={styles.modalHeaderTop}>
<SvgFavycon className={styles.logoMobile} />
<Button variant="modalClose" className={styles.button} onClick={() => setIsModalOpen(false)}>
Close
</Button>
</div>
</div>
<hr className={styles.hr} />
<div className={styles.people}>
{people.map((person) => (
<div key={person.screenName} className={styles.person}>
<div className={styles.personAvatar}>
<LazyImage
src={`/images/people/${person.screenName}@1x.png`}
srcRetina={`/images/people/${person.screenName}@2x.png`}
alt={person.name}
aspectRatio="56/56"
/>
</div>
<div>
<Typography variant="largeBody" weight="semiBold">
{person.name}
</Typography>
<Typography variant="regularBody" weight="medium">
{person.role}
</Typography>
<a
href={`https://twitter.com/${person.screenName}`}
className={styles.personTwitter}
target="_blank"
rel="noopener noreferrer">
<Typography variant="footer" weight="semiBold">
<SvgTwitter /> {person.screenName}
<div className={styles.modalBodyScroll}>
<div className={styles.modalHeaderMobile}>
<ToolTitle hideLogo small />
<Typography variant="largeBody" weight="medium" className={styles.firstParagraph}>
A small online tool to help you generate your favicon in all the sizes and formats you need.
</Typography>
<Typography variant="largeBody" weight="medium" className={styles.secondParagraph}>
Just drag &amp; drop an image and you will then get a downloadable file alongside some documentation on
how to add the favicons.
</Typography>
<hr className={styles.hr} />
<Typography variant="footer" weight="semiBold" color="gray" className={styles.footer}>
Background image from{' '}
<a href="https://unsplash.com" target="_blank" rel="noopener noreferrer">
Unsplash
</a>
.
</Typography>
</div>
<div className={styles.modalHeader}>
<SvgFavycon className={styles.logo} />
<Typography variant="largeTitle" weight="bold" className={styles.title}>
Behind the curtains
</Typography>
<Typography variant="largeBody" weight="medium" className={styles.subTitle}>
For new updates be sure to follow these guys on Twitter.
</Typography>
</div>
<hr className={styles.hr} />
<div className={styles.people}>
{people.map((person) => (
<div key={person.screenName} className={styles.person}>
<div className={styles.personAvatar}>
<LazyImage
src={`/images/people/${person.screenName}@1x.png`}
srcRetina={`/images/people/${person.screenName}@2x.png`}
alt={person.name}
aspectRatio="56/56"
/>
</div>
<div>
<Typography variant="largeBody" weight="semiBold">
{person.name}
</Typography>
</a>
<Typography variant="regularBody" weight="medium" className={styles.personRole}>
{person.role}
</Typography>
<a
href={`https://twitter.com/${person.screenName}`}
className={styles.personTwitter}
target="_blank"
rel="noopener noreferrer">
<Typography variant="footer" weight="semiBold">
<SvgTwitter /> {person.screenName}
</Typography>
</a>
</div>
</div>
</div>
))}
</div>
<hr className={styles.hr} />
<div className={classnames(styles.footer, styles.modalFooter)}>
<Typography variant="footer" weight="semiBold" color="gray">
Project on{' '}
<a
className={styles.repo}
href="https://github.com/ruisaraiva19/favycon"
target="_blank"
rel="noopener noreferrer">
GitHub
</a>
. Have feedback? Send it to{' '}
<a className={styles.contact} href="mailto:hello@favycon.app">
hello@favycon.app
</a>
</Typography>
))}
</div>
<hr className={styles.hr} />
<div className={classnames(styles.footer, styles.modalFooter)}>
<Typography variant="footer" weight="semiBold" color="gray">
Project on{' '}
<a
className={styles.repo}
href="https://github.com/ruisaraiva19/favycon"
target="_blank"
rel="noopener noreferrer">
GitHub
</a>
. Have feedback? Send it to{' '}
<a className={styles.contact} href="mailto:hello@favycon.app">
hello@favycon.app
</a>
</Typography>
</div>
</div>
</div>
</Modal>

View File

@ -8,6 +8,11 @@
width: 100%;
max-width: 540px;
padding: 41px 0 0;
@include breakpoint-md {
max-width: 100%;
padding: 0;
}
}
.background {
@ -28,10 +33,34 @@
bottom: 0;
left: 0;
z-index: 0;
content: '';
content: ' ';
background: rgba($black, 0.16);
border-radius: 8px;
}
@include breakpoint-md {
top: 0;
bottom: 0;
border-radius: 0;
transform: rotate(0);
&::after {
background: rgba($black, 0.56);
border-radius: 0;
}
}
}
.mobileBackground {
@include breakpoint-md-up {
display: none;
}
}
.desktopBackground {
@include breakpoint-md {
display: none;
}
}
.image {
@ -42,11 +71,22 @@
width: 185px;
height: 109px;
opacity: 1;
transition: opacity 0.2s ease-in-out;
transform: translate(100%, -100%);
transition: all 0.2s ease-in-out;
transform: translate(160px, -96px);
&.hide {
pointer-events: none;
visibility: hidden;
opacity: 0;
}
@media screen and (width >= 1280px) {
transform: translate(100%, -100%);
}
@include breakpoint-lg {
pointer-events: none;
visibility: hidden;
opacity: 0;
}
}

File diff suppressed because one or more lines are too long

View File

@ -8,6 +8,11 @@
height: 68px;
padding: 20px 20px 0 20px;
margin: 0 auto;
@include breakpoint-md {
height: 74px;
padding: 26px 26px 0 26px;
}
}
.header {
@ -15,6 +20,16 @@
align-items: center;
justify-content: flex-end;
height: 100%;
@include breakpoint-md {
justify-content: space-between;
}
}
.logo {
@include breakpoint-md-up {
display: none;
}
}
.item {
@ -23,14 +38,30 @@
box-shadow: 0 0 10px rgba($off-white, 0.5);
transition: all 0.2s ease;
@include breakpoint-md {
background: transparent;
box-shadow: none;
}
a {
display: flex;
align-items: center;
justify-content: center;
}
&:first-child {
svg {
width: 48px;
}
}
}
:global(.dark-mode) .item {
background: $darker-black;
box-shadow: 0 0 10px rgba($darker-black, 0.5);
@include breakpoint-md {
background: transparent;
box-shadow: none;
}
}

View File

@ -1,5 +1,7 @@
import React from 'react'
import classnames from 'classnames'
import { DarkModeToggle } from 'components/dark-mode-toggle'
import { SvgFavycon } from 'components/svgs/svg-favycon'
import { Sticky } from 'components/sticky'
import styles from './index.module.scss'
@ -10,6 +12,9 @@ const Header = () => {
<div className={styles.root}>
<div className={styles.container}>
<header className={styles.header}>
<div className={classnames(styles.item, styles.logo)}>
<SvgFavycon />
</div>
<div className={styles.item}>
<DarkModeToggle />
</div>

View File

@ -3,6 +3,11 @@
.root {
position: relative;
width: 100%;
&.stretch {
height: 100%;
padding-bottom: 0 !important;
}
}
.image {

View File

@ -1,6 +1,7 @@
import React, { useRef, useEffect } from 'react'
import { LazyImageFull, ImageState } from 'react-lazy-images'
import objectFitImages from 'object-fit-images'
import classNames from 'classnames'
import styles from './index.module.scss'
@ -10,9 +11,18 @@ type LazyImageProps = {
srcPlaceholder?: string
alt: string
aspectRatio: string
stretch?: boolean
} & React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>
const LazyImage = ({ src, srcRetina = src, srcPlaceholder = src, alt, aspectRatio, ...props }: LazyImageProps) => {
const LazyImage = ({
src,
srcRetina = src,
srcPlaceholder = src,
alt,
aspectRatio,
stretch = false,
...props
}: LazyImageProps) => {
const [widthString, heightString] = aspectRatio.split('/')
const width = parseInt(widthString)
const height = parseInt(heightString)
@ -30,7 +40,11 @@ const LazyImage = ({ src, srcRetina = src, srcPlaceholder = src, alt, aspectRati
{({ imageProps, imageState, ref }) => {
const loaded = imageState === ImageState.LoadSuccess
return (
<div className={styles.root} ref={ref} style={{ paddingBottom: `${(height / width) * 100}%` }} {...props}>
<div
className={classNames(styles.root, { [styles.stretch]: stretch })}
ref={ref}
style={{ paddingBottom: `${(height / width) * 100}%` }}
{...props}>
<img
className={styles.placeholder}
src={srcPlaceholder}

View File

@ -0,0 +1,27 @@
import React, { createContext, useContext, useMemo } from 'react'
import PropTypes from 'prop-types'
import useMedia from 'use-media'
type MediaQueryProviderProps = {
children: PropTypes.ReactNodeLike
isMobileDevice?: boolean
}
type ContextProps = {
isMobile: boolean
}
export const MediaQueryContext = createContext<ContextProps>({ isMobile: false })
export const MediaQueryProvider = ({ children, isMobileDevice = false }: MediaQueryProviderProps) => {
const isMobile = useMedia('(max-width: 991px)', isMobileDevice)
const value = useMemo(() => ({ isMobile }), [isMobile])
return <MediaQueryContext.Provider value={value}>{children}</MediaQueryContext.Provider>
}
MediaQueryProvider.propTypes = {
children: PropTypes.node.isRequired,
isMobileDevice: PropTypes.bool,
}
export const useMediaQueryContext = () => useContext(MediaQueryContext)

View File

@ -33,7 +33,7 @@ const SEO = ({ title, description }: SEOProps) => (
<meta property="og:type" content="website" />
<meta property="og:site_name" content={title} />
<meta property="og:url" content="https://favycon.app" />
<meta property="og:image" content="https://favycon.app/share.png?v2" />
<meta property="og:image" content="https://favycon.app/share.png?v3" />
<meta property="og:image:type" content="image/png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />

View File

@ -1,45 +0,0 @@
import React from 'react'
import { uniqueId } from 'utils/ids'
const SvgAppycon: React.FC<JSX.IntrinsicAttributes & React.SVGProps<SVGSVGElement>> = (props) => {
const idPrefix = uniqueId('svg-')
return (
<svg width={64} height={64} viewBox="0 0 64 64" aria-labelledby={`${idPrefix}-title`} {...props}>
<title id={`${idPrefix}-title`}>Appycon logo</title>
<defs>
<linearGradient x1="50%" y1="99.731%" x2="50%" y2=".44%" id={`${idPrefix}-c`}>
<stop stopColor="#FFBB45" offset="0%" />
<stop stopColor="#D53838" offset="100%" />
</linearGradient>
<filter x="-6.3%" y="-4.5%" width="112.5%" height="112.5%" filterUnits="objectBoundingBox" id={`${idPrefix}-a`}>
<feOffset dy={1} in="SourceAlpha" result="shadowOffsetOuter1" />
<feGaussianBlur stdDeviation={1} in="shadowOffsetOuter1" result="shadowBlurOuter1" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.08 0" in="shadowBlurOuter1" />
</filter>
<path
d="M29.669 4h4.662c6.766 0 10.83 1.021 14.414 2.938a19.99 19.99 0 018.317 8.317C58.979 18.84 60 22.903 60 29.669v4.662c0 6.766-1.021 10.83-2.938 14.414a19.99 19.99 0 01-8.317 8.317C45.16 58.979 41.097 60 34.331 60H29.67c-6.766 0-10.83-1.021-14.414-2.938a19.99 19.99 0 01-8.317-8.317C5.021 45.16 4 41.097 4 34.331V29.67c0-6.766 1.021-10.83 2.938-14.414a19.99 19.99 0 018.317-8.317C18.84 5.021 22.903 4 29.669 4z"
id={`${idPrefix}-b`}
/>
</defs>
<g fill="none" fillRule="evenodd">
<g transform="rotate(-8 32 32)">
<use fill="#000" filter={`url(${idPrefix}-a)`} xlinkHref={`${idPrefix}-b`} />
<use fill={`url(${idPrefix}-b)`} xlinkHref={`${idPrefix}-b`} />
</g>
<path
d="M25.795 4.597l4.617-.649c6.7-.942 10.865-.496 14.682.904a19.99 19.99 0 019.393 7.078c2.398 3.283 3.974 7.165 4.916 13.865l.649 4.617c.942 6.7.496 10.865-.904 14.682a19.99 19.99 0 01-7.078 9.393c-3.283 2.398-7.165 3.974-13.865 4.916l-4.617.649c-6.7.942-10.865.496-14.682-.904a19.99 19.99 0 01-9.393-7.078c-2.398-3.283-3.974-7.165-4.916-13.865l-.649-4.617c-.942-6.7-.496-10.865.904-14.682a19.99 19.99 0 017.078-9.393c3.283-2.398 7.165-3.974 13.865-4.916zm5.313 4.302l-4.618.65c-5.587.785-8.831 1.972-11.612 4.002a14.992 14.992 0 00-5.332 7.076C8.398 23.758 8.13 27.09 8.83 32.375l.07.517.65 4.618c.785 5.587 1.972 8.831 4.002 11.612a14.992 14.992 0 007.076 5.332c3.131 1.148 6.463 1.416 11.748.717l.517-.07 4.618-.65c5.587-.785 8.831-1.972 11.612-4.002a14.992 14.992 0 005.332-7.076c1.148-3.131 1.416-6.463.717-11.748l-.07-.517-.65-4.618c-.785-5.587-1.972-8.831-4.002-11.612a14.992 14.992 0 00-7.076-5.332C40.242 8.398 36.91 8.13 31.625 8.83l-.517.07z"
fillOpacity={0.48}
fill="#FFF"
fillRule="nonzero"
/>
<path
d="M21.532 41.283l.611-4.03 6.806-.957 1.698 3.706 3.516-.495-8.134-17.79-5.098.716-2.915 19.344 3.516-.494zm5.977-8.125l-4.872.685 1.266-8.488 3.606 7.803zm13.425 11.71l4.833-21.192-3.416.48-2.21 9.962-4.896-8.963-3.541.497 7.417 13.053-1.35 6.607 3.163-.445z"
fill="#FFF"
fillRule="nonzero"
/>
</g>
</svg>
)
}
export { SvgAppycon }

View File

@ -1,16 +0,0 @@
import React from 'react'
import useDarkMode from 'use-dark-mode'
import { uniqueId } from 'utils/ids'
const SvgArrowDown: React.FC<JSX.IntrinsicAttributes & React.SVGProps<SVGSVGElement>> = (props) => {
const { value: isDark } = useDarkMode(false)
const idPrefix = uniqueId('svg-')
return (
<svg width={16} height={16} viewBox="0 0 16 16" aria-labelledby={`${idPrefix}-title`} {...props}>
<title id={`${idPrefix}-title`}>Arrow down</title>
<path d="M3 6l5 5 5-5" stroke={isDark ? '#5a5b66' : '#ccc'} strokeWidth={2} fill="none" strokeLinejoin="round" />
</svg>
)
}
export { SvgArrowDown }

View File

@ -1,8 +1,9 @@
@import '../../styles/variables.scss';
.unchecked {
fill: #f7f7f8;
fill: #f7f7f7;
stroke: #ccc;
stroke-width: 1.5px;
transition: all 100ms ease-in-out;
&.disabled {
@ -13,11 +14,12 @@
:global(.dark-mode) .unchecked {
fill: $dark-grey;
stroke: $grey-dark;
stroke: $darker-black;
stroke-width: 1.5px;
&.disabled {
fill: $dark-black;
stroke: $dark-grey;
stroke: $darker-black;
}
}

View File

@ -3,6 +3,10 @@
.rect {
stroke: #ccc;
transition: stroke 0.2s ease;
@include breakpoint-md {
stroke-width: 0;
}
}
:global(.dark-mode) .rect {

View File

@ -1,10 +1,9 @@
import React from 'react'
import { uniqueId } from 'utils/ids'
import styles from './svg-favycon.module.scss'
const SvgFavycon: React.FC<JSX.IntrinsicAttributes & React.SVGProps<SVGSVGElement>> = (props) => {
const idPrefix = uniqueId('svg-')
const idPrefix = 'svg-favycon-'
return (
<svg width={64} height={64} viewBox="0 0 64 64" aria-labelledby={`${idPrefix}-title`} {...props}>
<title id={`${idPrefix}-title`}>Favycon logo</title>

View File

@ -1,11 +1,53 @@
@import '../../styles/variables.scss';
.circle {
opacity: 0;
fill: $white;
transition: all 0.2s ease;
@include breakpoint-md {
opacity: 0.1;
}
}
.rect {
fill: #ccc;
transition: all 0.2s ease;
&:nth-of-type(1) {
y: 20px;
height: 48px;
}
&:nth-of-type(2) {
x: 20px;
width: 48px;
}
&.active {
fill: $link;
@include breakpoint-md-up {
fill: $link;
}
&:nth-of-type(1) {
/* mouse, touch pad */
@media (hover: hover) and (pointer: fine) {
y: 16px;
height: 56px;
}
}
&:nth-of-type(2) {
/* mouse, touch pad */
@media (hover: hover) and (pointer: fine) {
x: 16px;
width: 56px;
}
}
}
@include breakpoint-md {
fill: $off-white-dark;
}
}
@ -15,4 +57,8 @@
&.active {
fill: $off-white-dark;
}
@include breakpoint-md {
fill: $off-white-dark;
}
}

View File

@ -1,6 +1,5 @@
import React from 'react'
import classnames from 'classnames'
import { uniqueId } from 'utils/ids'
import styles from './svg-image-upload.module.scss'
@ -12,24 +11,13 @@ const SvgImageUpload: React.FC<JSX.IntrinsicAttributes & React.SVGProps<SVGSVGEl
active = false,
...props
}) => {
const idPrefix = uniqueId('svg-')
const idPrefix = 'svg-image-upload-'
return (
<svg width={88} height={88} viewBox="0 0 88 88" aria-labelledby={`${idPrefix}-title`} {...props}>
<title id={`${idPrefix}-title`}>Image Upload</title>
<rect
x={43}
y={active ? 16 : 20}
width={2}
height={active ? 56 : 48}
className={classnames(styles.rect, { [styles.active]: active })}
/>
<rect
x={active ? 16 : 20}
y={43}
width={active ? 56 : 48}
height={2}
className={classnames(styles.rect, { [styles.active]: active })}
/>
<circle r={44} cx={44} cy={44} className={styles.circle} />
<rect x={43} y={20} width={2} height={48} className={classnames(styles.rect, { [styles.active]: active })} />
<rect x={20} y={43} width={48} height={2} className={classnames(styles.rect, { [styles.active]: active })} />
</svg>
)
}

View File

@ -1,10 +1,9 @@
import React from 'react'
import { uniqueId } from 'utils/ids'
import styles from './svg-info.module.scss'
const SvgInfo: React.FC<JSX.IntrinsicAttributes & React.SVGProps<SVGSVGElement>> = (props) => {
const idPrefix = uniqueId('svg-')
const idPrefix = 'svg-info-'
return (
<svg width={20} height={20} viewBox="0 0 20 20" aria-labelledby={`${idPrefix}-title`} {...props}>
<title id={`${idPrefix}-title`}>Info</title>

View File

@ -1,8 +1,7 @@
import React from 'react'
import { uniqueId } from 'utils/ids'
const SvgMoon: React.FC<JSX.IntrinsicAttributes & React.SVGProps<SVGSVGElement>> = (props) => {
const idPrefix = uniqueId('svg-')
const idPrefix = 'svg-moon-'
return (
<svg width={32} height={32} viewBox="0 0 32 32" aria-labelledby={`${idPrefix}-title`} {...props}>
<title id={`${idPrefix}-title`}>Activate dark mode</title>

View File

@ -1,8 +1,7 @@
import React from 'react'
import { uniqueId } from 'utils/ids'
const SvgSun: React.FC<JSX.IntrinsicAttributes & React.SVGProps<SVGSVGElement>> = (props) => {
const idPrefix = uniqueId('svg-')
const idPrefix = 'svg-sun-'
return (
<svg width={32} height={32} viewBox="0 0 32 32" aria-labelledby={`${idPrefix}-title`} {...props}>
<title id={`${idPrefix}-title`}>Activate light mode</title>

View File

@ -4,10 +4,15 @@ import { SvgFavycon } from 'components/svgs/svg-favycon'
import styles from './index.module.scss'
const ToolTitle = () => (
type ToolTitleProps = {
hideLogo?: boolean
small?: boolean
}
const ToolTitle = ({ hideLogo = false, small = false }: ToolTitleProps) => (
<div className={styles.root}>
<SvgFavycon />
<Typography variant="h1" weight="extraBold" color="black">
{!hideLogo && <SvgFavycon />}
<Typography variant={small ? 'h2' : 'h1'} weight="extraBold" color="black">
Favycon
</Typography>
<Typography variant="superscript" tag="span" weight="bold" color="gray">

View File

@ -9,6 +9,11 @@
line-height: $line-height-h1;
}
.h2 {
font-size: $font-size-extra-large-title;
line-height: $line-height-extra-large-title;
}
.smallBody {
font-size: $font-size-small-body;
line-height: $line-height-small-body;
@ -17,6 +22,10 @@
.regularBody {
font-size: $font-size-regular-body;
line-height: $line-height-regular-body;
@include breakpoint-md {
font-size: $font-size-medium-body;
}
}
.mediumBody {
@ -33,6 +42,10 @@
font-size: $font-size-footer;
line-height: $line-height-footer;
@include breakpoint-md {
font-size: $font-size-small-body;
}
a {
color: inherit;
@ -52,6 +65,10 @@
.title {
font-size: $font-size-title;
line-height: $line-height-title;
@include breakpoint-md {
font-size: $font-size-medium-body;
}
}
.largeTitle {
@ -59,6 +76,11 @@
line-height: $line-height-large-title;
}
.extraLargeTitle {
font-size: $font-size-extra-large-title;
line-height: $line-height-extra-large-title;
}
.regular {
font-weight: 400;
}
@ -101,7 +123,7 @@
transition: color 0.2s ease;
}
:global(.dark-mode) .white {
:global(.dark-mode) .white:not(.colorImmutable) {
color: $black;
}
@ -115,5 +137,5 @@
}
:global(.dark-mode) .muted {
color: $grey;
color: $grey-dark;
}

View File

@ -8,6 +8,7 @@ type TypographyProps = {
children: PropTypes.ReactNodeLike
variant:
| 'h1'
| 'h2'
| 'smallBody'
| 'regularBody'
| 'mediumBody'
@ -16,22 +17,25 @@ type TypographyProps = {
| 'superscript'
| 'title'
| 'largeTitle'
| 'extraLargeTitle'
weight: 'regular' | 'medium' | 'semiBold' | 'bold' | 'extraBold'
color: 'black' | 'gray' | 'white' | 'green'
colorImmutable?: boolean
tag?: string
muted?: boolean
} & React.DetailedHTMLProps<React.HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
const Typography = ({ children, variant, weight, color, tag, muted, ...props }: TypographyProps) => {
const Typography = ({ children, variant, weight, color, colorImmutable, tag, muted, ...props }: TypographyProps) => {
const className = classNames(
styles.root,
styles[variant],
styles[color],
styles[weight],
{ [styles.muted]: muted },
{ [styles.colorImmutable]: colorImmutable },
props.className
)
const componentType = ['h1'].includes(variant) ? variant : 'p'
const componentType = ['h1', 'h2'].includes(variant) ? variant : 'p'
return React.createElement(tag || componentType, { ...props, className }, children)
}
@ -40,6 +44,7 @@ Typography.defaultProps = {
variant: 'p',
weight: 'regular',
color: 'black',
colorImmutable: false,
}
export { Typography }

11
hooks/use-toggle.ts Normal file
View File

@ -0,0 +1,11 @@
import React from 'react'
export const useToggle = (initialValue = false): [boolean, () => void] => {
const [value, setValue] = React.useState(initialValue)
const toggle = React.useCallback(() => {
setValue((v) => !v)
}, [])
return [value, toggle]
}

View File

@ -62,8 +62,9 @@
"react-lazy-images": "1.1.0",
"react-modal": "3.11.2",
"react-transition-group": "4.4.1",
"sharp": "0.26.0",
"use-dark-mode": "2.3.1"
"sharp": "0.25.0",
"use-dark-mode": "2.3.1",
"use-media": "1.4.0"
},
"devDependencies": {
"@babel/core": "7.11.6",
@ -116,6 +117,9 @@
"husky": "4.2.5",
"lint-staged": "10.3.0",
"npm-run-all": "4.1.5",
"postcss-100vh-fix": "0.1.1",
"postcss-flexbugs-fixes": "4.2.1",
"postcss-preset-env": "6.7.0",
"prettier": "2.1.1",
"react-refresh": "0.8.3",
"regenerator-runtime": "0.13.7",
@ -129,6 +133,7 @@
"stylelint-config-recess-order": "2.1.0",
"stylelint-config-standard": "20.0.0",
"stylelint-prettier": "1.1.2",
"stylelint-scss": "3.17.2",
"typescript": "3.9.7",
"webpack-notifier": "1.8.0"
},

View File

@ -1,10 +1,15 @@
import React from 'react'
import { AppProps } from 'next/app'
import { MediaQueryProvider } from 'components/media-query-provider'
import '../styles/main.scss'
function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
return (
<MediaQueryProvider>
<Component {...pageProps} />
</MediaQueryProvider>
)
}
export default MyApp

View File

@ -6,6 +6,7 @@
}
.container {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
@ -14,4 +15,10 @@
min-height: 100vh;
padding: 52px 20px;
margin: 0 auto;
@include breakpoint-md {
align-items: stretch;
max-width: 100%;
padding: 0;
}
}

View File

@ -29,16 +29,20 @@ const Home: NextPage = () => {
setError(error)
}
const onGenerate = async (file: File, pwa: boolean) => {
const onGenerate = async (file: File, pwa: boolean, dark: boolean) => {
try {
NProgress.start()
const formData = new FormData()
formData.append('icon', file)
formData.append('pwa', pwa ? '1' : '0')
formData.append('dark', dark ? '1' : '0')
const response = await fetch('/api/favycon', {
method: 'POST',
body: formData,
})
if (response.status >= 300) {
throw new Error(await response.text())
}
return await response.arrayBuffer()
} catch (error) {
throw error
@ -55,12 +59,12 @@ const Home: NextPage = () => {
/>
<main className={styles.main}>
<div className={styles.container}>
<FavyconInfo />
<FavyconInfo className={styles.info} />
<FavyconWizard showDndImage={!file}>
<DragAndDrop key={fileCounter} onFile={setFile} onGenerate={onGenerate} onError={onError} />
</FavyconWizard>
</div>
<FavyconError key={errorCounter} error={error} clearError={() => onError('')} />
<FavyconError key={errorCounter} error={error} clearError={() => setError('')} />
</main>
</BaseLayout>
)

18
postcss.config.js Normal file
View File

@ -0,0 +1,18 @@
module.exports = {
plugins: [
'postcss-100vh-fix',
'postcss-flexbugs-fixes',
[
'postcss-preset-env',
{
autoprefixer: {
flexbox: 'no-2009',
},
stage: 3,
features: {
'custom-properties': false,
},
},
],
],
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 824 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 179 KiB

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 541 KiB

After

Width:  |  Height:  |  Size: 363 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

After

Width:  |  Height:  |  Size: 114 KiB

34
styles/breakpoints.scss Normal file
View File

@ -0,0 +1,34 @@
$breakpoint-xs: 576px;
$breakpoint-sm: 768px;
$breakpoint-md: 992px;
$breakpoint-lg: 1200px;
@mixin breakpoint-xs {
@media screen and (max-width: $breakpoint-xs - 1) {
@content;
}
}
@mixin breakpoint-sm {
@media screen and (max-width: $breakpoint-sm - 1) {
@content;
}
}
@mixin breakpoint-md {
@media screen and (max-width: $breakpoint-md - 1) {
@content;
}
}
@mixin breakpoint-md-up {
@media screen and (min-width: $breakpoint-md) {
@content;
}
}
@mixin breakpoint-lg {
@media screen and (max-width: $breakpoint-lg - 1) {
@content;
}
}

View File

@ -30,6 +30,7 @@ body {
* {
box-sizing: border-box;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {

View File

@ -121,7 +121,7 @@ blockquote::before,
blockquote::after,
q::before,
q::after {
content: '';
content: ' ';
content: none;
}
table {

View File

@ -1,3 +1,5 @@
@import 'breakpoints';
$white: #fff;
$white-dark: #a8b7c4;
$off-white: #fafafa;
@ -47,3 +49,6 @@ $line-height-title: 24px;
$font-size-large-title: 18px;
$line-height-large-title: 24px;
$font-size-extra-large-title: 32px;
$line-height-extra-large-title: 40px;

12
utils/device.ts Normal file
View File

@ -0,0 +1,12 @@
export const isTouchCapable = () => {
if (typeof window === 'undefined') {
return false
}
return (
'ontouchstart' in window ||
// @ts-ignore
(window.DocumentTouch && document instanceof window.DocumentTouch) ||
navigator.maxTouchPoints > 0 ||
window.navigator.msMaxTouchPoints > 0
)
}

500
yarn.lock
View File

@ -2352,6 +2352,11 @@
resolved "https://registry.yarnpkg.com/@commitlint/types/-/types-9.1.2.tgz#d05f66db03e3a3638a654e8badf2deb489eb220d"
integrity sha512-r3fwVbVH+M8W0qYlBBZFsUwKe6NT5qvz+EmU7sr8VeN1cQ63z+3cfXyTo7WGGEMEgKiT0jboNAK3b1FZp8k9LQ==
"@csstools/convert-colors@^1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7"
integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==
"@cypress/listr-verbose-renderer@^0.4.1":
version "0.4.1"
resolved "https://registry.yarnpkg.com/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#a77492f4b11dcc7c446a34b3e28721afd33c642a"
@ -4505,6 +4510,19 @@ attr-accept@^2.0.0:
resolved "https://registry.yarnpkg.com/attr-accept/-/attr-accept-2.1.0.tgz#a231a854385d36ff7a99647bb77b33c8a5175aee"
integrity sha512-sLzVM3zCCmmDtDNhI0i96k6PUztkotSOXqE4kDGQt/6iDi5M+H0srjeF+QC6jN581l4X/Zq3Zu/tgcErEssavg==
autoprefixer@^9.6.1, autoprefixer@^9.8.6:
version "9.8.6"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f"
integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==
dependencies:
browserslist "^4.12.0"
caniuse-lite "^1.0.30001109"
colorette "^1.2.1"
normalize-range "^0.1.2"
num2fraction "^1.2.2"
postcss "^7.0.32"
postcss-value-parser "^4.1.0"
autoprefixer@^9.7.2:
version "9.8.0"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.0.tgz#68e2d2bef7ba4c3a65436f662d0a56a741e56511"
@ -4518,19 +4536,6 @@ autoprefixer@^9.7.2:
postcss "^7.0.30"
postcss-value-parser "^4.1.0"
autoprefixer@^9.8.6:
version "9.8.6"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f"
integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==
dependencies:
browserslist "^4.12.0"
caniuse-lite "^1.0.30001109"
colorette "^1.2.1"
normalize-range "^0.1.2"
num2fraction "^1.2.2"
postcss "^7.0.32"
postcss-value-parser "^4.1.0"
aws-sign2@~0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
@ -4996,9 +5001,9 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.4.0:
integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==
bn.js@^5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.2.tgz#c9686902d3c9a27729f43ab10f9d79c2004da7b0"
integrity sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==
version "5.1.1"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.1.tgz#48efc4031a9c4041b9c99c6941d903463ab62eb5"
integrity sha512-IUTD/REb78Z2eodka1QZyyEk66pciRcP6Sroka0aI3tG/iwIdYLrBD62RsubR7vqdt3WyX8p4jxeatzmRSphtA==
body-parser@1.19.0:
version "1.19.0"
@ -5150,7 +5155,7 @@ browserify-zlib@^0.2.0:
dependencies:
pako "~1.0.5"
browserslist@4.13.0:
browserslist@4.13.0, browserslist@^4.6.4:
version "4.13.0"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.13.0.tgz#42556cba011e1b0a2775b611cba6a8eca18e940d"
integrity sha512-MINatJ5ZNrLnQ6blGvePd/QOz9Xtu+Ne+x29iQSCHfkU5BugKVJwZKn/iiL8UbpIpa3JhviKjz+XxMo0m2caFQ==
@ -5390,16 +5395,16 @@ can-use-dom@^0.1.0:
resolved "https://registry.yarnpkg.com/can-use-dom/-/can-use-dom-0.1.0.tgz#22cc4a34a0abc43950f42c6411024a3f6366b45a"
integrity sha1-IsxKNKCrxDlQ9CxkEQJKP2NmtFo=
caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001093:
version "1.0.30001109"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001109.tgz#a9f3f26a0c3753b063d7acbb48dfb9c0e46f2b19"
integrity sha512-4JIXRodHzdS3HdK8nSgIqXYLExOvG+D2/EenSvcub2Kp3QEADjo2v2oUn5g0n0D+UNwG9BtwKOyGcSq2qvQXvQ==
caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001043, caniuse-lite@^1.0.30001061:
version "1.0.30001077"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001077.tgz#5d7da6a120b08d9f4fd94823786ecb454aaa5626"
integrity sha512-AEzsGvjBJL0lby/87W96PyEvwN0GsYvk5LHsglLg9tW37K4BqvAvoSCdWIE13OZQ8afupqZ73+oL/1LkedN8hA==
caniuse-lite@^1.0.30001093:
version "1.0.30001109"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001109.tgz#a9f3f26a0c3753b063d7acbb48dfb9c0e46f2b19"
integrity sha512-4JIXRodHzdS3HdK8nSgIqXYLExOvG+D2/EenSvcub2Kp3QEADjo2v2oUn5g0n0D+UNwG9BtwKOyGcSq2qvQXvQ==
caniuse-lite@^1.0.30001109:
version "1.0.30001123"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001123.tgz#7b981d81382ab2c8fd062f3e6439215e8c503c22"
@ -5566,6 +5571,11 @@ chownr@^1.1.1, chownr@^1.1.2, chownr@^1.1.3, chownr@^1.1.4:
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
chownr@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
chrome-trace-event@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4"
@ -6334,6 +6344,21 @@ crypto-random-string@^2.0.0:
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==
css-blank-pseudo@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5"
integrity sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w==
dependencies:
postcss "^7.0.5"
css-has-pseudo@^0.10.0:
version "0.10.0"
resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz#3c642ab34ca242c59c41a125df9105841f6966ee"
integrity sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ==
dependencies:
postcss "^7.0.6"
postcss-selector-parser "^5.0.0-rc.4"
css-loader@3.5.3, css-loader@^3.0.0:
version "3.5.3"
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.5.3.tgz#95ac16468e1adcd95c844729e0bb167639eb0bcf"
@ -6353,6 +6378,13 @@ css-loader@3.5.3, css-loader@^3.0.0:
schema-utils "^2.6.6"
semver "^6.3.0"
css-prefers-color-scheme@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz#6f830a2714199d4f0d0d0bb8a27916ed65cff1f4"
integrity sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg==
dependencies:
postcss "^7.0.5"
css-select-base-adapter@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7"
@ -6419,6 +6451,16 @@ css@^2.0.0:
source-map-resolve "^0.5.2"
urix "^0.1.0"
cssdb@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0"
integrity sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ==
cssesc@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703"
integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==
cssesc@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
@ -6656,13 +6698,6 @@ decompress-response@^4.2.0:
dependencies:
mimic-response "^2.0.0"
decompress-response@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc"
integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==
dependencies:
mimic-response "^3.1.0"
dedent@0.7.0, dedent@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
@ -8155,6 +8190,11 @@ flatted@^2.0.0:
resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138"
integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==
flatten@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b"
integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==
flush-write-stream@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8"
@ -10560,7 +10600,7 @@ lodash.sortby@^4.7.0:
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
lodash.template@^4.0.2:
lodash.template@^4.0.2, lodash.template@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab"
integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==
@ -11091,11 +11131,6 @@ mimic-response@^2.0.0:
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43"
integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==
mimic-response@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9"
integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==
min-document@^2.19.0:
version "2.19.0"
resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
@ -11200,6 +11235,14 @@ minizlib@^2.1.0:
minipass "^3.0.0"
yallist "^4.0.0"
minizlib@^2.1.1:
version "2.1.2"
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
dependencies:
minipass "^3.0.0"
yallist "^4.0.0"
mississippi@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022"
@ -11251,6 +11294,11 @@ mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.4, mkdirp@^0.5.5, mkdir
dependencies:
minimist "^1.2.5"
mkdirp@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
modify-values@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
@ -11461,10 +11509,10 @@ node-abi@^2.7.0:
dependencies:
semver "^5.4.1"
node-addon-api@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.0.0.tgz#812446a1001a54f71663bed188314bba07e09247"
integrity sha512-sSHCgWfJ+Lui/u+0msF3oyCgvdkhxDbkCS6Q8uiJquzOimkJBvX6hl5aSSA7DR1XbMpdM8r7phjcF63sF4rkKg==
node-addon-api@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32"
integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==
node-dir@^0.1.10:
version "0.1.17"
@ -12667,13 +12715,145 @@ posix-character-classes@^0.1.0:
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
postcss-flexbugs-fixes@^4.1.0:
postcss-100vh-fix@0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/postcss-100vh-fix/-/postcss-100vh-fix-0.1.1.tgz#b3a5f816b5a7ba05b8073c3b0e7b44a48e0654df"
integrity sha512-Dv0OdLLIskpAgB70XxFTwHHs0mQnDbnXF12NI2DjIt7pq5wvwDr9p3jAoP7P7OBo7Uu2v6mQzj33tU7o0lI+NA==
dependencies:
postcss "^7.0.32"
postcss-attribute-case-insensitive@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz#d93e46b504589e94ac7277b0463226c68041a880"
integrity sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA==
dependencies:
postcss "^7.0.2"
postcss-selector-parser "^6.0.2"
postcss-color-functional-notation@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz#5efd37a88fbabeb00a2966d1e53d98ced93f74e0"
integrity sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g==
dependencies:
postcss "^7.0.2"
postcss-values-parser "^2.0.0"
postcss-color-gray@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz#532a31eb909f8da898ceffe296fdc1f864be8547"
integrity sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw==
dependencies:
"@csstools/convert-colors" "^1.4.0"
postcss "^7.0.5"
postcss-values-parser "^2.0.0"
postcss-color-hex-alpha@^5.0.3:
version "5.0.3"
resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz#a8d9ca4c39d497c9661e374b9c51899ef0f87388"
integrity sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw==
dependencies:
postcss "^7.0.14"
postcss-values-parser "^2.0.1"
postcss-color-mod-function@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz#816ba145ac11cc3cb6baa905a75a49f903e4d31d"
integrity sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ==
dependencies:
"@csstools/convert-colors" "^1.4.0"
postcss "^7.0.2"
postcss-values-parser "^2.0.0"
postcss-color-rebeccapurple@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz#c7a89be872bb74e45b1e3022bfe5748823e6de77"
integrity sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g==
dependencies:
postcss "^7.0.2"
postcss-values-parser "^2.0.0"
postcss-custom-media@^7.0.8:
version "7.0.8"
resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz#fffd13ffeffad73621be5f387076a28b00294e0c"
integrity sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg==
dependencies:
postcss "^7.0.14"
postcss-custom-properties@^8.0.11:
version "8.0.11"
resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz#2d61772d6e92f22f5e0d52602df8fae46fa30d97"
integrity sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA==
dependencies:
postcss "^7.0.17"
postcss-values-parser "^2.0.1"
postcss-custom-selectors@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz#64858c6eb2ecff2fb41d0b28c9dd7b3db4de7fba"
integrity sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w==
dependencies:
postcss "^7.0.2"
postcss-selector-parser "^5.0.0-rc.3"
postcss-dir-pseudo-class@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz#6e3a4177d0edb3abcc85fdb6fbb1c26dabaeaba2"
integrity sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw==
dependencies:
postcss "^7.0.2"
postcss-selector-parser "^5.0.0-rc.3"
postcss-double-position-gradients@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz#fc927d52fddc896cb3a2812ebc5df147e110522e"
integrity sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA==
dependencies:
postcss "^7.0.5"
postcss-values-parser "^2.0.0"
postcss-env-function@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-2.0.2.tgz#0f3e3d3c57f094a92c2baf4b6241f0b0da5365d7"
integrity sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw==
dependencies:
postcss "^7.0.2"
postcss-values-parser "^2.0.0"
postcss-flexbugs-fixes@4.2.1, postcss-flexbugs-fixes@^4.1.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-4.2.1.tgz#9218a65249f30897deab1033aced8578562a6690"
integrity sha512-9SiofaZ9CWpQWxOwRh1b/r85KD5y7GgvsNt1056k6OYLvWUun0czCvogfJgylC22uJTwW1KzY3Gz65NZRlvoiQ==
dependencies:
postcss "^7.0.26"
postcss-focus-visible@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz#477d107113ade6024b14128317ade2bd1e17046e"
integrity sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g==
dependencies:
postcss "^7.0.2"
postcss-focus-within@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz#763b8788596cee9b874c999201cdde80659ef680"
integrity sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w==
dependencies:
postcss "^7.0.2"
postcss-font-variant@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-4.0.0.tgz#71dd3c6c10a0d846c5eda07803439617bbbabacc"
integrity sha512-M8BFYKOvCrI2aITzDad7kWuXXTm0YhGdP9Q8HanmN4EF1Hmcgs1KK5rSHylt/lUJe8yLxiSwWAHdScoEiIxztg==
dependencies:
postcss "^7.0.2"
postcss-gap-properties@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz#431c192ab3ed96a3c3d09f2ff615960f902c1715"
integrity sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg==
dependencies:
postcss "^7.0.2"
postcss-html@^0.36.0:
version "0.36.0"
resolved "https://registry.yarnpkg.com/postcss-html/-/postcss-html-0.36.0.tgz#b40913f94eaacc2453fd30a1327ad6ee1f88b204"
@ -12681,6 +12861,31 @@ postcss-html@^0.36.0:
dependencies:
htmlparser2 "^3.10.0"
postcss-image-set-function@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz#28920a2f29945bed4c3198d7df6496d410d3f288"
integrity sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw==
dependencies:
postcss "^7.0.2"
postcss-values-parser "^2.0.0"
postcss-initial@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.2.tgz#f018563694b3c16ae8eaabe3c585ac6319637b2d"
integrity sha512-ugA2wKonC0xeNHgirR4D3VWHs2JcU08WAi1KFLVcnb7IN89phID6Qtg2RIctWbnvp1TM2BOmDtX8GGLCKdR8YA==
dependencies:
lodash.template "^4.5.0"
postcss "^7.0.2"
postcss-lab-function@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz#bb51a6856cd12289ab4ae20db1e3821ef13d7d2e"
integrity sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg==
dependencies:
"@csstools/convert-colors" "^1.4.0"
postcss "^7.0.2"
postcss-values-parser "^2.0.0"
postcss-less@^3.1.4:
version "3.1.4"
resolved "https://registry.yarnpkg.com/postcss-less/-/postcss-less-3.1.4.tgz#369f58642b5928ef898ffbc1a6e93c958304c5ad"
@ -12706,6 +12911,20 @@ postcss-loader@^3.0.0:
postcss-load-config "^2.0.0"
schema-utils "^1.0.0"
postcss-logical@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-3.0.0.tgz#2495d0f8b82e9f262725f75f9401b34e7b45d5b5"
integrity sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA==
dependencies:
postcss "^7.0.2"
postcss-media-minmax@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz#b75bb6cbc217c8ac49433e12f22048814a4f5ed5"
integrity sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw==
dependencies:
postcss "^7.0.2"
postcss-media-query-parser@^0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244"
@ -12744,6 +12963,93 @@ postcss-modules-values@^3.0.0:
icss-utils "^4.0.0"
postcss "^7.0.6"
postcss-nesting@^7.0.0:
version "7.0.1"
resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-7.0.1.tgz#b50ad7b7f0173e5b5e3880c3501344703e04c052"
integrity sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg==
dependencies:
postcss "^7.0.2"
postcss-overflow-shorthand@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz#31ecf350e9c6f6ddc250a78f0c3e111f32dd4c30"
integrity sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g==
dependencies:
postcss "^7.0.2"
postcss-page-break@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-2.0.0.tgz#add52d0e0a528cabe6afee8b46e2abb277df46bf"
integrity sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ==
dependencies:
postcss "^7.0.2"
postcss-place@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-4.0.1.tgz#e9f39d33d2dc584e46ee1db45adb77ca9d1dcc62"
integrity sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg==
dependencies:
postcss "^7.0.2"
postcss-values-parser "^2.0.0"
postcss-preset-env@6.7.0:
version "6.7.0"
resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz#c34ddacf8f902383b35ad1e030f178f4cdf118a5"
integrity sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg==
dependencies:
autoprefixer "^9.6.1"
browserslist "^4.6.4"
caniuse-lite "^1.0.30000981"
css-blank-pseudo "^0.1.4"
css-has-pseudo "^0.10.0"
css-prefers-color-scheme "^3.1.1"
cssdb "^4.4.0"
postcss "^7.0.17"
postcss-attribute-case-insensitive "^4.0.1"
postcss-color-functional-notation "^2.0.1"
postcss-color-gray "^5.0.0"
postcss-color-hex-alpha "^5.0.3"
postcss-color-mod-function "^3.0.3"
postcss-color-rebeccapurple "^4.0.1"
postcss-custom-media "^7.0.8"
postcss-custom-properties "^8.0.11"
postcss-custom-selectors "^5.1.2"
postcss-dir-pseudo-class "^5.0.0"
postcss-double-position-gradients "^1.0.0"
postcss-env-function "^2.0.2"
postcss-focus-visible "^4.0.0"
postcss-focus-within "^3.0.0"
postcss-font-variant "^4.0.0"
postcss-gap-properties "^2.0.0"
postcss-image-set-function "^3.0.1"
postcss-initial "^3.0.0"
postcss-lab-function "^2.0.1"
postcss-logical "^3.0.0"
postcss-media-minmax "^4.0.0"
postcss-nesting "^7.0.0"
postcss-overflow-shorthand "^2.0.0"
postcss-page-break "^2.0.0"
postcss-place "^4.0.1"
postcss-pseudo-class-any-link "^6.0.0"
postcss-replace-overflow-wrap "^3.0.0"
postcss-selector-matches "^4.0.0"
postcss-selector-not "^4.0.0"
postcss-pseudo-class-any-link@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz#2ed3eed393b3702879dec4a87032b210daeb04d1"
integrity sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew==
dependencies:
postcss "^7.0.2"
postcss-selector-parser "^5.0.0-rc.3"
postcss-replace-overflow-wrap@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz#61b360ffdaedca84c7c918d2b0f0d0ea559ab01c"
integrity sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw==
dependencies:
postcss "^7.0.2"
postcss-resolve-nested-selector@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz#29ccbc7c37dedfac304e9fff0bf1596b3f6a0e4e"
@ -12771,6 +13077,31 @@ postcss-scss@^2.1.1:
dependencies:
postcss "^7.0.6"
postcss-selector-matches@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz#71c8248f917ba2cc93037c9637ee09c64436fcff"
integrity sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww==
dependencies:
balanced-match "^1.0.0"
postcss "^7.0.2"
postcss-selector-not@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-4.0.0.tgz#c68ff7ba96527499e832724a2674d65603b645c0"
integrity sha512-W+bkBZRhqJaYN8XAnbbZPLWMvZD1wKTu0UxtFKdhtGjWYmxhkUneoeOhRJKdAE5V7ZTlnbHfCR+6bNwK9e1dTQ==
dependencies:
balanced-match "^1.0.0"
postcss "^7.0.2"
postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4:
version "5.0.0"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c"
integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==
dependencies:
cssesc "^2.0.0"
indexes-of "^1.0.1"
uniq "^1.0.1"
postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c"
@ -12798,6 +13129,15 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.3, postcss-value-parser@^
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb"
integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==
postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz#da8b472d901da1e205b47bdc98637b9e9e550e5f"
integrity sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==
dependencies:
flatten "^1.0.2"
indexes-of "^1.0.1"
uniq "^1.0.1"
postcss@7.0.21:
version "7.0.21"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.21.tgz#06bb07824c19c2021c5d056d5b10c35b989f7e17"
@ -12854,27 +13194,6 @@ prebuild-install@^5.3.3:
tunnel-agent "^0.6.0"
which-pm-runs "^1.0.0"
prebuild-install@^5.3.5:
version "5.3.5"
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.5.tgz#e7e71e425298785ea9d22d4f958dbaccf8bb0e1b"
integrity sha512-YmMO7dph9CYKi5IR/BzjOJlRzpxGGVo1EsLSUZ0mt/Mq0HWZIHOKHHcHdT69yG54C9m6i45GpItwRHpk0Py7Uw==
dependencies:
detect-libc "^1.0.3"
expand-template "^2.0.3"
github-from-package "0.0.0"
minimist "^1.2.3"
mkdirp "^0.5.1"
napi-build-utils "^1.0.1"
node-abi "^2.7.0"
noop-logger "^0.1.1"
npmlog "^4.0.1"
pump "^3.0.0"
rc "^1.2.7"
simple-get "^3.0.3"
tar-fs "^2.0.0"
tunnel-agent "^0.6.0"
which-pm-runs "^1.0.0"
prelude-ls@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
@ -14316,7 +14635,7 @@ semver@7.0.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
semver@7.3.2, semver@^7.1.2, semver@^7.2.1, semver@^7.3.2:
semver@7.3.2, semver@^7.1.2, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2:
version "7.3.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
@ -14440,19 +14759,19 @@ shallowequal@^1.1.0:
resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8"
integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==
sharp@0.26.0:
version "0.26.0"
resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.26.0.tgz#ff4c8d3200a7a1f76c69c53fd11879609d2ff062"
integrity sha512-MNldekb9ZnliJAD+qP6uBTf3Wd6HaDVhKYbxXG+SQDvit9fa+2X4wECJvMRF8FLdY4saojrz3BHsnt4OmJw7xg==
sharp@0.25.0:
version "0.25.0"
resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.25.0.tgz#b10f6249e4267ed70f627f702b29b47927fe3891"
integrity sha512-58XANPzzUNcDXdScxqKFzMWuzGTJtsoKQ2Y0v2Gj2ztgIMZCGJjeiErf7eQYwP6r/p9HFMYeaiW5PffTMPXo/Q==
dependencies:
color "^3.1.2"
detect-libc "^1.0.3"
node-addon-api "^3.0.0"
node-addon-api "^2.0.0"
npmlog "^4.1.2"
prebuild-install "^5.3.5"
semver "^7.3.2"
simple-get "^4.0.0"
tar-fs "^2.1.0"
prebuild-install "^5.3.3"
semver "^7.1.3"
simple-get "^3.1.0"
tar "^6.0.1"
tunnel-agent "^0.6.0"
sharp@^0.23.4:
@ -14549,15 +14868,6 @@ simple-get@^3.0.3, simple-get@^3.1.0:
once "^1.3.1"
simple-concat "^1.0.0"
simple-get@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.0.tgz#73fa628278d21de83dadd5512d2cc1f4872bd675"
integrity sha512-ZalZGexYr3TA0SwySsr5HlgOOinS4Jsa8YB2GJ6lUNAazyAu4KG/VmzMTwAt2YVXzzVj8QmefmAonZIK2BSGcQ==
dependencies:
decompress-response "^6.0.0"
once "^1.3.1"
simple-concat "^1.0.0"
simple-swizzle@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
@ -15311,6 +15621,17 @@ stylelint-prettier@1.1.2:
dependencies:
prettier-linter-helpers "^1.0.0"
stylelint-scss@3.17.2:
version "3.17.2"
resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-3.17.2.tgz#4d849a153f9241834396f5880db2c3c964def4e3"
integrity sha512-e0dmxqsofy/HZj4urcGSJw4S6yHDJxiQdT20/1ciCsd5lomisa7YM4+Qtt1EG4hsqEG1dbEeF855tec1UyqcSA==
dependencies:
lodash "^4.17.15"
postcss-media-query-parser "^0.2.3"
postcss-resolve-nested-selector "^0.1.1"
postcss-selector-parser "^6.0.2"
postcss-value-parser "^4.1.0"
stylelint@13.7.0:
version "13.7.0"
resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-13.7.0.tgz#8d7a4233063b2f06e9f28b3405ff189e334547b5"
@ -15483,7 +15804,7 @@ tapable@^1.0.0, tapable@^1.1.3:
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
tar-fs@^2.0.0, tar-fs@^2.1.0:
tar-fs@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.0.tgz#d1cdd121ab465ee0eb9ccde2d35049d3f3daf0d5"
integrity sha512-9uW5iDvrIMCVpvasdFHW0wJPez0K4JnMZtsuIeDI7HyMGJNxmDZDOCQROr7lXyS+iL/QMpj07qcjGYTSdRFXUg==
@ -15529,6 +15850,18 @@ tar@^5.0.5:
mkdirp "^0.5.0"
yallist "^4.0.0"
tar@^6.0.1:
version "6.0.5"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.5.tgz#bde815086e10b39f1dcd298e89d596e1535e200f"
integrity sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg==
dependencies:
chownr "^2.0.0"
fs-minipass "^2.0.0"
minipass "^3.0.0"
minizlib "^2.1.1"
mkdirp "^1.0.3"
yallist "^4.0.0"
telejson@^3.2.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/telejson/-/telejson-3.3.0.tgz#6d814f3c0d254d5c4770085aad063e266b56ad03"
@ -16206,6 +16539,11 @@ use-dark-mode@2.3.1:
"@use-it/event-listener" "^0.1.2"
use-persisted-state "^0.3.0"
use-media@1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/use-media/-/use-media-1.4.0.tgz#e777bf1f382a7aacabbd1f9ce3da2b62e58b2a98"
integrity sha512-XsgyUAf3nhzZmEfhc5MqLHwyaPjs78bgytpVJ/xDl0TF4Bptf3vEpBNBBT/EIKOmsOc8UbuECq3mrP3mt1QANA==
use-persisted-state@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/use-persisted-state/-/use-persisted-state-0.3.0.tgz#f8e3d2fd8eee67e0c86fd596c3ea3e8121c07402"