first commit
5
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
6
.idea/misc.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptSettings">
|
||||
<option name="languageLevel" value="JSX" />
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/vector-drawable-nextjs.iml" filepath="$PROJECT_DIR$/.idea/vector-drawable-nextjs.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
12
.idea/vector-drawable-nextjs.iml
generated
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
78
package-lock.json
generated
@ -233,6 +233,23 @@
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/context-base/-/context-base-0.14.0.tgz",
|
||||
"integrity": "sha512-sDOAZcYwynHFTbLo6n8kIbLiVF3a3BLkrmehJUyEbT9F+Smbi47kLGS2gG2g0fjBLR/Lr1InPD7kXL7FaTqEkw=="
|
||||
},
|
||||
"@tanem/svg-injector": {
|
||||
"version": "8.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@tanem/svg-injector/-/svg-injector-8.2.1.tgz",
|
||||
"integrity": "sha512-F8KbsSQnxLHRqoenP2MmB3IWKYANGqDtpyBIQZ6/tnkW7JYgZFG8PxM+QVrfiNbe62C+1b+HfGzb4xJjdu3NYQ==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"content-type": "^1.0.4",
|
||||
"tslib": "^2.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
|
||||
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/json-schema": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz",
|
||||
@ -1172,6 +1189,11 @@
|
||||
"resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
|
||||
"integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U="
|
||||
},
|
||||
"content-type": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
|
||||
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
|
||||
},
|
||||
"convert-source-map": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
|
||||
@ -1778,6 +1800,11 @@
|
||||
"safe-buffer": "^5.1.1"
|
||||
}
|
||||
},
|
||||
"exenv": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
|
||||
"integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50="
|
||||
},
|
||||
"expand-brackets": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
|
||||
@ -3769,6 +3796,20 @@
|
||||
"scheduler": "^0.20.1"
|
||||
}
|
||||
},
|
||||
"react-from-dom": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/react-from-dom/-/react-from-dom-0.5.1.tgz",
|
||||
"integrity": "sha512-ki6OGVgSjDCF0Gt4SMl2cUNBA9ZB8g59bwv9ZiSEXQ37Cw9ZGY0s7EgfPFQYDvaiVx22jto7/dYgQeS+Qw1Mfw=="
|
||||
},
|
||||
"react-inlinesvg": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/react-inlinesvg/-/react-inlinesvg-2.2.2.tgz",
|
||||
"integrity": "sha512-5uXTB0yL9LiRLbN5FhTnL1IK9mLg93kspY2HnKUftzoJDEqZrlscuZxzXStbMBZpNyO359U7QDspM3AqUYUrog==",
|
||||
"requires": {
|
||||
"exenv": "^1.2.2",
|
||||
"react-from-dom": "^0.5.1"
|
||||
}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
@ -3779,6 +3820,16 @@
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz",
|
||||
"integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg=="
|
||||
},
|
||||
"react-svg": {
|
||||
"version": "11.2.1",
|
||||
"resolved": "https://registry.npmjs.org/react-svg/-/react-svg-11.2.1.tgz",
|
||||
"integrity": "sha512-melHPgs52FQ0h9A6Q8I6jtBj12wQLF8ZhHrTd3pUbyTOXkkxn7DmGiNyyc0zh66pKuXaXrYMgOXl/N3ToOYs7A==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@tanem/svg-injector": "^8.2.0",
|
||||
"prop-types": "^15.7.2"
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
@ -4986,6 +5037,15 @@
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||
},
|
||||
"vector-drawable-svg": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/vector-drawable-svg/-/vector-drawable-svg-1.0.2.tgz",
|
||||
"integrity": "sha512-HSyzExG9JPRPwcC3pHQI9Hq/RokYAKMxevGDrxynmF01vFsMqIcZ2HrbJhvofx3f5527PDjMkYvElze7X3polg==",
|
||||
"requires": {
|
||||
"xml-formatter": "^2.4.0",
|
||||
"xmldom": "^0.4.0"
|
||||
}
|
||||
},
|
||||
"vm-browserify": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
|
||||
@ -5335,6 +5395,24 @@
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"xml-formatter": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/xml-formatter/-/xml-formatter-2.4.0.tgz",
|
||||
"integrity": "sha512-xTQ2IfbkCQKn0DGN5SD5KUgTgVohWiolyOXTLUHKJczIuSeGonN0BPduB9VQR5HOEuT1KOHQsOHSmTpU76zpUA==",
|
||||
"requires": {
|
||||
"xml-parser-xo": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"xml-parser-xo": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/xml-parser-xo/-/xml-parser-xo-3.1.1.tgz",
|
||||
"integrity": "sha512-gq1nDlJxjKQpPPZUhLbJ52pghtlB4Rz6LAQULm3SF6xzOYVnUloBglNhJR9vtZB3vIxMN/R3nZTf3qmun+6GCg=="
|
||||
},
|
||||
"xmldom": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.4.0.tgz",
|
||||
"integrity": "sha512-2E93k08T30Ugs+34HBSTQLVtpi6mCddaY8uO+pMNk1pqSjV5vElzn4mmh6KLxN3hki8rNcHSYzILoh3TEWORvA=="
|
||||
},
|
||||
"xtend": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
|
||||
@ -10,6 +10,9 @@
|
||||
"dependencies": {
|
||||
"next": "10.0.5",
|
||||
"react": "17.0.1",
|
||||
"react-dom": "17.0.1"
|
||||
"react-dom": "17.0.1",
|
||||
"react-inlinesvg": "^2.2.2",
|
||||
"react-svg": "^11.2.1",
|
||||
"vector-drawable-svg": "^1.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
37
pages/_document.js
Normal file
@ -0,0 +1,37 @@
|
||||
import Document, {Html, Head, Main, NextScript} from 'next/document'
|
||||
|
||||
export default class MyDocument extends Document {
|
||||
render() {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<Head>
|
||||
<link rel="icon" href="/favicon.ico"/>
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"/>
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"/>
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"/>
|
||||
<link rel="manifest" href="/site.webmanifest"/>
|
||||
<meta name="msapplication-TileColor" content="#1F1F1F"/>
|
||||
<meta name="theme-color" content="#1F1F1F"/>
|
||||
<title>VectorDrawable to SVG</title>
|
||||
|
||||
<meta property="og:url" content="https://vector-drawable.floo.app" />
|
||||
<meta property="og:title" content="Android VectorDrawable to SVG" />
|
||||
<meta property="og:description" content="Quickly create an SVG out of Android VectorDrawable." />
|
||||
<meta property="og:image" content="https://vector-drawable.floo.app/thumbnail-cover.png" />
|
||||
|
||||
<meta name="twitter:card" content="Android VectorDrawable to SVG"/>
|
||||
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com"/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&display=swap"
|
||||
rel="stylesheet"/>
|
||||
</Head>
|
||||
<body>
|
||||
<div className="container">
|
||||
<Main/>
|
||||
</div>
|
||||
<NextScript/>
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
|
||||
export default (req, res) => {
|
||||
res.statusCode = 200
|
||||
res.json({ name: 'John Doe' })
|
||||
}
|
||||
210
pages/index.js
@ -1,65 +1,169 @@
|
||||
import Head from 'next/head'
|
||||
import styles from '../styles/Home.module.css'
|
||||
import {ReactSVG} from "react-svg";
|
||||
import {useState} from "react";
|
||||
import {transform} from 'vector-drawable-svg';
|
||||
import SVG from 'react-inlinesvg';
|
||||
|
||||
|
||||
const STATE_NONE = -1
|
||||
const STATE_DRAG_LEAVE = 0
|
||||
const STATE_DRAGGING = 1
|
||||
const STATE_DROP = 2
|
||||
|
||||
|
||||
function downloadBlob(filename, text) {
|
||||
const element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(text));
|
||||
element.setAttribute('download', filename);
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
}
|
||||
|
||||
function isValidFileType(type) {
|
||||
if (type === 'text/xml') return true;
|
||||
return type === 'application/xml';
|
||||
}
|
||||
|
||||
function transformXmlOrNull(value, options) {
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return transform(value, options)
|
||||
} catch (e) {
|
||||
console.warn(e)
|
||||
}
|
||||
}
|
||||
|
||||
function dropzoneClassOfState(state) {
|
||||
if (state === STATE_DRAG_LEAVE) return '';
|
||||
if (state === STATE_DRAGGING) return 'vd-highlight';
|
||||
if (state === STATE_DROP) return 'vd-active';
|
||||
}
|
||||
|
||||
async function readFileContent(file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => resolve(reader.result)
|
||||
reader.readAsText(file);
|
||||
});
|
||||
}
|
||||
|
||||
export default function Home() {
|
||||
|
||||
const [dragState, setDragState] = useState(STATE_NONE)
|
||||
const [isEnabled, setEnabled] = useState(false);
|
||||
const [vectorDrawableFile, setVectorDrawableFile] = useState()
|
||||
const [transformedSvg, setTransformedSvg] = useState()
|
||||
|
||||
function handleFileUpload() {
|
||||
setEnabled(!isEnabled)
|
||||
}
|
||||
|
||||
function dragEnter(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
setDragState(STATE_DRAGGING)
|
||||
}
|
||||
|
||||
function dragLeave(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
setDragState(STATE_DRAG_LEAVE)
|
||||
}
|
||||
|
||||
async function fileDrop(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const files = e.dataTransfer.files;
|
||||
|
||||
if (files.length > 0) {
|
||||
const file = files[0]
|
||||
if (isValidFileType(file.type)) {
|
||||
const xmlContent = await readFileContent(file);
|
||||
const svgContent = transformXmlOrNull(xmlContent);
|
||||
if (!svgContent) {
|
||||
return;
|
||||
}
|
||||
|
||||
setTransformedSvg(svgContent);
|
||||
setVectorDrawableFile(file);
|
||||
setDragState(STATE_DROP);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
setDragState(STATE_NONE);
|
||||
}
|
||||
|
||||
function dragOver(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.dataTransfer.dropEffect = 'copy';
|
||||
}
|
||||
|
||||
function clearUpload() {
|
||||
setDragState(STATE_NONE)
|
||||
setVectorDrawableFile(null);
|
||||
setTransformedSvg(null);
|
||||
}
|
||||
|
||||
function downloadCurrentSvg() {
|
||||
if (!transformedSvg) {
|
||||
return;
|
||||
}
|
||||
|
||||
let filename = 'output.svg';
|
||||
if (vectorDrawableFile) {
|
||||
filename = vectorDrawableFile.name.split('.').slice(0, -1).join('.') + "svg";
|
||||
}
|
||||
|
||||
downloadBlob(filename, transformedSvg);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<Head>
|
||||
<title>Create Next App</title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
<div className="vd-form-center">
|
||||
<div className="vd-head vd-form-center">
|
||||
<h1 className="vd-title">VectorDrawable to SVG</h1>
|
||||
<p className="vd-subtitle">Drop your valid a vector drawable file here.</p>
|
||||
<div
|
||||
onDragEnter={dragEnter}
|
||||
onDragLeave={dragLeave}
|
||||
onDragOver={dragOver}
|
||||
onDrop={fileDrop}
|
||||
onClick={handleFileUpload}
|
||||
className={"vd-dropzone " + dropzoneClassOfState(dragState)}>
|
||||
<div className="vd-placeholder">
|
||||
<ReactSVG src="plus.svg"/>
|
||||
</div>
|
||||
<div className="vd-image-container">
|
||||
<div onClick={clearUpload} className="text-button-icon">
|
||||
<ReactSVG src="close.svg"/>
|
||||
</div>
|
||||
<div className="vd-image">
|
||||
<SVG src={transformedSvg} width={300} height={300} title="SVG"/>
|
||||
</div>
|
||||
|
||||
<main className={styles.main}>
|
||||
<h1 className={styles.title}>
|
||||
Welcome to <a href="https://nextjs.org">Next.js!</a>
|
||||
</h1>
|
||||
<div className="vd-filename">
|
||||
<p>{vectorDrawableFile?.name}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className={styles.description}>
|
||||
Get started by editing{' '}
|
||||
<code className={styles.code}>pages/index.js</code>
|
||||
</p>
|
||||
<button onClick={downloadCurrentSvg} disabled={!vectorDrawableFile} className="vd-download">
|
||||
<ReactSVG src="/download-circular-button.svg"/>
|
||||
Download
|
||||
</button>
|
||||
|
||||
<div className={styles.grid}>
|
||||
<a href="https://nextjs.org/docs" className={styles.card}>
|
||||
<h3>Documentation →</h3>
|
||||
<p>Find in-depth information about Next.js features and API.</p>
|
||||
</a>
|
||||
|
||||
<a href="https://nextjs.org/learn" className={styles.card}>
|
||||
<h3>Learn →</h3>
|
||||
<p>Learn about Next.js in an interactive course with quizzes!</p>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://github.com/vercel/next.js/tree/master/examples"
|
||||
className={styles.card}
|
||||
>
|
||||
<h3>Examples →</h3>
|
||||
<p>Discover and deploy boilerplate example Next.js projects.</p>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://vercel.com/import?filter=next.js&utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
|
||||
className={styles.card}
|
||||
>
|
||||
<h3>Deploy →</h3>
|
||||
<p>
|
||||
Instantly deploy your Next.js site to a public URL with Vercel.
|
||||
</p>
|
||||
<footer className="vd-footer">
|
||||
<div className="vd-github">
|
||||
<a href="https://github.com/seanghay/vector-drawable-nextjs" target="_blank">
|
||||
<ReactSVG src="/github.svg"/>
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer className={styles.footer}>
|
||||
<a
|
||||
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Powered by{' '}
|
||||
<img src="/vercel.svg" alt="Vercel Logo" className={styles.logo} />
|
||||
</a>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
BIN
public/android-chrome-192x192.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
public/android-chrome-512x512.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
public/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
9
public/browserconfig.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square150x150logo src="/mstile-150x150.png"/>
|
||||
<TileColor>#da532c</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
||||
1
public/close.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="17.414" height="17.414" viewBox="0 0 17.414 17.414"><g transform="translate(-469.793 -420.793)"><line x2="16" y2="16" transform="translate(470.5 421.5)" fill="none" stroke="#269bff" stroke-width="2"/><line x1="16" y2="16" transform="translate(470.5 421.5)" fill="none" stroke="#269bff" stroke-width="2"/></g></svg>
|
||||
|
After Width: | Height: | Size: 361 B |
48
public/download-circular-button.svg
Normal file
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="612px" height="612px" viewBox="0 0 612 612" style="enable-background:new 0 0 612 612;" xml:space="preserve">
|
||||
<g>
|
||||
<g id="_x37__43_">
|
||||
<g>
|
||||
<path d="M403.939,295.749l-78.814,78.833V172.125c0-10.557-8.568-19.125-19.125-19.125c-10.557,0-19.125,8.568-19.125,19.125
|
||||
v202.457l-78.814-78.814c-7.478-7.478-19.584-7.478-27.043,0c-7.478,7.478-7.478,19.584,0,27.042l108.19,108.19
|
||||
c4.59,4.59,10.863,6.005,16.812,4.953c5.929,1.052,12.221-0.382,16.811-4.953l108.19-108.19c7.478-7.478,7.478-19.583,0-27.042
|
||||
C423.523,288.29,411.417,288.29,403.939,295.749z M306,0C137.012,0,0,136.992,0,306s137.012,306,306,306s306-137.012,306-306
|
||||
S475.008,0,306,0z M306,573.75C158.125,573.75,38.25,453.875,38.25,306C38.25,158.125,158.125,38.25,306,38.25
|
||||
c147.875,0,267.75,119.875,267.75,267.75C573.75,453.875,453.875,573.75,306,573.75z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
BIN
public/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
public/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
1
public/github.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg enable-background="new 0 0 24 24" height="512" viewBox="0 0 24 24" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m12 .5c-6.63 0-12 5.28-12 11.792 0 5.211 3.438 9.63 8.205 11.188.6.111.82-.254.82-.567 0-.28-.01-1.022-.015-2.005-3.338.711-4.042-1.582-4.042-1.582-.546-1.361-1.335-1.725-1.335-1.725-1.087-.731.084-.716.084-.716 1.205.082 1.838 1.215 1.838 1.215 1.07 1.803 2.809 1.282 3.495.981.108-.763.417-1.282.76-1.577-2.665-.295-5.466-1.309-5.466-5.827 0-1.287.465-2.339 1.235-3.164-.135-.298-.54-1.497.105-3.121 0 0 1.005-.316 3.3 1.209.96-.262 1.98-.392 3-.398 1.02.006 2.04.136 3 .398 2.28-1.525 3.285-1.209 3.285-1.209.645 1.624.24 2.823.12 3.121.765.825 1.23 1.877 1.23 3.164 0 4.53-2.805 5.527-5.475 5.817.42.354.81 1.077.81 2.182 0 1.578-.015 2.846-.015 3.229 0 .309.21.678.825.56 4.801-1.548 8.236-5.97 8.236-11.173 0-6.512-5.373-11.792-12-11.792z" fill="#ffffff"/></svg>
|
||||
|
After Width: | Height: | Size: 897 B |
BIN
public/mstile-144x144.png
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
BIN
public/mstile-150x150.png
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
BIN
public/mstile-310x150.png
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
BIN
public/mstile-310x310.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
public/mstile-70x70.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
1
public/plus.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg height="426.66667pt" viewBox="0 0 426.66667 426.66667" width="426.66667pt" xmlns="http://www.w3.org/2000/svg"><path d="m405.332031 192h-170.664062v-170.667969c0-11.773437-9.558594-21.332031-21.335938-21.332031-11.773437 0-21.332031 9.558594-21.332031 21.332031v170.667969h-170.667969c-11.773437 0-21.332031 9.558594-21.332031 21.332031 0 11.777344 9.558594 21.335938 21.332031 21.335938h170.667969v170.664062c0 11.777344 9.558594 21.335938 21.332031 21.335938 11.777344 0 21.335938-9.558594 21.335938-21.335938v-170.664062h170.664062c11.777344 0 21.335938-9.558594 21.335938-21.335938 0-11.773437-9.558594-21.332031-21.335938-21.332031zm0 0"/></svg>
|
||||
|
After Width: | Height: | Size: 654 B |
19
public/site.webmanifest
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "",
|
||||
"short_name": "",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/android-chrome-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#ffffff",
|
||||
"background_color": "#ffffff",
|
||||
"display": "standalone"
|
||||
}
|
||||
BIN
public/thumbnail-cover.png
Normal file
|
After Width: | Height: | Size: 69 KiB |
@ -1,4 +0,0 @@
|
||||
<svg width="283" height="64" viewBox="0 0 283 64" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M141.04 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.46 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM248.72 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.45 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM200.24 34c0 6 3.92 10 10 10 4.12 0 7.21-1.87 8.8-4.92l7.68 4.43c-3.18 5.3-9.14 8.49-16.48 8.49-11.05 0-19-7.2-19-18s7.96-18 19-18c7.34 0 13.29 3.19 16.48 8.49l-7.68 4.43c-1.59-3.05-4.68-4.92-8.8-4.92-6.07 0-10 4-10 10zm82.48-29v46h-9V5h9zM36.95 0L73.9 64H0L36.95 0zm92.38 5l-27.71 48L73.91 5H84.3l17.32 30 17.32-30h10.39zm58.91 12v9.69c-1-.29-2.06-.49-3.2-.49-5.81 0-10 4-10 10V51h-9V17h9v9.2c0-5.08 5.91-9.2 13.2-9.2z" fill="#000"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
@ -1,122 +0,0 @@
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
padding: 0 0.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.main {
|
||||
padding: 5rem 0;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
border-top: 1px solid #eaeaea;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.footer img {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.footer a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.title a {
|
||||
color: #0070f3;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.title a:hover,
|
||||
.title a:focus,
|
||||
.title a:active {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: 0;
|
||||
line-height: 1.15;
|
||||
font-size: 4rem;
|
||||
}
|
||||
|
||||
.title,
|
||||
.description {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.description {
|
||||
line-height: 1.5;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.code {
|
||||
background: #fafafa;
|
||||
border-radius: 5px;
|
||||
padding: 0.75rem;
|
||||
font-size: 1.1rem;
|
||||
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
|
||||
Bitstream Vera Sans Mono, Courier New, monospace;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
max-width: 800px;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.card {
|
||||
margin: 1rem;
|
||||
flex-basis: 45%;
|
||||
padding: 1.5rem;
|
||||
text-align: left;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
border: 1px solid #eaeaea;
|
||||
border-radius: 10px;
|
||||
transition: color 0.15s ease, border-color 0.15s ease;
|
||||
}
|
||||
|
||||
.card:hover,
|
||||
.card:focus,
|
||||
.card:active {
|
||||
color: #0070f3;
|
||||
border-color: #0070f3;
|
||||
}
|
||||
|
||||
.card h3 {
|
||||
margin: 0 0 1rem 0;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.card p {
|
||||
margin: 0;
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 1em;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.grid {
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,23 @@
|
||||
:root {
|
||||
--vd-color-surface: #1F1F1F;
|
||||
--vd-color-on-surface: rgba(255, 255, 255, 0.03);
|
||||
--vd-color-stroke: rgba(255, 255, 255, .23);
|
||||
--vd-color-text: rgba(255, 255, 255, 0.69);
|
||||
--vd-color-primary: #269BFF;
|
||||
--vd-color-light-primary: #37a3ff;
|
||||
--vd-color-dark-primary: #1a7fd6;
|
||||
--vd-color-secondary-text: rgba(255, 255, 255, 0.33);
|
||||
--vd-size-corner-radius: 24px;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
||||
font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||
background-color: var(--vd-color-surface);
|
||||
color: var(--vd-color-text);
|
||||
}
|
||||
|
||||
a {
|
||||
@ -11,6 +25,211 @@ a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 720px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.vd-form-center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
.vd-title {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-size: 3em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.vd-subtitle {
|
||||
padding: 0;
|
||||
margin: 10px 0;
|
||||
color: var(--vd-color-secondary-text);
|
||||
text-align: center;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.vd-head {
|
||||
margin-top: 60px;
|
||||
}
|
||||
|
||||
.vd-dropzone {
|
||||
cursor: pointer;
|
||||
margin-top: 24px;
|
||||
min-width: 400px;
|
||||
min-height: 400px;
|
||||
background-color: var(--vd-color-on-surface);
|
||||
border-radius: var(--vd-size-corner-radius);
|
||||
border: 2px dashed var(--vd-color-stroke);
|
||||
position: relative;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.vd-dropzone.vd-highlight {
|
||||
border: 2px dashed var(--vd-color-primary);
|
||||
}
|
||||
|
||||
.vd-dropzone.vd-active {
|
||||
border: 2px dashed var(--vd-color-primary);
|
||||
}
|
||||
|
||||
.vd-dropzone.vd-active .vd-image-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.vd-dropzone.vd-active .vd-placeholder {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.vd-dropzone .vd-image-container {
|
||||
flex-grow: 1;
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.text-button-icon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
margin-right: 14px;
|
||||
margin-top: 12px;
|
||||
padding: 10px;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
border-radius: 50%;
|
||||
transition: 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.text-button-icon:hover {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
.text-button-icon:active {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
|
||||
.vd-dropzone .vd-image-container .vd-filename {
|
||||
background: rgba(0, 0, 0, .1);
|
||||
text-align: center;
|
||||
padding: 8px 14px;
|
||||
}
|
||||
|
||||
.vd-dropzone .vd-image-container .vd-filename p {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.vd-dropzone .vd-image-container .vd-image {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
|
||||
.vd-dropzone .vd-image-container .vd-image img {
|
||||
max-width: 300px;
|
||||
max-height: 300px;
|
||||
}
|
||||
|
||||
|
||||
.vd-placeholder {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.vd-download {
|
||||
margin-top: 28px;
|
||||
}
|
||||
|
||||
button {
|
||||
font-family: inherit;
|
||||
color: inherit;
|
||||
background: var(--vd-color-primary);
|
||||
font-size: 1.2em;
|
||||
border: none;
|
||||
min-width: 400px;
|
||||
border-radius: calc(var(--vd-size-corner-radius) / 1.5);
|
||||
padding: 14px 0;
|
||||
outline: none;
|
||||
transition: .23s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
-webkit-touch-callout: none; /* iOS Safari */
|
||||
-webkit-user-select: none; /* Safari */
|
||||
-khtml-user-select: none; /* Konqueror HTML */
|
||||
-moz-user-select: none; /* Old versions of Firefox */
|
||||
-ms-user-select: none; /* Internet Explorer/Edge */
|
||||
user-select: none; /* Non-prefixed version, currently
|
||||
supported by Chrome, Edge, Opera and Firefox */
|
||||
}
|
||||
|
||||
button:not(:disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
button svg {
|
||||
width: 1.2em;
|
||||
height: 1.2em;
|
||||
fill: var(--vd-color-text);
|
||||
margin-right: 8px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
button:disabled svg {
|
||||
fill: rgba(255, 255,255, 0.17);
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
background: #1C1C1C;
|
||||
color: rgba(255, 255,255, 0.17);
|
||||
}
|
||||
|
||||
button:not(:disabled):hover {
|
||||
background: var(--vd-color-light-primary);
|
||||
}
|
||||
|
||||
button:not(:disabled):active {
|
||||
background: var(--vd-color-dark-primary);
|
||||
}
|
||||
|
||||
.vd-placeholder svg {
|
||||
max-width: 48px;
|
||||
max-height: 48px;
|
||||
fill: var(--vd-color-secondary-text);
|
||||
}
|
||||
|
||||
.vd-footer {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.vd-github svg {
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
}
|
||||
|
||||