diff --git a/package.json b/package.json index 33febe0..2c7081c 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,12 @@ "version": "0.1.0", "private": true, "dependencies": { + "diff": "^4.0.1", + "prismjs": "^1.15.0", "react": "^16.8.0-alpha.1", "react-dom": "^16.8.0-alpha.1", - "react-scripts": "2.1.3" + "react-scripts": "2.1.3", + "react-use": "^5.2.2" }, "scripts": { "start": "react-scripts start", diff --git a/src/app.js b/src/app.js index bd07827..25c46de 100755 --- a/src/app.js +++ b/src/app.js @@ -1,7 +1,9 @@ import React from "react"; +import History from "./history"; function App({ commits }) { - return
{JSON.stringify(commits, null, 2)}
; + console.log(commits); + return ; } export default App; diff --git a/src/differ.js b/src/differ.js new file mode 100644 index 0000000..fb74815 --- /dev/null +++ b/src/differ.js @@ -0,0 +1,143 @@ +import * as diff from "diff"; +import tokenize from "./tokenizer"; +const newlineRe = /\r\n|\r|\n/; + +function myDiff(oldCode, newCode) { + const changes = diff.diffLines(oldCode || "", newCode); + + let oldIndex = -1; + return changes.map(({ value, count, removed, added }) => { + const lines = value.split(newlineRe); + // check if last line is empty, if it is, remove it + const lastLine = lines.pop(); + if (lastLine) { + lines.push(lastLine); + } + const result = { + oldIndex, + lines, + count, + removed, + added + }; + if (!added) { + oldIndex += count; + } + return result; + }); +} + +function insert(array, index, elements) { + return array.splice(index, 0, ...elements); +} + +function slideDiff(lines, codes, slideIndex) { + const prevLines = lines.filter(l => l.slides.includes(slideIndex - 1)); + const prevCode = codes[slideIndex - 1] || ""; + const currCode = codes[slideIndex]; + + const changes = myDiff(prevCode, currCode); + + changes.forEach(change => { + if (change.added) { + const prevLine = prevLines[change.oldIndex]; + const addAtIndex = lines.indexOf(prevLine) + 1; + const addLines = change.lines.map(content => ({ + content, + slides: [slideIndex] + })); + insert(lines, addAtIndex, addLines); + } else if (!change.removed) { + for (let j = 1; j <= change.count; j++) { + prevLines[change.oldIndex + j].slides.push(slideIndex); + } + } + }); + + const tokenLines = tokenize(currCode); + const currLines = lines.filter(l => l.slides.includes(slideIndex)); + currLines.forEach((line, index) => (line.tokens = tokenLines[index])); +} + +export function parseLines(codes) { + const lines = []; + for (let slideIndex = 0; slideIndex < codes.length; slideIndex++) { + slideDiff(lines, codes, slideIndex); + } + return lines; +} + +export function getSlides(codes) { + const lines = parseLines(codes); + // console.log("lines", lines); + return codes.map((_, slideIndex) => { + return lines + .map((line, lineIndex) => ({ + content: line.content, + tokens: line.tokens, + left: line.slides.includes(slideIndex - 1), + middle: line.slides.includes(slideIndex), + right: line.slides.includes(slideIndex + 1), + key: lineIndex + })) + .filter(line => line.middle || line.left || line.right); + }); +} + +// + +function getLines(change) { + return change.value + .trimRight(newlineRe) + .split(newlineRe) + .map(content => ({ + content + })); +} + +export function tripleDiff(left, middle, right) { + const leftDiff = diff.diffLines(left, middle); + const rightDiff = diff.diffLines(middle, right); + + let x = leftDiff + .map(change => + change.value + .trimRight(newlineRe) + .split(newlineRe) + .map(content => ({ + content, + left: !change.added, + middle: !change.removed + })) + ) + .flat(); + // console.log(JSON.stringify(leftDiff, null, 2)); + // console.log(JSON.stringify(x, null, 2)); + + let i = 0; + // console.log(rightDiff); + rightDiff.forEach(change => { + let mx = x.filter(l => l.middle || l.right); + if (change.added) { + const lines = change.value + .trimRight(newlineRe) + .split(newlineRe) + .map(content => ({ + content, + left: false, + middle: false, + right: true + })); + insert(x, i, lines); + } else if (!change.removed) { + // console.log(change); + for (let j = 0; j < change.count; j++) { + mx[i + j].right = true; + } + } + i += change.count; + }); + // console.log(JSON.stringify(rightDiff, null, 2)); + // console.log(JSON.stringify(x, null, 2)); + return x; +} diff --git a/src/github.js b/src/github.js index 28a516f..ac6d8ce 100644 --- a/src/github.js +++ b/src/github.js @@ -12,16 +12,20 @@ export async function getHistory(repo, sha, path, top = 10) { `https://api.github.com/repos/${repo}/commits?sha=${sha}&path=${path}` ); const commitsJson = await commitsResponse.json(); - const commits = commitsJson.map(commit => ({ - sha: commit.sha, - date: new Date(commit.commit.author.date), - author: { - login: commit.author.login, - avatar: commit.author.avatar_url - }, - commitUrl: commit.html_url, - message: commit.commit.message - })); + const commits = commitsJson + .map(commit => ({ + sha: commit.sha, + date: new Date(commit.commit.author.date), + author: { + login: commit.author.login, + avatar: commit.author.avatar_url + }, + commitUrl: commit.html_url, + message: commit.commit.message + })) + .sort(function(a, b) { + return a.date - b.date; + }); await Promise.all( commits.slice(0, top).map(async commit => { diff --git a/src/history.js b/src/history.js new file mode 100644 index 0000000..803ed1e --- /dev/null +++ b/src/history.js @@ -0,0 +1,34 @@ +import React, { useEffect, useState } from "react"; +import { getSlides } from "./differ"; +import { useSpring } from "react-use"; + +export default function History({ commits, language }) { + const codes = commits.map(commit => commit.content); + const slideLines = getSlides(codes); + const [current, target, setTarget] = useSliderSpring(codes.length - 1); + const index = Math.round(current); + + const nextSlide = () => + setTarget(Math.min(Math.round(target + 0.51), slideLines.length - 1)); + const prevSlide = () => setTarget(Math.max(Math.round(target - 0.51), 0)); + useEffect(() => { + document.body.onkeydown = function(e) { + if (e.keyCode === 39) { + nextSlide(); + } else if (e.keyCode === 37) { + prevSlide(); + } else if (e.keyCode === 32) { + setTarget(current); + } + }; + }); + return
{codes[index]}
; +} +function useSliderSpring(initial) { + const [target, setTarget] = useState(initial); + const tension = 0; + const friction = 10; + const value = useSpring(target, tension, friction); + + return [Math.round(value * 100) / 100, target, setTarget]; +} diff --git a/src/tokenizer.js b/src/tokenizer.js new file mode 100644 index 0000000..5202fb6 --- /dev/null +++ b/src/tokenizer.js @@ -0,0 +1,57 @@ +import Prism from "prismjs"; +const newlineRe = /\r\n|\r|\n/; + +// Take a list of nested tokens +// (token.content may contain an array of tokens) +// and flatten it so content is always a string +// and type the type of the leaf +function flattenTokens(tokens) { + const flatList = []; + tokens.forEach(token => { + if (Array.isArray(token.content)) { + flatList.push(...flattenTokens(token.content)); + } else { + flatList.push(token); + } + }); + return flatList; +} + +// Convert strings to tokens +function tokenizeStrings(prismTokens) { + return prismTokens.map(pt => + typeof pt === "string" + ? { type: "plain", content: pt } + : { + type: pt.type, + content: Array.isArray(pt.content) + ? tokenizeStrings(pt.content) + : pt.content + } + ); +} + +export default function tokenize(code, language = "javascript") { + const prismTokens = Prism.tokenize(code, Prism.languages[language]); + const nestedTokens = tokenizeStrings(prismTokens); + const tokens = flattenTokens(nestedTokens); + + let currentLine = []; + const lines = [currentLine]; + tokens.forEach(token => { + const contentLines = token.content.split(newlineRe); + + const firstContent = contentLines.shift(); + if (firstContent !== "") { + currentLine.push({ type: token.type, content: firstContent }); + } + contentLines.forEach(content => { + currentLine = []; + lines.push(currentLine); + if (content !== "") { + currentLine.push({ type: token.type, content }); + } + }); + }); + return lines; +} diff --git a/yarn.lock b/yarn.lock index d1105e5..dc487e1 100755 --- a/yarn.lock +++ b/yarn.lock @@ -825,6 +825,13 @@ dependencies: regenerator-runtime "^0.12.0" +"@babel/runtime@^7.1.2": + version "7.3.1" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.1.tgz#574b03e8e8a9898eaf4a872a92ea20b7846f6f2a" + integrity sha512-7jGW8ppV0ant637pIqAcFfQDDH1orEPGJb8aXfUozuCU3QqX7rX4DA8iwrbPrR1hcH0FTTHz47yQnk+bl5xHQA== + dependencies: + regenerator-runtime "^0.12.0" + "@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2": version "7.2.2" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907" @@ -901,11 +908,24 @@ "@svgr/core" "^2.4.1" loader-utils "^1.1.0" +"@types/prop-types@*": + version "15.5.8" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.5.8.tgz#8ae4e0ea205fe95c3901a5a1df7f66495e3a56ce" + integrity sha512-3AQoUxQcQtLHsK25wtTWIoIpgYjH3vSDroZOUr7PpCHw/jLY1RB9z9E8dBT/OSmwStVgkRNvdh+ZHNiomRieaw== + "@types/q@^1.5.1": version "1.5.1" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.1.tgz#48fd98c1561fe718b61733daed46ff115b496e18" integrity sha512-eqz8c/0kwNi/OEHQfvIuJVLTst3in0e7uTKeuY+WL/zfKn0xVujOTp42bS/vUUokhK5P2BppLd9JXMOMHcgbjA== +"@types/react@^16.7.13": + version "16.8.1" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.8.1.tgz#b431b104ecc6febda170b718caa9f50be66a6750" + integrity sha512-tD1ETKJcuhANOejRc/p7OgQ16DKnbGi0M3LccelKlPnUCDp2a5koVxZFoRN9HN+A+m84HB5VGN7I+r3nNhS3PA== + dependencies: + "@types/prop-types" "*" + csstype "^2.2.0" + "@types/tapable@1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.2.tgz#e13182e1b69871a422d7863e11a4a6f5b814a4bd" @@ -1788,6 +1808,11 @@ boolbase@^1.0.0, boolbase@~1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= +bowser@^1.7.3: + version "1.9.4" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.9.4.tgz#890c58a2813a9d3243704334fa81b96a5c150c9a" + integrity sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2020,6 +2045,11 @@ call-me-maybe@^1.0.1: resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= +callbag-subscribe@^1.4.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/callbag-subscribe/-/callbag-subscribe-1.5.0.tgz#dadc848ab102db7831a333d6a218dab077ab6cc2" + integrity sha512-nlojg2L0AX4MI3IBxUMBE9OyrfBGFvCqeiapDCXLwl2sory1/Z0HWNQnGR/9Gd7EcpRbyRWTrLVB53lW6EjAdA== + caller-callsite@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" @@ -2210,6 +2240,15 @@ cli-width@^2.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= +clipboard@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.4.tgz#836dafd66cf0fea5d71ce5d5b0bf6e958009112d" + integrity sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ== + dependencies: + good-listener "^1.2.2" + select "^1.1.2" + tiny-emitter "^2.0.0" + cliui@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" @@ -2569,6 +2608,14 @@ css-declaration-sorter@^4.0.1: postcss "^7.0.1" timsort "^0.3.0" +css-in-js-utils@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz#3b472b398787291b47cfe3e44fecfdd9e914ba99" + integrity sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA== + dependencies: + hyphenate-style-name "^1.0.2" + isobject "^3.0.1" + css-loader@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-1.0.0.tgz#9f46aaa5ca41dbe31860e3b62b8e23c42916bf56" @@ -2629,7 +2676,7 @@ css-tree@1.0.0-alpha.28: mdn-data "~1.1.0" source-map "^0.5.3" -css-tree@1.0.0-alpha.29: +css-tree@1.0.0-alpha.29, css-tree@^1.0.0-alpha.28: version "1.0.0-alpha.29" resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" integrity sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg== @@ -2754,6 +2801,11 @@ cssstyle@^1.0.0, cssstyle@^1.1.1: dependencies: cssom "0.3.x" +csstype@^2.2.0, csstype@^2.5.5: + version "2.6.2" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.2.tgz#3043d5e065454579afc7478a18de41909c8a2f01" + integrity sha512-Rl7PvTae0pflc1YtxtKbiSqq20Ts6vpIYOD5WBafl4y123DyHUeLrRdQP66sQW8/6gmX8jrYJLXwNeMqYVJcow== + cyclist@~0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" @@ -2906,6 +2958,11 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= +delegate@^3.1.2: + version "3.2.0" + resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166" + integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== + delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" @@ -2964,6 +3021,11 @@ diff@^3.2.0: resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== +diff@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff" + integrity sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q== + diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -3196,6 +3258,13 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +error-stack-parser@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.2.tgz#4ae8dbaa2bf90a8b450707b9149dcabca135520d" + integrity sha512-E1fPutRDdIj/hohG0UpT5mayXNCxXP9d+snxFsPU9X0XgccOumKraa3juDMwTUyi7+Bu5+mCGagjg4IYeNbOdw== + dependencies: + stackframe "^1.0.4" + es-abstract@^1.12.0, es-abstract@^1.5.1, es-abstract@^1.7.0: version "1.13.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" @@ -3691,6 +3760,11 @@ fast-levenshtein@~2.0.4: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fastest-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fastest-stable-stringify/-/fastest-stable-stringify-1.0.1.tgz#9122d406d4c9d98bea644a6b6853d5874b87b028" + integrity sha1-kSLUBtTJ2YvqZEpraFPVh0uHsCg= + fastparse@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" @@ -4162,6 +4236,13 @@ globby@^6.1.0: pify "^2.0.0" pinkie-promise "^2.0.0" +good-listener@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50" + integrity sha1-1TswzfkxPf+33JoNR3CWqm0UXFA= + dependencies: + delegate "^3.1.2" + graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6: version "4.1.15" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" @@ -4513,6 +4594,11 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= +hyphenate-style-name@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz#097bb7fa0b8f1a9cf0bd5c734cf95899981a9b48" + integrity sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ== + iconv-lite@0.4.23: version "0.4.23" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" @@ -4654,6 +4740,14 @@ ini@^1.3.4, ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== +inline-style-prefixer@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-4.0.2.tgz#d390957d26f281255fe101da863158ac6eb60911" + integrity sha512-N8nVhwfYga9MiV9jWlwfdj1UDIaZlBFu4cJSJkIr7tZX7sHpHhGR5su1qdpW+7KPL8ISTvCIkcaFi/JdBknvPg== + dependencies: + bowser "^1.7.3" + css-in-js-utils "^2.0.0" + inquirer@6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.0.tgz#51adcd776f661369dc1e894859c2560a224abdd8" @@ -5688,6 +5782,11 @@ jsx-ast-utils@^2.0.1: dependencies: array-includes "^3.0.3" +keyboardjs@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/keyboardjs/-/keyboardjs-2.5.1.tgz#2eb5d96bd1028e07136cd71919f607579edca716" + integrity sha512-mRf7MQMiFcudADEpPn3vTtl/rtFELo5MAiKA6yH4ShsFsnwwjMrVfaNt6bpYhBDeODs/T5NXwltz4+ktRQyP7A== + killable@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" @@ -6285,6 +6384,20 @@ nan@^2.9.2: resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw== +nano-css@^3.4.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/nano-css/-/nano-css-3.5.0.tgz#2406956def55ead602f88ee64b5caf3e7ab1e14d" + integrity sha512-PygEOJFZyjlrrjb8uTAxnRSveJH8byZEQfJDPMhEhijPJGfUeBHCFK5pEIN/JsCwqOxl94y/fw0d9k0Yoc6fyg== + dependencies: + css-tree "^1.0.0-alpha.28" + csstype "^2.5.5" + fastest-stable-stringify "^1.0.1" + inline-style-prefixer "^4.0.0" + rtl-css-js "^1.9.0" + sourcemap-codec "^1.4.1" + stacktrace-js "^2.0.0" + stylis "3.5.0" + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -7656,6 +7769,13 @@ pretty-format@^23.6.0: ansi-regex "^3.0.0" ansi-styles "^3.2.0" +prismjs@^1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.15.0.tgz#8801d332e472091ba8def94976c8877ad60398d9" + integrity sha512-Lf2JrFYx8FanHrjoV5oL8YHCclLQgbJcVZR+gikGGMqz6ub5QVWDTM6YIwm3BuPxM/LOV+rKns3LssXNLIf+DA== + optionalDependencies: + clipboard "^2.0.0" + private@^0.1.6, private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -7971,6 +8091,26 @@ react-scripts@2.1.3: optionalDependencies: fsevents "1.2.4" +react-use@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/react-use/-/react-use-5.2.2.tgz#6590866304528905028cc03088188b892f4871f2" + integrity sha512-k3upFSTInBNOa0QLKE+0Re3nkbxYTu4ga2hX4knwxMmaINuPJmF1O9yBGlTUvYdtpDv+UZoficmC95A3PK64GQ== + dependencies: + "@types/react" "^16.7.13" + keyboardjs "^2.5.1" + nano-css "^3.4.0" + react-wait "^0.3.0" + rebound "^0.1.0" + throttle-debounce "^2.0.1" + ts-easing "^0.1.0" + use-callbag "^0.1.2" + use-onclickoutside "^0.1.0" + +react-wait@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/react-wait/-/react-wait-0.3.0.tgz#0cdd4d919012451a5bc3ab0a16d00c6fd9a8c10b" + integrity sha512-kB5x/kMKWcn0uVr9gBdNz21/oGbQwEQnF3P9p6E9yLfJ9DRcKS0fagbgYMFI0YFOoyKDj+2q6Rwax0kTYJF37g== + react@^16.8.0-alpha.1: version "16.8.0-alpha.1" resolved "https://registry.yarnpkg.com/react/-/react-16.8.0-alpha.1.tgz#c2b32689f3b466d3ce85a634dd9035f789d2cd97" @@ -8063,6 +8203,11 @@ realpath-native@^1.0.0: dependencies: util.promisify "^1.0.0" +rebound@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/rebound/-/rebound-0.1.0.tgz#0638c61a93666bb515a58a03e1cfb34021e88b72" + integrity sha1-BjjGGpNma7UVpYoD4c+zQCHoi3I= + recursive-readdir@2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" @@ -8364,6 +8509,13 @@ rsvp@^3.3.3: resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a" integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw== +rtl-css-js@^1.9.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/rtl-css-js/-/rtl-css-js-1.11.0.tgz#a7151930ef9d54656607d754ebb172ddfc9ef836" + integrity sha512-YnZ6jWxZxlWlcQAGF9vOmiF9bEmoQmSHE+wsrsiILkdK9HqiRPAIll4SY/QDzbvEu2lB2h62+hfg3TYzjnldbA== + dependencies: + "@babel/runtime" "^7.1.2" + run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" @@ -8472,6 +8624,11 @@ select-hose@^2.0.0: resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= +select@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" + integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0= + selfsigned@^1.9.1: version "1.10.4" resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.4.tgz#cdd7eccfca4ed7635d47a08bf2d5d3074092e2cd" @@ -8747,6 +8904,11 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= +source-map@0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + integrity sha1-dc449SvwczxafwwRjYEzSiu19BI= + source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -8757,6 +8919,11 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +sourcemap-codec@^1.4.1: + version "1.4.4" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.4.tgz#c63ea927c029dd6bd9a2b7fa03b3fec02ad56e9f" + integrity sha512-CYAPYdBu34781kLHkaW3m6b/uUSyMOC2R61gcYMWooeuaGtjof86ZA/8T+qVPPt7np1085CR9hmMGrySwEc8Xg== + spdx-correct@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" @@ -8852,11 +9019,40 @@ stable@~0.1.6: resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== +stack-generator@^2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/stack-generator/-/stack-generator-2.0.3.tgz#bb74385c67ffc4ccf3c4dee5831832d4e509c8a0" + integrity sha512-kdzGoqrnqsMxOEuXsXyQTmvWXZmG0f3Ql2GDx5NtmZs59sT2Bt9Vdyq0XdtxUi58q/+nxtbF9KOQ9HkV1QznGg== + dependencies: + stackframe "^1.0.4" + stack-utils@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== +stackframe@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.0.4.tgz#357b24a992f9427cba6b545d96a14ed2cbca187b" + integrity sha512-to7oADIniaYwS3MhtCa/sQhrxidCCQiF/qp4/m5iN3ipf0Y7Xlri0f6eG29r08aL7JYl8n32AF3Q5GYBZ7K8vw== + +stacktrace-gps@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/stacktrace-gps/-/stacktrace-gps-3.0.2.tgz#33f8baa4467323ab2bd1816efa279942ba431ccc" + integrity sha512-9o+nWhiz5wFnrB3hBHs2PTyYrS60M1vvpSzHxwxnIbtY2q9Nt51hZvhrG1+2AxD374ecwyS+IUwfkHRE/2zuGg== + dependencies: + source-map "0.5.6" + stackframe "^1.0.4" + +stacktrace-js@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/stacktrace-js/-/stacktrace-js-2.0.0.tgz#776ca646a95bc6c6b2b90776536a7fc72c6ddb58" + integrity sha1-d2ymRqlbxsayuQd2U2p/xyxt21g= + dependencies: + error-stack-parser "^2.0.1" + stack-generator "^2.0.1" + stacktrace-gps "^3.0.1" + static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" @@ -9033,6 +9229,11 @@ stylehacks@^4.0.0: postcss "^7.0.0" postcss-selector-parser "^3.0.0" +stylis@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.0.tgz#016fa239663d77f868fef5b67cf201c4b7c701e1" + integrity sha512-pP7yXN6dwMzAR29Q0mBrabPCe0/mNO1MSr93bhay+hcZondvMMTpeGyd8nbhYJdyperNT2DRxONQuUGcJr5iPw== + supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -9151,6 +9352,11 @@ throat@^4.0.0: resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo= +throttle-debounce@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-2.1.0.tgz#257e648f0a56bd9e54fe0f132c4ab8611df4e1d5" + integrity sha512-AOvyNahXQuU7NN+VVvOOX+uW6FPaWdAOdRP5HfwYxAfCzXTFKRMoIMk+n+po318+ktcChx+F1Dd91G3YHeMKyg== + through2@^2.0.0: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" @@ -9181,6 +9387,11 @@ timsort@^0.3.0: resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= +tiny-emitter@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.0.2.tgz#82d27468aca5ade8e5fd1e6d22b57dd43ebdfb7c" + integrity sha512-2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow== + tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -9273,6 +9484,11 @@ tryer@^1.0.0: resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== +ts-easing@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ts-easing/-/ts-easing-0.1.1.tgz#055c68ba878ddb78d7b22ce4852557b8b8366bcd" + integrity sha512-0ak4XidpHPzrGFShdgKWY70EyShH/jKUARsJD7GjmQDmHVWxnuIzhN+B2aCqB/0lp/QGSbuk1rOXxQasRc5yiA== + tslib@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" @@ -9472,6 +9688,18 @@ url@^0.11.0: punycode "1.3.2" querystring "0.2.0" +use-callbag@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/use-callbag/-/use-callbag-0.1.2.tgz#8f214952ccc488159b185ffe7ff17fccba7a73d3" + integrity sha512-8JJIpoqQaqJu9nfSTYe4WpJm2NyfHYgIDjouxhu4WOpgYI8W9IvMM32ecfcdZTzkWDuZkEyh3unGLMxA4wF7Bg== + dependencies: + callbag-subscribe "^1.4.1" + +use-onclickoutside@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/use-onclickoutside/-/use-onclickoutside-0.1.1.tgz#14327d6062639541374cb48db02cac3ebe7836ac" + integrity sha512-IcQzKjG9OAlMQBGmUZ/3pU6DUuynPb6KlZaGNOFdmJ0FaV1yhJLauvvPcTerWAuH84K/cbkOLyAgncY+oTLtcg== + use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"