├── .github └── FUNDING.yml ├── .gitignore ├── blog-demo ├── .prettierrc ├── content │ ├── assets │ │ └── avatar.png │ └── posts │ │ └── hello-world.mdx ├── gatsby-config.js ├── package.json └── src │ └── gatsby-plugin-theme-ui │ └── index.js ├── demo ├── .gitignore ├── .prettierrc ├── blog │ ├── assets │ │ └── avatar.png │ ├── posts │ │ └── post.mdx │ └── theme-ui.js ├── decks │ ├── counter.js │ ├── hi.mdx │ └── theme.js ├── gatsby-config.js ├── package.json ├── src │ ├── components │ │ ├── charts │ │ │ ├── chart-wave.js │ │ │ ├── layout.js │ │ │ └── waves-variant.js │ │ ├── deck │ │ │ ├── deck-wave.js │ │ │ ├── embed.js │ │ │ ├── layout.js │ │ │ └── waves-variant.js │ │ ├── header.js │ │ ├── images │ │ │ ├── layout.js │ │ │ └── waves-variant.js │ │ └── maps │ │ │ ├── layout.js │ │ │ ├── maps-wave.js │ │ │ └── waves-variant.js │ ├── gatsby-theme-blog │ │ └── components │ │ │ └── layout.js │ ├── gatsby-theme-mdx-deck │ │ └── templates │ │ │ └── deck.js │ └── pages │ │ ├── charts │ │ └── index.mdx │ │ ├── deck │ │ └── index.mdx │ │ ├── images │ │ ├── 01.jpg │ │ ├── 04.jpg │ │ ├── 05.jpg │ │ ├── 06.jpg │ │ ├── 07.jpg │ │ ├── 08.jpg │ │ ├── 09.jpg │ │ ├── 10.jpg │ │ ├── 11.jpg │ │ └── index.mdx │ │ ├── index.js │ │ ├── maps │ │ └── index.mdx │ │ ├── media │ │ ├── chart.png │ │ ├── chart.t.png │ │ ├── charts.mp4 │ │ ├── charts.webm │ │ ├── code-dark.png │ │ ├── code-dark.t.png │ │ ├── code.gif │ │ ├── code.mp4 │ │ ├── code.png │ │ ├── code.t.png │ │ ├── code.webm │ │ ├── deck.mp4 │ │ ├── deck.png │ │ ├── deck.t.png │ │ ├── deck.webm │ │ ├── home.jpg │ │ ├── image.png │ │ ├── image.t.png │ │ ├── images.mp4 │ │ ├── images.webm │ │ ├── jam.png │ │ ├── maps.mp4 │ │ ├── maps.png │ │ ├── maps.t.png │ │ └── maps.webm │ │ └── screenshots.js ├── static │ └── favicon.ico └── yarn.lock ├── license ├── package.json ├── readme.md ├── rehype-waves ├── .npmignore ├── __file_snapshots__ │ ├── codeblock.mdx-0 │ ├── metastring.mdx-0 │ ├── minimal.mdx-0 │ └── multi-steps.mdx-0 ├── __fixtures__ │ ├── codeblock.mdx │ ├── metastring.mdx │ ├── minimal.mdx │ └── multi-steps.mdx ├── index.js ├── package.json ├── parser.js ├── readme.md ├── step-reader.js └── test.js ├── theme ├── .gitignore ├── .prettierrc ├── gatsby-config.js ├── gatsby-node.js ├── index.js ├── license ├── package.json ├── readme.md └── src │ ├── components │ ├── bar-scroller.js │ ├── code-sticker.js │ ├── code-wave.js │ ├── image-sticker.js │ ├── image-wave.js │ ├── opacity-scroller.js │ └── wave.js │ ├── gatsby-plugin-theme-ui │ ├── index.js │ └── waves.js │ └── stuff │ └── step-reader.js └── yarn.lock /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | patreon: pomber 2 | custom: https://www.paypal.me/pomber 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # dotenv environment variables file 55 | .env 56 | 57 | # gatsby files 58 | .cache/ 59 | public 60 | 61 | # Mac files 62 | .DS_Store 63 | 64 | # Yarn 65 | yarn-error.log 66 | .pnp/ 67 | .pnp.js 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | .netlify/ 72 | -------------------------------------------------------------------------------- /blog-demo/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "lf", 3 | "semi": false, 4 | "singleQuote": false, 5 | "tabWidth": 2, 6 | "trailingComma": "es5", 7 | "overrides": [ 8 | { 9 | "files": "*.mdx", 10 | "options": { 11 | "printWidth": 50 12 | } 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /blog-demo/content/assets/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/blog-demo/content/assets/avatar.png -------------------------------------------------------------------------------- /blog-demo/content/posts/hello-world.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Hello World 3 | --- 4 | 5 | import { CodeWave } from "gatsby-theme-waves" 6 | 7 | # This is the Title 8 | 9 | Lorem ipsum dolor sit amet, fugit errem volumus ex sit, magna fugit deserunt et qui. Sapientem mnesarchum ei vis, offendit appetere inimicus eu has. Te utamur voluptua per. Per dicant intellegebat in. Laboramus referrentur id his, electram philosophia sit an. Possim efficiendi no sea, eu admodum copiosae indoctum mea. 10 | 11 | Sit eligendi dignissim et, sit eius ancillae voluptatibus te. Ea summo nostrum omnesque sed. Deserunt iracundia definiebas ei est. An vitae reprimique ius, facer timeam cu nam. 12 | 13 | Id quot impetus prodesset eum, et usu iuvaret alienum. Ut amet quaerendum pro, impetus appetere disputando te per. Stet congue ancillae mei in, nam fuisset antiopam id. Ad denique blandit accommodare ius. Solum legere ea sea, per cu affert timeam, meis expetendis intellegebat ex pro. 14 | 15 | Nec probo paulo facilisi cu, eu nibh persecuti mea. Ut aperiam deseruisse est, eos eu delicata repudiare aliquando. Mei te justo euismod accusam, eos posse saperet elaboraret ne, mucius quodsi vocibus sit in. Mea at utinam maiorum, mei eu tale etiam. 16 | 17 | Te eos antiopam honestatis. No graeci regione nam, mea te accusam disputationi. An quo bonorum blandit honestatis, at nam wisi facilis oportere. Appetere democritum mea cu. Te tempor lobortis duo, vim an dicunt ornatus. 18 | 19 | 20 | 21 | ```jsx 22 | function HelloWorld({ 23 | greeting = "hello", 24 | greeted = '"World"', 25 | silent = false, 26 | onMouseOver, 27 | }) { 28 | // TODO write more code 29 | } 30 | ``` 31 | 32 | Lorem ipsum dolor sit amet, fugit errem volumus ex sit, magna fugit deserunt et qui. Sapientem mnesarchum ei vis, offendit appetere inimicus eu has. Te utamur voluptua per. Per dicant intellegebat in. Laboramus referrentur id his, electram philosophia sit an. Possim efficiendi no sea, eu admodum copiosae indoctum mea. 33 | 34 | ```js 35 | function HelloWorld({ 36 | greeting = "hello", 37 | greeted = '"World"', 38 | silent = false, 39 | onMouseOver, 40 | }) { 41 | if (!greeting) { 42 | return null 43 | } 44 | 45 | // TODO write more code 46 | } 47 | ``` 48 | 49 | Sit eligendi dignissim et, sit eius ancillae voluptatibus te. Ea summo nostrum omnesque sed. Deserunt iracundia definiebas ei est. 50 | 51 | - omnesque 52 | - tempor 53 | - referrentur 54 | 55 | An vitae reprimique ius, facer timeam cu nam. 56 | 57 | ```js 58 | function HelloWorld({ 59 | greeting = "hello", 60 | greeted = '"World"', 61 | silent = false, 62 | onMouseOver, 63 | }) { 64 | if (!greeting) { 65 | return null 66 | } 67 | 68 | let num = 0 69 | 70 | return ( 71 |
76 | 77 | {greeting.slice(0, 1).toUpperCase() + 78 | greeting.slice(1).toLowerCase()} 79 | 80 | {greeting.endsWith(",") ? ( 81 | " " 82 | ) : ( 83 | 84 | ", " 85 | 86 | )} 87 | {greeted} 88 | {silent ? "." : "!"} 89 |
90 | ) 91 | } 92 | ``` 93 | 94 | ## Id quot impetus prodesset eum 95 | 96 | > et usu iuvaret alienum 97 | 98 | Ut amet quaerendum pro, impetus appetere disputando te per. Stet congue ancillae mei in, nam fuisset antiopam id. Ad denique blandit accommodare ius. Solum legere ea sea, per cu affert timeam, meis expetendis intellegebat ex pro. 99 | 100 | ```js 11 101 | function HelloWorld({ 102 | greeting = "hello", 103 | greeted = '"World"', 104 | silent = false, 105 | onMouseOver, 106 | }) { 107 | if (!greeting) { 108 | return null 109 | } 110 | 111 | let num = 0 112 | 113 | return ( 114 |
119 | 120 | {greeting.slice(0, 1).toUpperCase() + 121 | greeting.slice(1).toLowerCase()} 122 | 123 | {greeting.endsWith(",") ? ( 124 | " " 125 | ) : ( 126 | 127 | ", " 128 | 129 | )} 130 | {greeted} 131 | {silent ? "." : "!"} 132 |
133 | ) 134 | } 135 | ``` 136 | 137 | Nec probo paulo facilisi cu, eu nibh persecuti mea. Ut aperiam deseruisse est, eos eu delicata repudiare aliquando. Mei te justo euismod accusam, eos posse saperet elaboraret ne, mucius quodsi vocibus sit in. Mea at utinam maiorum, mei eu tale etiam. 138 | 139 | ```js 140 | function HelloWorld({ 141 | greeting = "hello", 142 | greeted = '"World"', 143 | silent = false, 144 | onMouseOver, 145 | }) { 146 | if (!greeting) { 147 | return null 148 | } 149 | 150 | // TODO: Don't use random in render 151 | let num = Math.floor(Math.random() * 1e7) 152 | .toString() 153 | .replace(/\.\d+/gi, "") 154 | 155 | return ( 156 |
161 | 162 | {greeting.slice(0, 1).toUpperCase() + 163 | greeting.slice(1).toLowerCase()} 164 | 165 | {greeting.endsWith(",") ? ( 166 | " " 167 | ) : ( 168 | 169 | ", " 170 | 171 | )} 172 | {greeted} 173 | {silent ? "." : "!"} 174 |
175 | ) 176 | } 177 | ``` 178 | 179 | Te eos antiopam honestatis. No graeci regione nam, mea te accusam disputationi. An quo bonorum blandit honestatis, at nam wisi facilis oportere. Appetere democritum mea cu. Te tempor lobortis duo, vim an dicunt ornatus. 180 | 181 | ```js 1:37 182 | function HelloWorld({ 183 | greeting = "hello", 184 | greeted = '"World"', 185 | silent = false, 186 | onMouseOver, 187 | }) { 188 | if (!greeting) { 189 | return null 190 | } 191 | 192 | // TODO: Don't use random in render 193 | let num = Math.floor(Math.random() * 1e7) 194 | .toString() 195 | .replace(/\.\d+/gi, "") 196 | 197 | return ( 198 |
203 | 204 | {greeting.slice(0, 1).toUpperCase() + 205 | greeting.slice(1).toLowerCase()} 206 | 207 | {greeting.endsWith(",") ? ( 208 | " " 209 | ) : ( 210 | 211 | ", " 212 | 213 | )} 214 | {greeted} 215 | {silent ? "." : "!"} 216 |
217 | ) 218 | } 219 | ``` 220 | 221 | Sit eligendi dignissim et, sit eius ancillae voluptatibus te. Ea summo nostrum omnesque sed. Deserunt iracundia definiebas ei est. 222 | 223 |
224 | 225 | Lorem ipsum dolor sit amet, fugit errem volumus ex sit, magna fugit deserunt et qui. Sapientem mnesarchum ei vis, offendit appetere inimicus eu has. Te utamur voluptua per. Per dicant intellegebat in. Laboramus referrentur id his, electram philosophia sit an. Possim efficiendi no sea, eu admodum copiosae indoctum mea. 226 | 227 | Sit eligendi dignissim et, sit eius ancillae voluptatibus te. Ea summo nostrum omnesque sed. Deserunt iracundia definiebas ei est. An vitae reprimique ius, facer timeam cu nam. 228 | 229 | Id quot impetus prodesset eum, et usu iuvaret alienum. Ut amet quaerendum pro, impetus appetere disputando te per. Stet congue ancillae mei in, nam fuisset antiopam id. Ad denique blandit accommodare ius. Solum legere ea sea, per cu affert timeam, meis expetendis intellegebat ex pro. 230 | 231 | Nec probo paulo facilisi cu, eu nibh persecuti mea. Ut aperiam deseruisse est, eos eu delicata repudiare aliquando. Mei te justo euismod accusam, eos posse saperet elaboraret ne, mucius quodsi vocibus sit in. Mea at utinam maiorum, mei eu tale etiam. 232 | -------------------------------------------------------------------------------- /blog-demo/gatsby-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [`gatsby-theme-blog`, `gatsby-theme-waves`] 3 | }; 4 | -------------------------------------------------------------------------------- /blog-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blog-demo", 3 | "private": true, 4 | "version": "0.0.1", 5 | "scripts": { 6 | "develop": "gatsby develop", 7 | "start": "gatsby develop", 8 | "build": "gatsby build" 9 | }, 10 | "dependencies": { 11 | "deepmerge": "^4.0.0", 12 | "gatsby": "^2.13.24", 13 | "gatsby-theme-blog": "^1.0.2", 14 | "gatsby-theme-waves": "*", 15 | "react": "^16.8.6", 16 | "react-dom": "^16.8.6" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /blog-demo/src/gatsby-plugin-theme-ui/index.js: -------------------------------------------------------------------------------- 1 | import wavesTheme from "gatsby-theme-waves/src/gatsby-plugin-theme-ui/index"; 2 | import blogTheme from "gatsby-theme-blog/src/gatsby-plugin-theme-ui/index"; 3 | import merge from "deepmerge"; 4 | 5 | export default merge(blogTheme, wavesTheme); 6 | -------------------------------------------------------------------------------- /demo/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # dotenv environment variables file 55 | .env 56 | 57 | # gatsby files 58 | .cache/ 59 | public 60 | 61 | # Mac files 62 | .DS_Store 63 | 64 | # Yarn 65 | yarn-error.log 66 | .pnp/ 67 | .pnp.js 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | -------------------------------------------------------------------------------- /demo/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "lf", 3 | "semi": false, 4 | "singleQuote": false, 5 | "tabWidth": 2, 6 | "trailingComma": "es5", 7 | "overrides": [ 8 | { 9 | "files": "*.mdx", 10 | "options": { 11 | "printWidth": 50 12 | } 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /demo/blog/assets/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/blog/assets/avatar.png -------------------------------------------------------------------------------- /demo/blog/posts/post.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Hello World 3 | --- 4 | 5 | import { CodeWave } from "gatsby-theme-waves" 6 | 7 | --- 8 | 9 | Lorem ipsum dolor sit amet, fugit errem volumus ex sit, magna fugit deserunt et qui. Sapientem mnesarchum ei vis, offendit appetere inimicus eu has. Te utamur voluptua per. Per dicant intellegebat in. Laboramus referrentur id his, electram philosophia sit an. Possim efficiendi no sea, eu admodum copiosae indoctum mea. 10 | 11 | Sit eligendi dignissim et, sit eius ancillae voluptatibus te. Ea summo nostrum omnesque sed. Deserunt iracundia definiebas ei est. An vitae reprimique ius, facer timeam cu nam. 12 | 13 | Id quot impetus prodesset eum, et usu iuvaret alienum. Ut amet quaerendum pro, impetus appetere disputando te per. Stet congue ancillae mei in, nam fuisset antiopam id. Ad denique blandit accommodare ius. Solum legere ea sea, per cu affert timeam, meis expetendis intellegebat ex pro. 14 | 15 | ## Fatum quoque fluminaque 16 | 17 | Nec probo paulo facilisi cu, eu nibh persecuti mea. Ut aperiam deseruisse est, eos eu delicata repudiare aliquando. Mei te justo euismod accusam, eos posse saperet elaboraret ne, mucius quodsi vocibus sit in. Mea at utinam maiorum, mei eu tale etiam. 18 | 19 | Te eos antiopam honestatis. No graeci regione nam, mea te accusam disputationi. An quo bonorum blandit honestatis, at nam wisi facilis oportere. Appetere democritum mea cu. Te tempor lobortis duo, vim an dicunt ornatus. 20 | 21 | 22 | 23 | ```jsx 24 | function HelloWorld({ 25 | greeting = "hello", 26 | greeted = '"World"', 27 | silent = false, 28 | onMouseOver, 29 | }) { 30 | // TODO write more code 31 | } 32 | ``` 33 | 34 | ### Pugnae ortas 35 | 36 | Lorem markdownum; horror testudine colorque si neque memor! Dextraque inlisit 37 | mundi contraxere resurgere sentis, quod belua requirere super naturae. 38 | 39 |
40 | 41 | ```python 42 | # Hi 43 | ``` 44 | 45 |
46 | 47 | Ad molle respicit, **venerat cum mansit** ferventi tempora. Tela insignia. 48 | Threicius altera fundamina ex **preces**: quaerenti ferarum adspicit mihi 49 | pharetramque huius, esses [ambae](http://quiespraemia.org/gerebat) nitido cuncta 50 | dixit litus. Fovi avara iniusti illi aequaret conata tergum, et et. Sub 51 | accendit, et ab recens auctore sumptis, carina illac, patriaeque. 52 | 53 | ```js 54 | function HelloWorld({ 55 | greeting = "hello", 56 | greeted = '"World"', 57 | silent = false, 58 | onMouseOver, 59 | }) { 60 | if (!greeting) { 61 | return null 62 | } 63 | 64 | // TODO write more code 65 | } 66 | ``` 67 | 68 | Umeros haud arida, sinuosa. [Dabat dato](http://urbsut.org/eadem) bracchia 69 | qualia, aversum, motu fuerat nulla pelle est fluctibus esses pariterque secto. 70 | In summo se natum ursos ramis geminas; pestifero formosior suscipiunt forte. 71 | 72 | > Duorum meo arma, spatioque captatam cursus, iunctus ictus terrigenasque felix? 73 | > Nec sidereis voce ora dominari concutio _sustinet_ amisit? Mala suo tum animae 74 | > casas Venerem consedit omen Olympus Parcarum aede eque proceres: 75 | > [huic](http://venit.io/haut). 76 | 77 | ```js 78 | function HelloWorld({ 79 | greeting = "hello", 80 | greeted = '"World"', 81 | silent = false, 82 | onMouseOver, 83 | }) { 84 | if (!greeting) { 85 | return null 86 | } 87 | 88 | let num = 0 89 | 90 | return ( 91 |
96 | 97 | {greeting.slice(0, 1).toUpperCase() + 98 | greeting.slice(1).toLowerCase()} 99 | 100 | {greeting.endsWith(",") ? ( 101 | " " 102 | ) : ( 103 | 104 | ", " 105 | 106 | )} 107 | {greeted} 108 | {silent ? "." : "!"} 109 |
110 | ) 111 | } 112 | ``` 113 | 114 | ### Fuerit difficile parentem soceri 115 | 116 | Scitusque si causas edita Athenae **videri**. Hoc olor naturalique mihi haesit 117 | virago congestaque passa crepitantia _honorque flexo trahendo_ agris; 118 | deprenderat accedere Noctisque altior. Summam insuperabile quae; qui poena 119 | granum spectes. 120 | 121 | 1. Sunt tamen meruere fonte soceri praestant nostrae 122 | 2. E utrimque pater quo 123 | 3. Orbes Iovis Celadon Hodites 124 | 125 | Digitos nocte dixit fessa moderato [positisque solis](http://quosignis.net/) 126 | secreta, fulvae Cytherea, acerris inposito. Antiquus apta, nec fragmina torquet 127 | Cithaeron extentam turpius regna quid _terras favent_. Undique ingenium! 128 | Cyclopum iurgia, liquerat cacumine aliquis cecidere tectoque dixit posses. 129 | 130 | ```js 11 131 | function HelloWorld({ 132 | greeting = "hello", 133 | greeted = '"World"', 134 | silent = false, 135 | onMouseOver, 136 | }) { 137 | if (!greeting) { 138 | return null 139 | } 140 | 141 | let num = 0 142 | 143 | return ( 144 |
149 | 150 | {greeting.slice(0, 1).toUpperCase() + 151 | greeting.slice(1).toLowerCase()} 152 | 153 | {greeting.endsWith(",") ? ( 154 | " " 155 | ) : ( 156 | 157 | ", " 158 | 159 | )} 160 | {greeted} 161 | {silent ? "." : "!"} 162 |
163 | ) 164 | } 165 | ``` 166 | 167 | Quae centum: possumus explorat, vitium mari nepotis miserere susurra _madescit_ 168 | indignis essent. Cecidere thalamosque suos editus ardent hesternos praerupit 169 | tenuit. Erat terque facit iuvenci pericula: provolvi et post. 170 | 171 | Sparsa fuge, loton nota ora illi illi. Est pectore tibi amor faciem Victor 172 | diuque, iam deficit, figuram date ruris fuit iaculum tuo _verum primus_. 173 | 174 | Tum mota Denique sanguis spumis **et**, tuli periura, dilacerant lactantia 175 | nigraque ambibat ortus. Tanto nato tenebat Arethusa parilesque concumbere mihi 176 | conceperat quam iuxta et. Hausta vesper? Ipse quam dum lenius cum certe iamque 177 | iam en paelex insilit Phrygiae cessant. Tori est montibus; et, sub et pro 178 | sorores. 179 | 180 | ```js 181 | function HelloWorld({ 182 | greeting = "hello", 183 | greeted = '"World"', 184 | silent = false, 185 | onMouseOver, 186 | }) { 187 | if (!greeting) { 188 | return null 189 | } 190 | 191 | // TODO: Don't use random in render 192 | let num = Math.floor(Math.random() * 1e7) 193 | .toString() 194 | .replace(/\.\d+/gi, "") 195 | 196 | return ( 197 |
202 | 203 | {greeting.slice(0, 1).toUpperCase() + 204 | greeting.slice(1).toLowerCase()} 205 | 206 | {greeting.endsWith(",") ? ( 207 | " " 208 | ) : ( 209 | 210 | ", " 211 | 212 | )} 213 | {greeted} 214 | {silent ? "." : "!"} 215 |
216 | ) 217 | } 218 | ``` 219 | 220 | ### Tenens tepente conversae patruo 221 | 222 | [Lorem markdownum](http://www.et-sumit.io/) crevit humum, mille esse [semper 223 | tamen religatus](http://boves.io/) tumere tonitrua indicat. Tamen cantat pariter 224 | ieiunia, et quae versum lapis altique, prensam dilectos collo. Narrare auro 225 | **credit**; hoc manus et ovantem crimen, serpens humanaeve! Qui hic templa 226 | mollit superest ibimus effugit Britannos bracchia continet. 227 | 228 | - Pectora gemitus adsuetos 229 | - Haec opposuit 230 | - Non labori aequem sanguine contigit concurrere ab 231 | 232 | ```js 1:37 233 | function HelloWorld({ 234 | greeting = "hello", 235 | greeted = '"World"', 236 | silent = false, 237 | onMouseOver, 238 | }) { 239 | if (!greeting) { 240 | return null 241 | } 242 | 243 | // TODO: Don't use random in render 244 | let num = Math.floor(Math.random() * 1e7) 245 | .toString() 246 | .replace(/\.\d+/gi, "") 247 | 248 | return ( 249 |
254 | 255 | {greeting.slice(0, 1).toUpperCase() + 256 | greeting.slice(1).toLowerCase()} 257 | 258 | {greeting.endsWith(",") ? ( 259 | " " 260 | ) : ( 261 | 262 | ", " 263 | 264 | )} 265 | {greeted} 266 | {silent ? "." : "!"} 267 |
268 | ) 269 | } 270 | ``` 271 | 272 | Male cum monstris vulnera _in impetus_ ingenium tempora tanti non sed amens 273 | lucem, ruricolae placuisse. Et eodem vellet, parens dextra, fortissime vidi 274 | coniunx [exaudi at](http://illud.org/lampetidepiceae) pectora ad hastile. 275 | 276 | Positamque alebat occiduo; nisi iuveni, sed ille illa. Tamen Ligurum, videre 277 | velle. Bellum _liquerat nec_ quoniam coiere monstratum **vulnera** abstulit 278 | 279 |
280 | 281 | Lorem ipsum dolor sit amet, fugit errem volumus ex sit, magna fugit deserunt et qui. Sapientem mnesarchum ei vis, offendit appetere inimicus eu has. Te utamur voluptua per. Per dicant intellegebat in. Laboramus referrentur id his, electram philosophia sit an. Possim efficiendi no sea, eu admodum copiosae indoctum mea. 282 | 283 | Sit eligendi dignissim et, sit eius ancillae voluptatibus te. Ea summo nostrum omnesque sed. Deserunt iracundia definiebas ei est. An vitae reprimique ius, facer timeam cu nam. 284 | 285 | Id quot impetus prodesset eum, et usu iuvaret alienum. Ut amet quaerendum pro, impetus appetere disputando te per. Stet congue ancillae mei in, nam fuisset antiopam id. Ad denique blandit accommodare ius. Solum legere ea sea, per cu affert timeam, meis expetendis intellegebat ex pro. 286 | 287 | Nec probo paulo facilisi cu, eu nibh persecuti mea. Ut aperiam deseruisse est, eos eu delicata repudiare aliquando. Mei te justo euismod accusam, eos posse saperet elaboraret ne, mucius quodsi vocibus sit in. Mea at utinam maiorum, mei eu tale etiam. 288 | -------------------------------------------------------------------------------- /demo/blog/theme-ui.js: -------------------------------------------------------------------------------- 1 | import deepmerge from "deepmerge" 2 | import blogTheme from "gatsby-theme-blog/src/gatsby-plugin-theme-ui/index" 3 | import wavesTheme from "gatsby-theme-waves/src/gatsby-plugin-theme-ui/index" 4 | // import { nightOwl } from "code-surfer/dist/standalone.esm" 5 | 6 | export default deepmerge.all([ 7 | blogTheme, 8 | wavesTheme, 9 | { 10 | breakpoints: ["1000px"], 11 | colors: { 12 | primary: "rebeccapurple", 13 | modes: { dark: { background: "#1e1e1e" } }, 14 | }, 15 | }, 16 | // nightOwl, 17 | ]) 18 | -------------------------------------------------------------------------------- /demo/decks/counter.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx } from "theme-ui" 3 | import React from "react" 4 | 5 | export default class Counter extends React.Component { 6 | state = { 7 | count: 0, 8 | } 9 | 10 | inc = () => { 11 | this.setState(state => ({ count: state.count + 1 })) 12 | } 13 | 14 | dec = () => { 15 | this.setState(state => ({ count: state.count - 1 })) 16 | } 17 | 18 | render() { 19 | return ( 20 |
26 | 50 |
{this.state.count}
51 | 75 |
76 | ) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /demo/decks/hi.mdx: -------------------------------------------------------------------------------- 1 | import { 2 | Head, 3 | Image, 4 | Notes, 5 | Appear, 6 | Invert, 7 | Split, 8 | SplitRight, 9 | FullScreenCode, 10 | Horizontal, 11 | } from "gatsby-theme-mdx-deck" 12 | import Counter from "./counter" 13 | import big from "./theme" 14 | 15 | export const theme = big 16 | 17 | 18 | mdx-deck 19 | 23 | 24 | 25 | 29 | 33 | 34 | 35 | # MDX Deck 36 | 37 | MDX-based presentation decks 38 | 39 | --- 40 | 41 | # Presentation decks 42 | 43 | --- 44 | 45 | # Built with [MDX][] 46 | 47 | [mdx]: https://github.com/mdx-js/mdx 48 | 49 | --- 50 | 51 | ### Import and Use React Components 52 | 53 | 54 | 55 | --- 56 | 57 | - Make bulleted lists 58 | - To help make your point 59 | 60 | --- 61 | 62 | ## Getting Started 63 | 64 | 1. `npm i -D mdx-deck` 65 | 2. Write some markdown and JSX 66 | 3. Present 67 | 68 | --- 69 | 70 | ```jsx 71 | 72 | ``` 73 | 74 | 75 | 76 | - These are speaker notes 77 | - And they won't be rendered in your slide 78 | 79 | 80 | 81 | --- 82 | 83 | > “Blockquotes are essential to any good presentation” 84 | 85 | – Anonymous 86 | 87 | 88 | 92 | 93 | 94 | --- 95 | 96 | ### Appear 97 | 98 | 106 | 107 | --- 108 | 109 | 113 | 114 | Testing object fit 115 | 116 | --- 117 | 118 | 119 | 120 | --- 121 | 122 | 123 | 124 | ![](https://images.unsplash.com/photo-1462331940025-496dfbfc7564?new_york&w=2048&q=20) 125 | 126 | ## Split Layout 127 | 128 | 129 | 130 | --- 131 | 132 | 133 | 134 | ![](https://images.unsplash.com/photo-1462331940025-496dfbfc7564?new_york&w=2048&q=20) 135 | 136 | ## Split Layout 137 | 138 | (To the right) 139 | 140 | 141 | 142 | --- 143 | 144 | 145 | 146 | ![](https://source.unsplash.com/random/1024x768') 147 | 148 | ![](https://source.unsplash.com/random/1024x768') 149 | 150 | ### Horizontal Layout 151 | 152 | 153 | 154 | --- 155 | 156 | ![](https://images.unsplash.com/photo-1462331940025-496dfbfc7564?new_york&w=2048&h=1024&q=20&fit=crop) 157 | 158 | Inline image 159 | 160 | --- 161 | 162 | # Get started :sunglasses: 163 | 164 | [GitHub](https://github.com/jxnblk/mdx-deck) 165 | -------------------------------------------------------------------------------- /demo/decks/theme.js: -------------------------------------------------------------------------------- 1 | const blue = "#0af" 2 | 3 | export default { 4 | googleFont: "https://fonts.googleapis.com/css?family=Bowlby+One+SC", 5 | fonts: { 6 | body: '"Bowlby One SC", sans-serif', 7 | }, 8 | colors: { 9 | text: "#dff", 10 | background: "#011", 11 | primary: blue, 12 | blue, 13 | black: "#000", 14 | }, 15 | fontWeights: { 16 | heading: 600, 17 | bold: 600, 18 | }, 19 | styles: { 20 | pre: { 21 | color: "primary", 22 | bg: "black", 23 | }, 24 | code: { 25 | color: "primary", 26 | }, 27 | }, 28 | } 29 | -------------------------------------------------------------------------------- /demo/gatsby-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | "gatsby-plugin-theme-ui", 4 | `gatsby-plugin-sharp`, 5 | "gatsby-theme-waves", 6 | { 7 | resolve: `gatsby-source-filesystem`, 8 | options: { 9 | path: `${__dirname}/src/pages`, 10 | }, 11 | }, 12 | { 13 | resolve: `gatsby-theme-blog`, 14 | options: { 15 | basePath: `/blog`, 16 | contentPath: `blog/posts`, 17 | assetsPath: `blog/assets`, 18 | mdx: false, 19 | }, 20 | }, 21 | { 22 | resolve: "gatsby-plugin-mdx", 23 | options: { 24 | gatsbyRemarkPlugins: [ 25 | { 26 | resolve: `gatsby-remark-images`, 27 | options: { 28 | maxWidth: 1200, 29 | }, 30 | }, 31 | ], 32 | rehypePlugins: [require("rehype-waves")], 33 | }, 34 | }, 35 | { 36 | resolve: "gatsby-theme-mdx-deck", 37 | options: { mdx: false, basePath: "decks" }, 38 | }, 39 | ], 40 | } 41 | -------------------------------------------------------------------------------- /demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "demo", 4 | "version": "0.1.0", 5 | "license": "MIT", 6 | "scripts": { 7 | "build": "gatsby build", 8 | "develop": "gatsby develop -H 0.0.0.0", 9 | "format": "prettier --write src/**/*.{js,jsx}", 10 | "start": "npm run develop", 11 | "serve": "gatsby serve", 12 | "clean": "gatsby clean", 13 | "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\"" 14 | }, 15 | "dependencies": { 16 | "@emotion/core": "^10.0.14", 17 | "@mdx-js/mdx": "^1.1.0", 18 | "@mdx-js/react": "^1.0.27", 19 | "@theme-ui/presets": "^0.2.15", 20 | "deepmerge": "^4.0.0", 21 | "gatsby": "^2.13.24", 22 | "gatsby-plugin-mdx": "^1.0.14", 23 | "gatsby-plugin-sharp": "^2.2.9", 24 | "gatsby-remark-images": "^3.1.7", 25 | "gatsby-theme-blog": "^1.0.2", 26 | "gatsby-theme-mdx-deck": "^3.0.7", 27 | "gatsby-theme-waves": "*", 28 | "pigeon-maps": "^0.13.0", 29 | "react": "^16.8.6", 30 | "react-dom": "^16.8.6", 31 | "recharts": "^1.6.2", 32 | "rehype-waves": "*" 33 | }, 34 | "devDependencies": { 35 | "prettier": "^1.18.2" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /demo/src/components/charts/chart-wave.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx, useThemeUI } from "theme-ui" 3 | import React from "react" 4 | import BarScroller from "gatsby-theme-waves/src/components/bar-scroller" 5 | import Wave from "gatsby-theme-waves/src/components/wave" 6 | import { ResponsiveContainer, BarChart, XAxis, YAxis, Bar } from "recharts" 7 | 8 | function toColumns(items, columnCount) { 9 | const columns = Array(columnCount) 10 | .fill() 11 | .map(() => []) 12 | 13 | items.forEach((item, i) => { 14 | const isCode = item.props && item.props.mdxType === "pre" 15 | if (isCode) { 16 | const json = JSON.parse(item.props.children.props.children) 17 | columns[0].push(json) 18 | columns[1].push(React.createElement("div", {}, [])) 19 | } else { 20 | const step = columns[0].length - 1 21 | columns[1][step].props.children.push(item) 22 | } 23 | }) 24 | 25 | return columns 26 | } 27 | 28 | function ChartWave(props) { 29 | const childrenToColumns = children => { 30 | const items = React.Children.map(children, child => [child]) 31 | const columnCount = 2 32 | const columns = toColumns(items, columnCount) 33 | return columns 34 | } 35 | 36 | return ( 37 | 43 | ) 44 | } 45 | 46 | function ChartSticker({ variant, steps, currentStep, progress }) { 47 | const { theme } = useThemeUI() 48 | return ( 49 |
50 |
51 | 52 | 56 | 57 | 58 | 59 | 60 | 61 |
62 |
63 | ) 64 | } 65 | 66 | export default ChartWave 67 | -------------------------------------------------------------------------------- /demo/src/components/charts/layout.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { ThemeProvider, Container, Styled, jsx } from "theme-ui" 3 | import { roboto } from "@theme-ui/presets" 4 | import { Global } from "@emotion/core" 5 | 6 | import Header from "../header" 7 | import image from "../../pages/media/chart.png" 8 | 9 | import sidebarVariant from "./waves-variant" 10 | import deepmerge from "deepmerge" 11 | 12 | const theme = deepmerge(roboto, { 13 | colors: { 14 | negativeBackground: "#121320", 15 | negativeText: "#fafafa", 16 | }, 17 | styles: { 18 | Container: { 19 | width: ["100%", "500px"], 20 | marginRight: [0, "40px"], 21 | }, 22 | }, 23 | root: { 24 | display: "flex", 25 | }, 26 | }) 27 | 28 | theme.styles.waves = { 29 | ...sidebarVariant, 30 | } 31 | 32 | theme.breakpoints = ["1120px"] 33 | 34 | export default props => ( 35 | 36 | 37 | 38 |
43 |
44 |
45 | {props.children} 46 |
47 | 50 |
51 | 52 | 53 | ) 54 | -------------------------------------------------------------------------------- /demo/src/components/charts/waves-variant.js: -------------------------------------------------------------------------------- 1 | export default { 2 | sidebar: { 3 | Wave: { 4 | width: ["100%", "960px"], 5 | marginTop: "40px", 6 | marginLeft: 0, 7 | marginBottom: "40px", 8 | position: "relative", 9 | display: ["block", "flex"], 10 | flexDirection: ["", "row-reverse"], 11 | }, 12 | ScrollerContainer: { 13 | flex: [1, "500px"], 14 | paddingLeft: 0, 15 | marginRight: [0, "40px"], 16 | paddingTop: ["50px", 0], 17 | }, 18 | ScrollerStep: { 19 | position: "relative", 20 | padding: 0, 21 | minHeight: "250px", 22 | display: "flex", 23 | alignItems: "center", 24 | borderLeft: "none", 25 | width: ["auto", "388px"], 26 | }, 27 | ScrollerProgress: { 28 | position: "absolute", 29 | left: "-12px", 30 | backgroundColor: "secondary", 31 | }, 32 | StickerContainer: { 33 | width: ["100vw", "40%"], 34 | marginLeft: ["calc(50% - 50vw)", "40px"], 35 | position: ["sticky", "static"], 36 | top: [0, "auto"], 37 | zIndex: [1, "auto"], 38 | height: ["50vh", "auto"], 39 | backgroundColor: "negativeBackground", 40 | color: "negativeText", 41 | }, 42 | Sticker: { 43 | position: ["static", "sticky"], 44 | width: "100%", 45 | height: ["100%", "40vh"], 46 | top: ["auto", "30vh"], 47 | border: ["none", "none"], 48 | }, 49 | focus: [0.7, 0.5], 50 | }, 51 | } 52 | -------------------------------------------------------------------------------- /demo/src/components/deck/deck-wave.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx } from "theme-ui" 3 | import React from "react" 4 | import BarScroller from "gatsby-theme-waves/src/components/bar-scroller" 5 | import Wave from "gatsby-theme-waves/src/components/wave" 6 | import { useStaticQuery, graphql } from "gatsby" 7 | import { MDXRenderer } from "gatsby-plugin-mdx" 8 | import { Embed } from "./embed" 9 | 10 | function toColumns(items, columnCount) { 11 | const columns = Array(columnCount) 12 | .fill() 13 | .map(() => []) 14 | 15 | columns[0].push(null) 16 | columns[1].push(React.createElement("div", {}, [])) 17 | items.forEach((item, i) => { 18 | const isHr = item.props.mdxType === "hr" 19 | if (isHr) { 20 | columns[0].push(null) 21 | columns[1].push(React.createElement("div", {}, [])) 22 | } else { 23 | const step = columns[0].length - 1 24 | columns[1][step].props.children.push(item) 25 | } 26 | }) 27 | 28 | return columns 29 | } 30 | 31 | function DeckWave(props) { 32 | const childrenToColumns = children => { 33 | const items = React.Children.map(children, child => [child]) 34 | const columnCount = 2 35 | const columns = toColumns(items, columnCount) 36 | return columns 37 | } 38 | 39 | const { allDeck } = useStaticQuery(graphql` 40 | query Hey { 41 | allDeck { 42 | nodes { 43 | slug 44 | body 45 | } 46 | } 47 | } 48 | `) 49 | const deck = allDeck.nodes.find(deck => deck.slug === props.deck) 50 | 51 | return ( 52 | 58 | ) 59 | } 60 | 61 | function DeckSticker({ deck, progress, currentStep, variant }) { 62 | const prevIndex = Math.floor(progress) 63 | const nextIndex = prevIndex + 1 64 | 65 | return ( 66 |
67 |
68 |
71 | 78 | 85 |
86 |
87 |
88 | ) 89 | } 90 | 91 | export default DeckWave 92 | -------------------------------------------------------------------------------- /demo/src/components/deck/embed.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx, ThemeProvider } from "theme-ui" 3 | import splitSlides from "gatsby-theme-mdx-deck/src/split-slides" 4 | import Slide from "gatsby-theme-mdx-deck/src/components/slide" 5 | import Zoom from "gatsby-theme-mdx-deck/src/components/zoom" 6 | 7 | const wrapper = ({ slide: i, ratio, zoom, theme, ...props }) => { 8 | const slides = splitSlides(props) 9 | const slide = slides[i - 1] 10 | 11 | if (!slide) { 12 | return
No slide found (slide {i})
13 | } 14 | 15 | return ( 16 | 17 | 18 | 19 | 20 | 21 | ) 22 | } 23 | 24 | const components = { 25 | wrapper, 26 | } 27 | 28 | export const Embed = ({ 29 | src: Deck, 30 | slide = 1, 31 | ratio = 16 / 9, 32 | zoom = 1, 33 | ...props 34 | }) => ( 35 | 42 | ) 43 | 44 | export default Embed 45 | -------------------------------------------------------------------------------- /demo/src/components/deck/layout.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { roboto } from "@theme-ui/presets" 3 | import Header from "../header" 4 | import deepmerge from "deepmerge" 5 | import { ThemeProvider, Styled, Container } from "theme-ui" 6 | import variants from "./waves-variant" 7 | import { Global } from "@emotion/core" 8 | import image from "../../pages/media/deck.png" 9 | 10 | const theme = deepmerge(roboto, { 11 | styles: { 12 | Container: { 13 | width: ["100%", "700px"], 14 | }, 15 | waves: variants, 16 | }, 17 | }) 18 | 19 | theme.breakpoints = ["900px"] 20 | 21 | export default props => ( 22 | 23 | 24 | 25 |
30 | {props.children} 31 | 32 | 33 | ) 34 | -------------------------------------------------------------------------------- /demo/src/components/deck/waves-variant.js: -------------------------------------------------------------------------------- 1 | export default { 2 | default: { 3 | Wave: { 4 | width: ["100%", "960px"], 5 | marginTop: "40px", 6 | marginLeft: [0, "calc(50% - 480px)"], 7 | marginBottom: "40px", 8 | position: "relative", 9 | display: ["block", "flex"], 10 | }, 11 | ScrollerContainer: { 12 | flex: [1, "430px"], 13 | paddingLeft: [0, "50px"], 14 | paddingTop: ["50px", 0], 15 | }, 16 | ScrollerStep: { 17 | position: "relative", 18 | padding: [0, "0 10px"], 19 | minHeight: "250px", 20 | display: "flex", 21 | alignItems: "center", 22 | borderLeft: ["none", "3px solid transparent"], 23 | }, 24 | ScrollerProgress: { 25 | position: "absolute", 26 | left: ["-12px", "-3px"], 27 | backgroundColor: "primary", 28 | }, 29 | StickerContainer: { 30 | width: ["100vw", "480px"], 31 | marginLeft: ["calc(50% - 50vw)", 0], 32 | position: ["sticky", "static"], 33 | top: [0, "auto"], 34 | zIndex: [1, "auto"], 35 | height: ["calc(100vw * 9 / 16)", "auto"], 36 | fontSize: ["0.8em", "0.8em"], 37 | }, 38 | Sticker: { 39 | position: ["static", "sticky"], 40 | width: ["100%", "480px"], 41 | height: ["100%", "calc(480px * 9 / 16)"], 42 | top: ["auto", "calc(50vh - 480px * 9 / 32)"], 43 | border: ["none", "1px solid"], 44 | borderColor: "secondary", 45 | overflow: "hidden", 46 | boxShadow: "0 20px 50px 0 rgba(0,0,0,0.3)", 47 | }, 48 | // this is used to select the active scroller step 49 | // 0.5 selects the step that is at half the screen height 50 | // 0.7 the step that is at 70% the screen height 51 | focus: [0.7, 0.5], 52 | }, 53 | } 54 | -------------------------------------------------------------------------------- /demo/src/components/header.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx, Styled } from "theme-ui" 3 | 4 | import { Link } from "gatsby" 5 | import { Helmet } from "react-helmet" 6 | 7 | export default ({ codeUrl, title, image }) => ( 8 | 16 | 17 | Gatsby Theme Waves: {title} 18 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | All Demos 31 | 32 | 33 | View Code 34 | 35 | 36 | ) 37 | -------------------------------------------------------------------------------- /demo/src/components/images/layout.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx, ThemeProvider, Container, Styled } from "theme-ui" 3 | 4 | import wavesRoot from "gatsby-theme-waves/src/gatsby-plugin-theme-ui" 5 | import images from "./waves-variant" 6 | 7 | import Header from "../header" 8 | import image from "../../pages/media/image.png" 9 | 10 | const theme = { 11 | colors: { 12 | text: "#fafafaee", 13 | primary: "salmon", 14 | }, 15 | styles: { 16 | waves: { 17 | ...wavesRoot.styles.waves, 18 | ...images, 19 | }, 20 | Container: { 21 | width: ["100%", 520], 22 | fontSize: ["1em", "1.2em"], 23 | marginLeft: ["auto", "10%"], 24 | color: "text", 25 | fontFamily: `-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif`, 26 | }, 27 | a: { 28 | color: "primary", 29 | }, 30 | }, 31 | } 32 | 33 | export default props => ( 34 | 35 | 36 |
41 | {props.children} 42 | 43 | 44 | ) 45 | -------------------------------------------------------------------------------- /demo/src/components/images/waves-variant.js: -------------------------------------------------------------------------------- 1 | export default { 2 | fullscreen: { 3 | Wave: { 4 | width: "100%", 5 | marginTop: 0, 6 | marginLeft: 0, 7 | marginBottom: 0, 8 | position: "static", 9 | display: "block", 10 | }, 11 | ScrollerContainer: { 12 | flex: 1, 13 | paddingLeft: 0, 14 | margin: "30vh 0", 15 | }, 16 | ScrollerStep: { 17 | position: "relative", 18 | padding: "0 10px", 19 | minHeight: "250px", 20 | display: "flex", 21 | alignItems: "center", 22 | borderLeft: "3px solid transparent", 23 | }, 24 | StickerContainer: { 25 | width: "100vw", 26 | height: "100vh", 27 | position: "fixed", 28 | top: 0, 29 | left: 0, 30 | backgroundColor: "rgba(1, 1, 1, 0.6)", 31 | zIndex: -1, 32 | }, 33 | Sticker: { 34 | width: "100vw", 35 | height: "100vh", 36 | position: "fixed", 37 | top: 0, 38 | left: 0, 39 | zIndex: -2, 40 | }, 41 | }, 42 | } 43 | -------------------------------------------------------------------------------- /demo/src/components/maps/layout.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { ThemeProvider, Styled } from "theme-ui" 3 | import { roboto } from "@theme-ui/presets" 4 | import { Global } from "@emotion/core" 5 | 6 | import Header from "../header" 7 | import image from "../../pages/media/maps.png" 8 | 9 | import sidebarVariant from "./waves-variant" 10 | import deepmerge from "deepmerge" 11 | 12 | const theme = deepmerge(roboto, { 13 | colors: { 14 | background: "#121320", 15 | text: "#fafafa", 16 | primary: "salmon", 17 | }, 18 | styles: { 19 | Container: { 20 | width: ["100%", "500px"], 21 | marginRight: [0, "40px"], 22 | }, 23 | root: { 24 | // display: "flex", 25 | // background: "#121320", 26 | color: "#fafafa", 27 | }, 28 | }, 29 | }) 30 | 31 | theme.styles.waves = { 32 | ...sidebarVariant, 33 | } 34 | 35 | theme.breakpoints = ["900px"] 36 | 37 | export default props => ( 38 | 39 | 40 | 41 |
46 | {props.children} 47 | 48 | 49 | ) 50 | -------------------------------------------------------------------------------- /demo/src/components/maps/maps-wave.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx } from "theme-ui" 3 | import React from "react" 4 | import BarScroller from "gatsby-theme-waves/src/components/bar-scroller" 5 | import Wave from "gatsby-theme-waves/src/components/wave" 6 | import Map from "pigeon-maps" 7 | 8 | function toColumns(items, columnCount) { 9 | const columns = Array(columnCount) 10 | .fill() 11 | .map(() => []) 12 | 13 | items.forEach((item, i) => { 14 | const isCode = item.props && item.props.mdxType === "pre" 15 | if (isCode) { 16 | const json = JSON.parse(item.props.children.props.children) 17 | columns[0].push(json) 18 | columns[1].push(React.createElement("div", {}, [])) 19 | } else { 20 | const step = columns[0].length - 1 21 | columns[1][step].props.children.push(item) 22 | } 23 | }) 24 | 25 | return columns 26 | } 27 | 28 | function MapsWave(props) { 29 | const childrenToColumns = children => { 30 | const items = React.Children.map(children, child => [child]) 31 | const columnCount = 2 32 | const columns = toColumns(items, columnCount) 33 | return columns 34 | } 35 | 36 | return ( 37 | 43 | ) 44 | } 45 | 46 | function MapsSticker({ variant, steps, currentStep, progress }) { 47 | return ( 48 |
53 |
54 | 55 |
56 |
57 | ) 58 | } 59 | 60 | export default MapsWave 61 | -------------------------------------------------------------------------------- /demo/src/components/maps/waves-variant.js: -------------------------------------------------------------------------------- 1 | export default { 2 | sidebar: { 3 | Wave: { 4 | width: "100%", 5 | marginTop: "40px", 6 | marginLeft: 0, 7 | marginBottom: "40px", 8 | position: "relative", 9 | display: ["block", "flex"], 10 | }, 11 | ScrollerContainer: { 12 | flex: [1, "50vw"], 13 | paddingLeft: [0, "51vw"], 14 | marginRight: [0, "40px"], 15 | paddingTop: ["50px", 0], 16 | }, 17 | ScrollerStep: { 18 | position: "relative", 19 | padding: 0, 20 | minHeight: "250px", 21 | display: "flex", 22 | alignItems: "center", 23 | borderLeft: "none", 24 | width: ["auto", "388px"], 25 | }, 26 | ScrollerProgress: { 27 | position: "absolute", 28 | left: "-12px", 29 | // backgroundColor: "primary", 30 | }, 31 | StickerContainer: { 32 | width: ["100vw", "50vw"], 33 | marginLeft: ["calc(50% - 50vw)", 0], 34 | position: ["sticky", "fixed"], 35 | top: 0, 36 | left: ["auto", 0], 37 | zIndex: [1, -1], 38 | height: ["50vh", "auto"], 39 | }, 40 | Sticker: { 41 | position: ["static", "sticky"], 42 | width: "100%", 43 | height: ["100%", "100vh"], 44 | top: ["auto", 0], 45 | border: ["none", "none"], 46 | }, 47 | focus: [0.7, 0.5], 48 | }, 49 | } 50 | -------------------------------------------------------------------------------- /demo/src/gatsby-theme-blog/components/layout.js: -------------------------------------------------------------------------------- 1 | import Layout from "gatsby-theme-blog/src/components/layout" 2 | import React from "react" 3 | import theme from "../../../blog/theme-ui" 4 | import { ThemeProvider, ColorMode } from "theme-ui" 5 | 6 | import Header from "../../components/header" 7 | import image from "../../pages/media/code.png" 8 | 9 | export default props => ( 10 | 11 | 12 |
17 | 18 | 19 | ) 20 | -------------------------------------------------------------------------------- /demo/src/gatsby-theme-mdx-deck/templates/deck.js: -------------------------------------------------------------------------------- 1 | export default () => { 2 | // shadowing because something is wrong with ssr 3 | // I think it has a wrong mdx context, but it's hard to debug 4 | return "" 5 | } 6 | -------------------------------------------------------------------------------- /demo/src/pages/charts/index.mdx: -------------------------------------------------------------------------------- 1 | import ChartWave from "../../components/charts/chart-wave" 2 | import PageLayout from "../../components/charts/layout" 3 | export default PageLayout 4 | 5 | # Ulla Libye inductum 6 | 7 | ## Res arsit alta elusaque dixit 8 | 9 | Lorem markdownum seniles. Rediere iam quid laudat turba medias vires vocatur 10 | pavet aptius, pondere patris, circuitu! Vias sumpsisse. 11 | 12 | - Certamine at sidereum inmissusque magis tyranni ulla 13 | - Poterat solitumque sunt 14 | - Superbum genibusque mediis 15 | - Pocula infans et in satis 16 | 17 | Vox calidumque exceptas etiamnum oculosque tendit [fratris relinquam 18 | sinuatoque](http://coepisseedidit.net/spectabere) pedibus; non. Perdidit iniquis 19 | belua animoque carcere, per saltu non, mota rore. Venit _iubet tenuissimus_, 20 | ille posuisti iuppiter, iam quam tradere. Sibyllae trepidare aequore terrae. 21 | Posceret autumnos _licet surrexit_ in late, fluxit, iaculo prius; volenti 22 | venenum adulterium haec cervice ab duro erat. 23 | 24 | 25 | 26 | ```json 27 | [ 28 | { "x": "A", "y": 2400 }, 29 | { "x": "B", "y": 1398 }, 30 | { "x": "C", "y": 9800 }, 31 | { "x": "D", "y": 3908 }, 32 | { "x": "E", "y": 4800 } 33 | ] 34 | ``` 35 | 36 | ## Res arsit alta elusaque dixit 37 | 38 | Lorem markdownum seniles. Rediere iam quid laudat turba medias vires vocatur 39 | pavet aptius, pondere patris, circuitu! Vias sumpsisse. 40 | 41 | - Certamine at sidereum inmissusque magis tyranni ulla 42 | - Poterat solitumque sunt 43 | - Superbum genibusque mediis 44 | - Pocula infans et in satis 45 | 46 | Vox calidumque exceptas etiamnum oculosque tendit [fratris relinquam 47 | sinuatoque](http://coepisseedidit.net/spectabere) pedibus; non. Perdidit iniquis 48 | belua animoque carcere, per saltu non, mota rore. Venit _iubet tenuissimus_, 49 | ille posuisti iuppiter, iam quam tradere. Sibyllae trepidare aequore terrae. 50 | Posceret autumnos _licet surrexit_ in late, fluxit, iaculo prius; volenti 51 | venenum adulterium haec cervice ab duro erat. 52 | 53 | ```json 54 | [ 55 | { "x": "A", "y": 6000 }, 56 | { "x": "B", "y": 1398 }, 57 | { "x": "C", "y": 9800 }, 58 | { "x": "D", "y": 8908 }, 59 | { "x": "E", "y": 4800 } 60 | ] 61 | ``` 62 | 63 | ## Non laborum cum 64 | 65 | Exitium porrexit referam ceratis, _dantem si super_, iuncta ad, de consueta 66 | **mille dabis**. Audaci illis prohibent visa. 67 | 68 | 1. Esset feros tantum suos dedantur 69 | 2. Nec posco sensit dira 70 | 3. Per medii ubi Threicius Circen 71 | 72 | In sine nata semper nova Tegeaea, sed fassurae agam cum lapillos et iacens 73 | memori domosque fere, nato. Statione potiar modo totiens novae obstipui in heros 74 | quodcumque quoque gemellos Rhodopeius temone, non. Lotos audire sordida obliquo; 75 | ira accipit in Aurora, Helles postquam. Infregit secundo coniuge iussa cur tamen 76 | pro fretum quid saepibus, tibi. 77 | 78 | ```json 79 | [ 80 | { "x": "A", "y": 6000 }, 81 | { "x": "B", "y": 1398 }, 82 | { "x": "C", "y": 9800 }, 83 | { "x": "D", "y": 5908 }, 84 | { "x": "E", "y": 9800 } 85 | ] 86 | ``` 87 | 88 | ## Tela centauri nobis perhorruit pugnat facundis claudit 89 | 90 | Revellit latebras tamen vivo **vellera herbas**. Ulixem huius acerbo 91 | recondiderat verba acceptaque ater mansit tandem, ex? Fortuna caeca collectum 92 | crudelis rogant increpuit, primum Ecce, fessamque 93 | [illis](http://ad-tu.org/quid.html) quae **fama** modo longius dei [fugiunt 94 | vindice](http://qua-ingrate.io/telum.php). 95 | 96 | Tertius passus ossibus inter, pervenerat armis ruricolae in sibi suffusus, 97 | **se** quod nec quod: dumosaque iungat color. Dextra dictis aures mirum, 98 | rescindere petit, cavo molli pia suarum, tum cum gradu. 99 | 100 | Est fuga colore translata liquida pervenit Laomedonque prius volventem alarum 101 | infelix corpus canum valeant. Colle [prensoque](http://pater-nec.net/) cecidit 102 | oscula. Artus senioribus manum quod, tamen caput circumdata nata fictos; ora 103 | arguit durisque excutior. 104 | 105 | Sit eligendi dignissim et, sit eius ancillae voluptatibus te. Ea summo nostrum omnesque sed. Deserunt iracundia definiebas ei est. 106 | 107 | ```json 108 | [ 109 | { "x": "A", "y": 6000 }, 110 | { "x": "B", "y": 7398 }, 111 | { "x": "C", "y": 7100 }, 112 | { "x": "D", "y": 5908 }, 113 | { "x": "E", "y": 9800 } 114 | ] 115 | ``` 116 | 117 | ## Caput haec iam extulerat transire unda vultus 118 | 119 | **Lorem markdownum** quantus laeta [et vincere](http://et-corpus.com/serpit) 120 | castique tenuit; in erras: iacebas gramen, totiens Danaam: ad. _Rescindere_ 121 | ripas, vestem, qua otia est, ferox avidamque, purgamina. 122 | 123 | Achilles priori Aethiopasque plura duabus Phorcidas, ventis _conlapsaque quod_. 124 | Tanto pectore rebus: atria quae semina corpus; igne recens ferrum violesque 125 | quibus fugiuntque aequos, raptatur malignas tuas. Et maledicere placitas 126 | _Phinea_ lacrimis ad petit ardescunt dumque excipiunt longis iuvenis tendentem 127 | malo. Danaam mane, remissis vis nova **sinit** parte, truces et sonat noctis! 128 | 129 | ```json 130 | [ 131 | { "x": "A", "y": 8000 }, 132 | { "x": "B", "y": 8398 }, 133 | { "x": "C", "y": 9100 }, 134 | { "x": "D", "y": 8908 }, 135 | { "x": "E", "y": 9800 } 136 | ] 137 | ``` 138 | 139 | ## Diem vero 140 | 141 | Urbem fecere figat: cum referentia amissam ruit, obice meminisse voces coniunx: 142 | [famuli dixi non](http://stringit.net/mersis-pluribus) tumescunt mane. 143 | [Contraque](http://ecce.org/) dextram ereptus, pedis resolvit sceleratus, quem 144 | ex, inpensius et. Ad adspiceres spemque ibi tamen. 145 | 146 | 1. Dona verba solitum gravitas carmina in ecce 147 | 2. Sustulit erat retia 148 | 3. Haec humi 149 | 4. Erant sensi quae addidit istis minor lavere 150 | 5. Et quoque serpit labant 151 | 152 | Cornibus ossa aere frustraque conanti, et sua dedisses poma domus illa! Natos 153 | caelo mittere, amari, quasque Callida, sub caesis fugacis, vicinia insidias Aiax 154 | venio contigit percussa. Sunt tibi semina, dolor Phaethon: videre, _antiquam_, 155 | qui respicit ferocia laterique amnes, Phoebique quod. Quem lacertis portabat. 156 | 157 | [Sub iam](http://sicula-intonsumque.net/brevis-caelumque.php) sed ictus tellure 158 | ora _artus nix_ quondam sublimis auras gruem. Orat suam fati generi, quoque aut 159 | pallada pisces raucaque populus leaeque palmis, luctor vigilantibus quae 160 | Cyllene? 161 | 162 | 163 | 164 | ## Quique terrasque meas remota gestasset restabat secures 165 | 166 | Cycnum parat veteris pharetram secum fixo convulso verti spolioque velaturque 167 | inter. Lacertis Hyantea et hirta retexit mea genis Arethusa _si causa_ 168 | proceresque agris est flosque gnatis Lemnos? Illa pinguesque tanta sagittifera 169 | amare propositumque auras est funesti fecundior volebat luporum plumas. Agitatis 170 | moles aratro. 171 | 172 | [Ianua de](http://patefecit.com/) o agendum tale croceo, corpus, tabellae 173 | elicuere. Nec at quod Iove corpora, in arvis adplicat trepidans si signo 174 | rostrum. Iram _qualia_ Lucina longis tamen nosse **ambiguus**, imitata in 175 | Cyllare et. 176 | 177 | > Ramis alimenta. Non **simul** repulsa lenti isto, indeploratum ostentis, e 178 | > Antissa dant! [Ore](http://www.sibi.io/essem) positi, bracchia devoveas, 179 | > famulis faciem Lapitharum dedere viximus. 180 | 181 | ## Est Aphareus 182 | 183 | Optat stetit septem Euros nostros iacent corruat usus, Seriphi? Cura nunc est 184 | ictu dea nil exstinctus sagittas cum, aut mansit sacros fama! Madefactam cernit: 185 | turba imis ille vellent, inquirant quosque simulaverat summo arcum corpus! 186 | 187 | > Diu Terram tendebat funduntur te inminet ultimus: puppim motisque addiderim 188 | > duas non. Ea ille iuvenis; ope meliora quisquam Xanthos, septem. Forma Clymene 189 | > qui _mare volucrem extinctum_ glaebaque. A Zancle tetigere frequentes: membra 190 | > vera natam tantum, quo! Gurgite ponti voce morsu, profuso accipit Achillis et 191 | > et nurumque! 192 | 193 | Antaeo in admissum saepe, tu [peti repetit 194 | inania](http://www.mihi-albet.org/aequalis.html) capacem. Patrii intrat: et 195 | latus, mihi recingunt recessu iubet ab. 196 | 197 | ## Res arsit alta elusaque dixit 198 | 199 | Lorem markdownum seniles. Rediere iam quid laudat turba medias vires vocatur 200 | pavet aptius, pondere patris, circuitu! Vias sumpsisse. 201 | 202 | - Certamine at sidereum inmissusque magis tyranni ulla 203 | - Poterat solitumque sunt 204 | - Superbum genibusque mediis 205 | - Pocula infans et in satis 206 | 207 | Vox calidumque exceptas etiamnum oculosque tendit [fratris relinquam 208 | sinuatoque](http://coepisseedidit.net/spectabere) pedibus; non. Perdidit iniquis 209 | belua animoque carcere, per saltu non, mota rore. Venit _iubet tenuissimus_, 210 | ille posuisti iuppiter, iam quam tradere. Sibyllae trepidare aequore terrae. 211 | Posceret autumnos _licet surrexit_ in late, fluxit, iaculo prius; volenti 212 | venenum adulterium haec cervice ab duro erat. 213 | -------------------------------------------------------------------------------- /demo/src/pages/deck/index.mdx: -------------------------------------------------------------------------------- 1 | import DeckWave from "../../components/deck/deck-wave" 2 | import PageLayout from "../../components/deck/layout" 3 | export default PageLayout 4 | 5 | # Huc loquendo omnia 6 | 7 | ## Fortes sum terras et postquam adurat ait 8 | 9 | Lorem markdownum [convicti](http://www.orbe.org/condit). Remissos maturus 10 | penetrat praesuta Simois litora Hippasus pollicitique unda; qui animalia inde, 11 | me? Urbesque primo. 12 | 13 | - Est esse corpus 14 | - Est incepti est et dissimulant mare devorat 15 | - Serae limen confundimur pueri ferinis 16 | - Dixit postquam 17 | - Os mollia quod ambiguus 18 | 19 | ## Et erat quo discordemque Lyrcea imis ingens 20 | 21 | Lorem markdownum fortes operique et certe, quam porrigit, erat, tactusque. Ipsi 22 | cum et viscera debere et Gallicus **nescis non nec** mora, sui vada etiamnum 23 | Lelex. Succincta odisse: nymphae glaeba. Est quae deae; [dixit 24 | fila](http://per.org/) priora est fortius medio: artus. Et virgo erit, tenaci 25 | causa an sub fata sopita? 26 | 27 | 28 | 29 | ## Celare et obruta terrore horrida 30 | 31 | Ordine ait aequoris sacra fieretque, nondum feci. Temerarius dolor abiit 32 | adgreditur Hecabe anno: it frondis arva ante aliqua longum tu erat genus. 33 | 34 | Tectaque Atalanta cohaeserat arte, mittitur formae micantes dixit metiris, 35 | siqua, quis tamen caeli tremuisse nec. Armento magno et cum sua saxi sanguineae 36 | virtus procul arcus percussit _egit_ socerque bimarem quaerit potestis, conplet. 37 | 38 | --- 39 | 40 | ## Poenaeque Delos 41 | 42 | Lorem markdownum eadem que flammas cerae est. Robore inpellit legebant arbor, 43 | fit ad reddidit scitabere cum antiquas [auribus](http://www.atin.io/sint)! 44 | Rebellant ait exitus tulit. 45 | 46 | - Certamine at sidereum inmissusque magis tyranni ulla 47 | - Poterat solitumque sunt 48 | - Superbum genibusque mediis 49 | - Pocula infans et in satis 50 | 51 | --- 52 | 53 | Vox calidumque exceptas etiamnum oculosque tendit [fratris relinquam 54 | sinuatoque](http://coepisseedidit.net/spectabere) pedibus; non. Perdidit iniquis 55 | belua animoque carcere, per saltu non, mota rore. Venit _iubet tenuissimus_, 56 | ille posuisti iuppiter, iam quam tradere. Sibyllae trepidare aequore terrae. 57 | Posceret autumnos _licet surrexit_ in late, fluxit, iaculo prius; volenti 58 | venenum adulterium haec cervice ab duro erat. 59 | 60 | --- 61 | 62 | Mors incingitur, ad parva. Huius mater: in _est_ stringebat et libens, serpentem 63 | mortisque et Sospite. Cervix ver tangi: est Sedit cum pervenit resque vulgatos 64 | hinc aeternus: in solebat, ore augere. 65 | 66 | --- 67 | 68 | ## Frenis telluris genitor venerat lacrimarum equos 69 | 70 | Et ad operique Athamas terret ducis quo videres suis sine commissas Tmolus 71 | suique colit dominumque et quod? Nulla cura muneris siquem potest inposuitque 72 | deceat somnoque aderat, aranea in habebant medio illum, est quoque aut. Eadem 73 | dixerat per impetus _ire haerens nunc_ Persidaque pressit videoque _manu_. 74 | 75 | --- 76 | 77 | Certamine _mente haliaeetus_ ministret qua; pennae somnus, utere deum caede: 78 | quid muros. Quique forti; Peleu huic nullis. Partim manu, concutit umbrarum 79 | quibusque arma huic sicut saxa: supra Volturnus. Et forte repugnat laetis nisi; 80 | dextra sparsit solitum corpore, sic spumosis de oraque. Sententia capioque et 81 | cura supremo mille spem, _in_ nostrae radiis, promissaque hos labore non, citis 82 | pavido ore. 83 | 84 | --- 85 | 86 | ## Metuenda festinus fortis imaginis iugo desideret vulnere 87 | 88 | Lorem **markdownum** umbrosaque vomere montibus peto, quod magnis causa 89 | adiciunt, nec stabat undam. Deum nulli lunae viris [Baucis](http://www.et.org/) 90 | esto visa victrix linguae holus nec est, ad amor ferens. Secuit fieri 91 | Phaethontis latent. Audito rupit, ingens rerum. Quid ad cupido curvamine, est 92 | post nullum: aura. 93 | 94 | 1. Undis sumus vulnere 95 | 2. Manibus et negetur mulcere 96 | 3. Fine tardis corpus 97 | 4. Exit genu non a 98 | 5. Tenentem atque precibusque nova noluit relabens 99 | 6. Retia filia 100 | 101 | --- 102 | 103 | ## Dum quidem 104 | 105 | Delubra _datus aut_, insistere Helicen damno rotato: Thaumantias et licebit 106 | inarsit _matre_ intrepidum. Ante potiora aut parte, ceu nisi suos nisi telaque 107 | ac fontes. Colloquium abdita voce: cursu ero volui fremit. 108 | 109 | > Cessant ne caeli subiere pectore fieret Nyseides error clausus adspicit, suos 110 | > cum; nec Cadmus in parte cuius. Dixit mortale? Premens pectore non Phocus 111 | > videri mater. Et inquit valle, et fulmen, imperiumque passo invidit arma 112 | > quibus! 113 | 114 | --- 115 | 116 | ## Tandem et hasta Eurylochumque errat pervigilem est 117 | 118 | Pylio Atlas in haut inmensum consulit triticeas recusat [saepe aper 119 | tua](http://atque-animam.io/sub) secura vidisse gravemque meumque. Quem admovet 120 | iamque. 121 | 122 | Et erigite [deo simul](http://persidaque.net/illas) fateri nova malum pavido 123 | velum tamen quo ipse cum felicia. Ite Argo manum rure: cavata vagantem 124 | pressistis animoque Phoeboque timuit fraternis. Esse tacito caelo mirantia 125 | **pulsisque haerent**, radices trans multorum? 126 | 127 | --- 128 | 129 | Lorem markdownum redimicula superi ponti nullius fugacia fuit cur caeloque 130 | cepisse venatrixque exitus. Aquatica et vir arboris: exit quos ore requiem 131 | iuverat sub **talia nigris**, laevaque. 132 | 133 | 1. Exclamo poterat et frigus ferro 134 | 2. Quid pondere 135 | 3. Coepi erat potui propior desine credite naribus 136 | 137 | --- 138 | 139 | ## Est quos admissumque omnes 140 | 141 | Omnes evincitque fallere ac certe, haut persequar [trabeati 142 | verbis](http://divum.org/ingemuitquenoviens) contendere Phoebeis ille tamen? 143 | Casas campus sors procul, vox licet manu o auras atque manus essent pellite 144 | genetrix? Quodsi non vivere, et ei quaerensque arboribus huic cladis moriens 145 | refugit pulvere torpet. Tabe finiat, cum Aegeus manet fluctus totidem 146 | prospiciens miserandus causa, cinctaeque de enim ostentis passaque. 147 | 148 | --- 149 | 150 | ## Isse Aenea advertens iuvencae quo libido 151 | 152 | Suo ulla, [hinc modo](http://cum-natura.org/) ille hostibus parentis offensane 153 | natalibus Icare illius neque Nereide cum. Desinat **ab mittis**, sagittas 154 | geminae gente! Conclamat trabeati haut quo atris laetus. 155 | 156 | --- 157 | 158 | [Gallicus](http://www.mala.org/ausus) et ora stimulis regnum, inanem gratamque, 159 | venti abit sorbere, erat, **quam**. Pecudes totidem rostro, usus sed, dura 160 | concurreret nectar. 161 | 162 | Prohibent conorque mea infelix gratesque dilectaque dotatissima artus me ales, 163 | superest viro dabit: maris. Sine nec numeri est, contractus repandus sunt: 164 | radice solus aequalibus. 165 | 166 | --- 167 | 168 | Vox calidumque exceptas etiamnum oculosque tendit [fratris relinquam 169 | sinuatoque](http://coepisseedidit.net/spectabere) pedibus; non. Perdidit iniquis 170 | belua animoque carcere, per saltu non, mota rore. Venit _iubet tenuissimus_, 171 | ille posuisti iuppiter, iam quam tradere. Sibyllae trepidare aequore terrae. 172 | Posceret autumnos _licet surrexit_ in late, fluxit, iaculo prius; volenti 173 | venenum adulterium haec cervice ab duro erat. 174 | 175 | --- 176 | 177 | ## Frenis telluris genitor venerat lacrimarum equos 178 | 179 | Et ad operique Athamas terret ducis quo videres suis sine commissas Tmolus 180 | suique colit dominumque et quod? Nulla cura muneris siquem potest inposuitque 181 | deceat somnoque aderat, aranea in habebant medio illum, est quoque aut. Eadem 182 | dixerat per impetus _ire haerens nunc_ Persidaque pressit videoque _manu_. 183 | 184 | --- 185 | 186 | Certamine _mente haliaeetus_ ministret qua; pennae somnus, utere deum caede: 187 | quid muros. Quique forti; Peleu huic nullis. Partim manu, concutit umbrarum 188 | quibusque arma huic sicut saxa: supra Volturnus. Et forte repugnat laetis nisi; 189 | dextra sparsit solitum corpore, sic spumosis de oraque. Sententia capioque et 190 | cura supremo mille spem, _in_ nostrae radiis, promissaque hos labore non, citis 191 | pavido ore. 192 | 193 | 194 | 195 | ## Tollere ruit etiam quota semifer rustica lactantes 196 | 197 | Virgo Aeneadae flores in, ipsa animis tamen quis est Rhadamanthus caelestia 198 | solidumque. Arbor litore: fruticumque in quaque praedator usum tibi, procellae 199 | Iliaden volantem. 200 | 201 | - Vetitae eripuit et neque et 202 | - Servat alas Vertumnus Ilion proxima mihi sibi 203 | - Dea succincta erat 204 | - Cape verba ut qua quem genitor 205 | 206 | ## Cedunt Aiax cum rerum 207 | 208 | Nomine fumantiaque levat cursuque, est in peto simulacraque [facinus ne 209 | tempora](http://ferre.com/) caeli, aperire utraque? 210 | 211 | - Certamine at sidereum inmissusque magis tyranni ulla 212 | - Poterat solitumque sunt 213 | - Superbum genibusque mediis 214 | - Pocula infans et in satis 215 | 216 | Vox calidumque exceptas etiamnum oculosque tendit [fratris relinquam 217 | sinuatoque](http://coepisseedidit.net/spectabere) pedibus; non. Perdidit iniquis 218 | belua animoque carcere, per saltu non, mota rore. Venit _iubet tenuissimus_, 219 | ille posuisti iuppiter, iam quam tradere. Sibyllae trepidare aequore terrae. 220 | Posceret autumnos _licet surrexit_ in late, fluxit, iaculo prius; volenti 221 | venenum adulterium haec cervice ab duro erat. 222 | -------------------------------------------------------------------------------- /demo/src/pages/images/01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/images/01.jpg -------------------------------------------------------------------------------- /demo/src/pages/images/04.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/images/04.jpg -------------------------------------------------------------------------------- /demo/src/pages/images/05.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/images/05.jpg -------------------------------------------------------------------------------- /demo/src/pages/images/06.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/images/06.jpg -------------------------------------------------------------------------------- /demo/src/pages/images/07.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/images/07.jpg -------------------------------------------------------------------------------- /demo/src/pages/images/08.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/images/08.jpg -------------------------------------------------------------------------------- /demo/src/pages/images/09.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/images/09.jpg -------------------------------------------------------------------------------- /demo/src/pages/images/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/images/10.jpg -------------------------------------------------------------------------------- /demo/src/pages/images/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/images/11.jpg -------------------------------------------------------------------------------- /demo/src/pages/images/index.mdx: -------------------------------------------------------------------------------- 1 | import { ImageWave } from "gatsby-theme-waves" 2 | import PageLayout from "../../components/images/layout" 3 | export default PageLayout 4 | 5 | 6 | 7 | ![](./01.jpg) 8 | 9 | # Ulla Libye inductum 10 | 11 | ## Res arsit alta elusaque dixit 12 | 13 | Lorem markdownum seniles. Rediere iam quid laudat turba medias vires vocatur 14 | pavet aptius, pondere patris, circuitu! Vias sumpsisse. 15 | 16 | - Certamine at sidereum inmissusque magis tyranni ulla 17 | - Poterat solitumque sunt 18 | - Superbum genibusque mediis 19 | - Pocula infans et in satis 20 | 21 | Vox calidumque exceptas etiamnum oculosque tendit [fratris relinquam 22 | sinuatoque](http://coepisseedidit.net/spectabere) pedibus; non. Perdidit iniquis 23 | belua animoque carcere, per saltu non, mota rore. Venit _iubet tenuissimus_, 24 | ille posuisti iuppiter, iam quam tradere. Sibyllae trepidare aequore terrae. 25 | Posceret autumnos _licet surrexit_ in late, fluxit, iaculo prius; volenti 26 | venenum adulterium haec cervice ab duro erat. 27 | 28 | ![](./04.jpg) 29 | 30 | ## Non laborum cum 31 | 32 | Exitium porrexit referam ceratis, _dantem si super_, iuncta ad, de consueta 33 | **mille dabis**. Audaci illis prohibent visa. 34 | 35 | 1. Esset feros tantum suos dedantur 36 | 2. Nec posco sensit dira 37 | 3. Per medii ubi Threicius Circen 38 | 39 | In sine nata semper nova Tegeaea, sed fassurae agam cum lapillos et iacens 40 | memori domosque fere, nato. Statione potiar modo totiens novae obstipui in heros 41 | quodcumque quoque gemellos Rhodopeius temone, non. Lotos audire sordida obliquo; 42 | ira accipit in Aurora, Helles postquam. Infregit secundo coniuge iussa cur tamen 43 | pro fretum quid saepibus, tibi. 44 | 45 | ![](./05.jpg) 46 | 47 | ## Tela centauri nobis perhorruit pugnat facundis claudit 48 | 49 | Revellit latebras tamen vivo **vellera herbas**. Ulixem huius acerbo 50 | recondiderat verba acceptaque ater mansit tandem, ex? Fortuna caeca collectum 51 | crudelis rogant increpuit, primum Ecce, fessamque 52 | [illis](http://ad-tu.org/quid.html) quae **fama** modo longius dei [fugiunt 53 | vindice](http://qua-ingrate.io/telum.php). 54 | 55 | Tertius passus ossibus inter, pervenerat armis ruricolae in sibi suffusus, 56 | **se** quod nec quod: dumosaque iungat color. Dextra dictis aures mirum, 57 | rescindere petit, cavo molli pia suarum, tum cum gradu. 58 | 59 | Est fuga colore translata liquida pervenit Laomedonque prius volventem alarum 60 | infelix corpus canum valeant. Colle [prensoque](http://pater-nec.net/) cecidit 61 | oscula. Artus senioribus manum quod, tamen caput circumdata nata fictos; ora 62 | arguit durisque excutior. 63 | 64 | Sit eligendi dignissim et, sit eius ancillae voluptatibus te. Ea summo nostrum omnesque sed. Deserunt iracundia definiebas ei est. 65 | 66 | ![](./06.jpg) 67 | 68 | ## Caput haec iam extulerat transire unda vultus 69 | 70 | **Lorem markdownum** quantus laeta [et vincere](http://et-corpus.com/serpit) 71 | castique tenuit; in erras: iacebas gramen, totiens Danaam: ad. _Rescindere_ 72 | ripas, vestem, qua otia est, ferox avidamque, purgamina. 73 | 74 | Achilles priori Aethiopasque plura duabus Phorcidas, ventis _conlapsaque quod_. 75 | Tanto pectore rebus: atria quae semina corpus; igne recens ferrum violesque 76 | quibus fugiuntque aequos, raptatur malignas tuas. Et maledicere placitas 77 | _Phinea_ lacrimis ad petit ardescunt dumque excipiunt longis iuvenis tendentem 78 | malo. Danaam mane, remissis vis nova **sinit** parte, truces et sonat noctis! 79 | 80 | ![](./08.jpg) 81 | 82 | ## Per Phaethon phaedimus Priamides erat humano iuvencae 83 | 84 | Umbra pars proelia Troum. Cum Mysum sedes, mutatur facies sepulcris ut beati 85 | tandem stridore de Thisbes! Rudis iustissimus tamen 86 | [pectore](http://modo.net/latus) si sequar relinquit Laconide; hic fovet saltem. 87 | 88 | Coniugis persequar denique alter ducat Celmi nec laevae iaculum sibi, inerti 89 | tenentem, gladios poenas _dumque sonabat_. Novo sapies **sine quo**; ubi saepe 90 | petenda Phoebus venerat, tegis. Viro mente Actaeon nec fecit **vitae** malo 91 | herbis et illae ad ipso Pharsalia bellica: o _cui_ places. 92 | 93 | ![](./09.jpg) 94 | 95 | ## Diem vero 96 | 97 | Urbem fecere figat: cum referentia amissam ruit, obice meminisse voces coniunx: 98 | [famuli dixi non](http://stringit.net/mersis-pluribus) tumescunt mane. 99 | [Contraque](http://ecce.org/) dextram ereptus, pedis resolvit sceleratus, quem 100 | ex, inpensius et. Ad adspiceres spemque ibi tamen. 101 | 102 | 1. Dona verba solitum gravitas carmina in ecce 103 | 2. Sustulit erat retia 104 | 3. Haec humi 105 | 4. Erant sensi quae addidit istis minor lavere 106 | 5. Et quoque serpit labant 107 | 108 | Cornibus ossa aere frustraque conanti, et sua dedisses poma domus illa! Natos 109 | caelo mittere, amari, quasque Callida, sub caesis fugacis, vicinia insidias Aiax 110 | venio contigit percussa. Sunt tibi semina, dolor Phaethon: videre, _antiquam_, 111 | qui respicit ferocia laterique amnes, Phoebique quod. Quem lacertis portabat. 112 | 113 | [Sub iam](http://sicula-intonsumque.net/brevis-caelumque.php) sed ictus tellure 114 | ora _artus nix_ quondam sublimis auras gruem. Orat suam fati generi, quoque aut 115 | pallada pisces raucaque populus leaeque palmis, luctor vigilantibus quae 116 | Cyllene? 117 | 118 | ![](./07.jpg) 119 | 120 | ## Eque virtus 121 | 122 | Lorem markdownum obliquis, census pallorque lumine _trementi_ aerias, ferunt 123 | _insopitumque rata spargit_ vices a? Scelus pisces. Aer [pictas 124 | mons](http://illo-usum.net/) ubi inposuit ante, manus siquis et nota et 125 | miserabile aetas. Tibi petitum miscuit **time**, curvique et manibus Anaxaretes 126 | epulae! 127 | 128 | 1. Supplevit viribus dea 129 | 2. Est tellus clementia dixit 130 | 3. Mei pater poenam admovitque Tartessia ventis quaecumque 131 | 4. Per Idaeis 132 | 5. Qua puniceo 133 | 134 | ![](./10.jpg) 135 | 136 | ## Quique terrasque meas remota gestasset restabat secures 137 | 138 | Cycnum parat veteris pharetram secum fixo convulso verti spolioque velaturque 139 | inter. Lacertis Hyantea et hirta retexit mea genis Arethusa _si causa_ 140 | proceresque agris est flosque gnatis Lemnos? Illa pinguesque tanta sagittifera 141 | amare propositumque auras est funesti fecundior volebat luporum plumas. Agitatis 142 | moles aratro. 143 | 144 | [Ianua de](http://patefecit.com/) o agendum tale croceo, corpus, tabellae 145 | elicuere. Nec at quod Iove corpora, in arvis adplicat trepidans si signo 146 | rostrum. Iram _qualia_ Lucina longis tamen nosse **ambiguus**, imitata in 147 | Cyllare et. 148 | 149 | > Ramis alimenta. Non **simul** repulsa lenti isto, indeploratum ostentis, e 150 | > Antissa dant! [Ore](http://www.sibi.io/essem) positi, bracchia devoveas, 151 | > famulis faciem Lapitharum dedere viximus. 152 | 153 | ![](./11.jpg) 154 | 155 | ## Est Aphareus 156 | 157 | Optat stetit septem Euros nostros iacent corruat usus, Seriphi? Cura nunc est 158 | ictu dea nil exstinctus sagittas cum, aut mansit sacros fama! Madefactam cernit: 159 | turba imis ille vellent, inquirant quosque simulaverat summo arcum corpus! 160 | 161 | > Diu Terram tendebat funduntur te inminet ultimus: puppim motisque addiderim 162 | > duas non. Ea ille iuvenis; ope meliora quisquam Xanthos, septem. Forma Clymene 163 | > qui _mare volucrem extinctum_ glaebaque. A Zancle tetigere frequentes: membra 164 | > vera natam tantum, quo! Gurgite ponti voce morsu, profuso accipit Achillis et 165 | > et nurumque! 166 | 167 | Antaeo in admissum saepe, tu [peti repetit 168 | inania](http://www.mihi-albet.org/aequalis.html) capacem. Patrii intrat: et 169 | latus, mihi recingunt recessu iubet ab. 170 | 171 | 172 | -------------------------------------------------------------------------------- /demo/src/pages/index.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { Main, Styled, Container, Header, jsx, ThemeProvider } from "theme-ui" 3 | import { roboto } from "@theme-ui/presets" 4 | import { Global } from "@emotion/core" 5 | import codeWebm from "./media/code.webm" 6 | import codeMp4 from "./media/code.mp4" 7 | import chartsWebm from "./media/charts.webm" 8 | import chartsMp4 from "./media/charts.mp4" 9 | import imagesWebm from "./media/images.webm" 10 | import imagesMp4 from "./media/images.mp4" 11 | import mapsWebm from "./media/maps.webm" 12 | import mapsMp4 from "./media/maps.mp4" 13 | import deckWebm from "./media/deck.webm" 14 | import deckMp4 from "./media/deck.mp4" 15 | import image from "./media/home.jpg" 16 | import { Link } from "gatsby" 17 | import { Helmet } from "react-helmet" 18 | 19 | const demos = [ 20 | { 21 | title: "Code Wave", 22 | link: "/blog/post", 23 | webmSrc: codeWebm, 24 | mp4Src: codeMp4, 25 | }, 26 | { 27 | title: "Maps Wave", 28 | webmSrc: mapsWebm, 29 | mp4Src: mapsMp4, 30 | link: "/maps", 31 | }, 32 | { 33 | title: "Deck Wave", 34 | webmSrc: deckWebm, 35 | mp4Src: deckMp4, 36 | link: "/deck", 37 | }, 38 | { 39 | title: "Image Wave", 40 | webmSrc: imagesWebm, 41 | mp4Src: imagesMp4, 42 | link: "/images", 43 | }, 44 | { 45 | title: "Chart Wave", 46 | webmSrc: chartsWebm, 47 | mp4Src: chartsMp4, 48 | link: "/charts", 49 | }, 50 | ] 51 | 52 | const theme = { 53 | ...roboto, 54 | breakpoints: ["900px"], 55 | } 56 | 57 | export default () => { 58 | return ( 59 | 60 | 61 | Gatsby Theme Waves Demos 62 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 75 |
76 |
86 | 89 | Gatsby Theme Waves 90 | 91 | 95 | GitHub 96 | 97 |
98 | 101 |
109 | {demos.map((demo, i) => ( 110 | 111 | ))} 112 |
113 |
114 |
115 |
116 | ) 117 | } 118 | 119 | function Demo({ title, webmSrc, mp4Src, link, big }) { 120 | const height = big ? 350 : 240 121 | const width = big ? 560 : 384 122 | return ( 123 |
128 | 129 |
146 | 150 | 151 |
159 | 168 | {title} 169 | 170 |
171 |
172 |
173 |
174 | ) 175 | } 176 | -------------------------------------------------------------------------------- /demo/src/pages/maps/index.mdx: -------------------------------------------------------------------------------- 1 | import MapsWave from "../../components/maps/maps-wave" 2 | import PageLayout from "../../components/maps/layout" 3 | export default PageLayout 4 | 5 | 6 | 7 | ```json 8 | { 9 | "center": [-38.7183, -62.2663], 10 | "zoom": 8 11 | } 12 | ``` 13 | 14 | ## Res arsit alta elusaque dixit 15 | 16 | Lorem markdownum seniles. Rediere iam quid laudat turba medias vires vocatur 17 | pavet aptius, pondere patris, circuitu! Vias sumpsisse. 18 | 19 | - Certamine at sidereum inmissusque magis tyranni ulla 20 | - Poterat solitumque sunt 21 | - Superbum genibusque mediis 22 | - Pocula infans et in satis 23 | 24 | Vox calidumque exceptas etiamnum oculosque tendit [fratris relinquam 25 | sinuatoque](http://coepisseedidit.net/spectabere) pedibus; non. Perdidit iniquis 26 | belua animoque carcere, per saltu non, mota rore. Venit _iubet tenuissimus_, 27 | ille posuisti iuppiter, iam quam tradere. Sibyllae trepidare aequore terrae. 28 | Posceret autumnos _licet surrexit_ in late, fluxit, iaculo prius; volenti 29 | venenum adulterium haec cervice ab duro erat. 30 | 31 | ```json 32 | { 33 | "center": [-38.7183, -62.2663], 34 | "zoom": 6 35 | } 36 | ``` 37 | 38 | ## Non laborum cum 39 | 40 | Exitium porrexit referam ceratis, _dantem si super_, iuncta ad, de consueta 41 | **mille dabis**. Audaci illis prohibent visa. 42 | 43 | 1. Esset feros tantum suos dedantur 44 | 2. Nec posco sensit dira 45 | 3. Per medii ubi Threicius Circen 46 | 47 | In sine nata semper nova Tegeaea, sed fassurae agam cum lapillos et iacens 48 | memori domosque fere, nato. Statione potiar modo totiens novae obstipui in heros 49 | quodcumque quoque gemellos Rhodopeius temone, non. Lotos audire sordida obliquo; 50 | ira accipit in Aurora, Helles postquam. Infregit secundo coniuge iussa cur tamen 51 | pro fretum quid saepibus, tibi. 52 | 53 | ```json 54 | { 55 | "center": [-34.6037, -58.3816], 56 | "zoom": 6 57 | } 58 | ``` 59 | 60 | ## Tela centauri nobis perhorruit pugnat facundis claudit 61 | 62 | Revellit latebras tamen vivo **vellera herbas**. Ulixem huius acerbo 63 | recondiderat verba acceptaque ater mansit tandem, ex? Fortuna caeca collectum 64 | crudelis rogant increpuit, primum Ecce, fessamque 65 | [illis](http://ad-tu.org/quid.html) quae **fama** modo longius dei [fugiunt 66 | vindice](http://qua-ingrate.io/telum.php). 67 | 68 | Tertius passus ossibus inter, pervenerat armis ruricolae in sibi suffusus, 69 | **se** quod nec quod: dumosaque iungat color. Dextra dictis aures mirum, 70 | rescindere petit, cavo molli pia suarum, tum cum gradu. 71 | 72 | Est fuga colore translata liquida pervenit Laomedonque prius volventem alarum 73 | infelix corpus canum valeant. Colle [prensoque](http://pater-nec.net/) cecidit 74 | oscula. Artus senioribus manum quod, tamen caput circumdata nata fictos; ora 75 | arguit durisque excutior. 76 | 77 | Sit eligendi dignissim et, sit eius ancillae voluptatibus te. Ea summo nostrum omnesque sed. Deserunt iracundia definiebas ei est. 78 | 79 | ```json 80 | { 81 | "center": [-34.6037, -58.3816], 82 | "zoom": 10 83 | } 84 | ``` 85 | 86 | ## Caput haec iam extulerat transire unda vultus 87 | 88 | **Lorem markdownum** quantus laeta [et vincere](http://et-corpus.com/serpit) 89 | castique tenuit; in erras: iacebas gramen, totiens Danaam: ad. _Rescindere_ 90 | ripas, vestem, qua otia est, ferox avidamque, purgamina. 91 | 92 | Achilles priori Aethiopasque plura duabus Phorcidas, ventis _conlapsaque quod_. 93 | Tanto pectore rebus: atria quae semina corpus; igne recens ferrum violesque 94 | quibus fugiuntque aequos, raptatur malignas tuas. Et maledicere placitas 95 | _Phinea_ lacrimis ad petit ardescunt dumque excipiunt longis iuvenis tendentem 96 | malo. Danaam mane, remissis vis nova **sinit** parte, truces et sonat noctis! 97 | 98 | ```json 99 | { 100 | "center": [-34.6037, -58.3816], 101 | "zoom": 5 102 | } 103 | ``` 104 | 105 | ## Per Phaethon phaedimus Priamides erat humano iuvencae 106 | 107 | Umbra pars proelia Troum. Cum Mysum sedes, mutatur facies sepulcris ut beati 108 | tandem stridore de Thisbes! Rudis iustissimus tamen 109 | [pectore](http://modo.net/latus) si sequar relinquit Laconide; hic fovet saltem. 110 | 111 | Coniugis persequar denique alter ducat Celmi nec laevae iaculum sibi, inerti 112 | tenentem, gladios poenas _dumque sonabat_. Novo sapies **sine quo**; ubi saepe 113 | petenda Phoebus venerat, tegis. Viro mente Actaeon nec fecit **vitae** malo 114 | herbis et illae ad ipso Pharsalia bellica: o _cui_ places. 115 | 116 | ```json 117 | { 118 | "center": [-38.4161, -63.6167], 119 | "zoom": 4 120 | } 121 | ``` 122 | 123 | ## Diem vero 124 | 125 | Urbem fecere figat: cum referentia amissam ruit, obice meminisse voces coniunx: 126 | [famuli dixi non](http://stringit.net/mersis-pluribus) tumescunt mane. 127 | [Contraque](http://ecce.org/) dextram ereptus, pedis resolvit sceleratus, quem 128 | ex, inpensius et. Ad adspiceres spemque ibi tamen. 129 | 130 | 1. Dona verba solitum gravitas carmina in ecce 131 | 2. Sustulit erat retia 132 | 3. Haec humi 133 | 4. Erant sensi quae addidit istis minor lavere 134 | 5. Et quoque serpit labant 135 | 136 | Cornibus ossa aere frustraque conanti, et sua dedisses poma domus illa! Natos 137 | caelo mittere, amari, quasque Callida, sub caesis fugacis, vicinia insidias Aiax 138 | venio contigit percussa. Sunt tibi semina, dolor Phaethon: videre, _antiquam_, 139 | qui respicit ferocia laterique amnes, Phoebique quod. Quem lacertis portabat. 140 | 141 | [Sub iam](http://sicula-intonsumque.net/brevis-caelumque.php) sed ictus tellure 142 | ora _artus nix_ quondam sublimis auras gruem. Orat suam fati generi, quoque aut 143 | pallada pisces raucaque populus leaeque palmis, luctor vigilantibus quae 144 | Cyllene? 145 | 146 | ```json 147 | { 148 | "center": [-38.4161, -63.6167], 149 | "zoom": 3 150 | } 151 | ``` 152 | 153 | ## Eque virtus 154 | 155 | Lorem markdownum obliquis, census pallorque lumine _trementi_ aerias, ferunt 156 | _insopitumque rata spargit_ vices a? Scelus pisces. Aer [pictas 157 | mons](http://illo-usum.net/) ubi inposuit ante, manus siquis et nota et 158 | miserabile aetas. Tibi petitum miscuit **time**, curvique et manibus Anaxaretes 159 | epulae! 160 | 161 | 1. Supplevit viribus dea 162 | 2. Est tellus clementia dixit 163 | 3. Mei pater poenam admovitque Tartessia ventis quaecumque 164 | 4. Per Idaeis 165 | 5. Qua puniceo 166 | 167 | 168 | -------------------------------------------------------------------------------- /demo/src/pages/media/chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/chart.png -------------------------------------------------------------------------------- /demo/src/pages/media/chart.t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/chart.t.png -------------------------------------------------------------------------------- /demo/src/pages/media/charts.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/charts.mp4 -------------------------------------------------------------------------------- /demo/src/pages/media/charts.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/charts.webm -------------------------------------------------------------------------------- /demo/src/pages/media/code-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/code-dark.png -------------------------------------------------------------------------------- /demo/src/pages/media/code-dark.t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/code-dark.t.png -------------------------------------------------------------------------------- /demo/src/pages/media/code.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/code.gif -------------------------------------------------------------------------------- /demo/src/pages/media/code.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/code.mp4 -------------------------------------------------------------------------------- /demo/src/pages/media/code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/code.png -------------------------------------------------------------------------------- /demo/src/pages/media/code.t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/code.t.png -------------------------------------------------------------------------------- /demo/src/pages/media/code.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/code.webm -------------------------------------------------------------------------------- /demo/src/pages/media/deck.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/deck.mp4 -------------------------------------------------------------------------------- /demo/src/pages/media/deck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/deck.png -------------------------------------------------------------------------------- /demo/src/pages/media/deck.t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/deck.t.png -------------------------------------------------------------------------------- /demo/src/pages/media/deck.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/deck.webm -------------------------------------------------------------------------------- /demo/src/pages/media/home.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/home.jpg -------------------------------------------------------------------------------- /demo/src/pages/media/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/image.png -------------------------------------------------------------------------------- /demo/src/pages/media/image.t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/image.t.png -------------------------------------------------------------------------------- /demo/src/pages/media/images.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/images.mp4 -------------------------------------------------------------------------------- /demo/src/pages/media/images.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/images.webm -------------------------------------------------------------------------------- /demo/src/pages/media/jam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/jam.png -------------------------------------------------------------------------------- /demo/src/pages/media/maps.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/maps.mp4 -------------------------------------------------------------------------------- /demo/src/pages/media/maps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/maps.png -------------------------------------------------------------------------------- /demo/src/pages/media/maps.t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/maps.t.png -------------------------------------------------------------------------------- /demo/src/pages/media/maps.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/src/pages/media/maps.webm -------------------------------------------------------------------------------- /demo/src/pages/screenshots.js: -------------------------------------------------------------------------------- 1 | import code from "./media/code.png" 2 | import codeDark from "./media/code-dark.png" 3 | import deck from "./media/deck.png" 4 | import image from "./media/image.png" 5 | import maps from "./media/maps.png" 6 | import chart from "./media/chart.png" 7 | import React from "react" 8 | import { Global } from "@emotion/core" 9 | 10 | const shots = [ 11 | ["Code Wave", code], 12 | ["Code Wave", codeDark], 13 | ["Deck Wave", deck], 14 | ["Image Wave", image], 15 | ["Maps Wave", maps], 16 | ["Chart Wave", chart], 17 | ] 18 | 19 | export default () => { 20 | return ( 21 | 22 | 25 |
26 | 27 | 28 | 29 |
30 |
31 | 32 | 33 | 34 |
35 |
36 | 37 | 38 |
39 |
40 | ) 41 | } 42 | 43 | function Screenshot({ shot }) { 44 | const [title, img] = shot 45 | return ( 46 |
53 | 57 |
68 |

76 | {title} 77 |

78 |
79 |
80 | ) 81 | } 82 | 83 | function FullScreenshot({ shot }) { 84 | const [title, img] = shot 85 | return ( 86 |
87 | 91 |
102 |

109 | {title} 110 |

111 |
112 |
113 | ) 114 | } 115 | -------------------------------------------------------------------------------- /demo/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/demo/static/favicon.ico -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Rodrigo Pombo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "workspaces": [ 4 | "theme", 5 | "demo", 6 | "blog-demo", 7 | "rehype-waves" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Gatsby Theme Waves 2 | 3 | ### **I'm not maintaining this project anymore, but I'm working on its spiritual successor: [Code Hike](https://github.com/code-hike/codehike)** 4 | 5 | Bring scrollytelling to your mdx. Animate code, images, charts, maps and more as you scroll. 6 | 7 | 13 | 14 | The MDX looks like this: 15 | 16 | ````md 17 | import { CodeWave } from "gatsby-theme-waves" 18 | 19 | 20 | 21 | ```py 22 | # some code 23 | ``` 24 | 25 | # Some markdown 26 | 27 | ```py 28 | # more code 29 | ``` 30 | 31 | More markdown 32 | 33 | > and more 34 | 35 | ```py 36 | # and more 37 | ``` 38 | 39 | - ok 40 | - that's enough 41 | 42 | 43 | ```` 44 | 45 | ## Installation 46 | 47 | You need a Gatsby site with MDX. For example, this is how you add gatsby-theme-waves to a site that uses [gatsby-theme-blog](https://www.npmjs.com/package/gatsby-theme-blog): 48 | 49 | 1. Install the theme (and `deepmerge` for merging the theme styles) 50 | 51 | ```sh 52 | npm install --save gatsby-theme-waves deepmerge 53 | ``` 54 | 55 | 2. Add the theme to your `gatsby-config.js` (at the end of the plugin list just in case) 56 | 57 | ```js 58 | module.exports = { 59 | plugins: [ 60 | "gatsby-theme-blog", 61 | "gatsby-theme-waves" // <-- add this 62 | ] 63 | }; 64 | ``` 65 | 66 | 3. Merge the styles: create or edit `src/gatsby-plugin-theme-ui/index.js` 67 | 68 | ```js 69 | import wavesTheme from "gatsby-theme-waves/src/gatsby-plugin-theme-ui/index"; 70 | import blogTheme from "gatsby-theme-blog/src/gatsby-plugin-theme-ui/index"; 71 | import merge from "deepmerge"; 72 | 73 | export default merge(blogTheme, wavesTheme); 74 | ``` 75 | 76 | 4) Import `CodeWave` and use it in any MDX file 77 | 78 | ````md 79 | import { CodeWave } from "gatsby-theme-waves" 80 | 81 | 82 | 83 | ```py 84 | # some code 85 | ``` 86 | 87 | # Some markdown 88 | 89 | ```py 90 | # more code 91 | ``` 92 | 93 | More markdown 94 | 95 | > and more 96 | 97 | ```py 98 | # and more 99 | ``` 100 | 101 | - ok 102 | - that's enough 103 | 104 | 105 | ```` 106 | 107 | Your set up should look like [this example](https://github.com/pomber/gatsby-theme-waves/tree/master/blog-demo). 108 | 109 | ### Code Blocks 110 | 111 | By default the lines that changed between two consecutive code blocks will be highlighted. You can change it to highlight the line (and columns) you want: 112 | 113 | ````md 114 | ```js 1:3,6 115 | // highlights line 1,2,3 and 6 116 | ``` 117 | 118 | ```js 5[1,3:6],8 119 | // highlights: 120 | // columns 1,3,4,5 and 6 from line 5 121 | // and line 8 122 | ``` 123 | ```` 124 | 125 | ## Coming Soon 126 | 127 | - Import code from files 128 | - Better custom code syntax highlighting using theme-ui 129 | - More waves 130 | - More docs 131 | -------------------------------------------------------------------------------- /rehype-waves/.npmignore: -------------------------------------------------------------------------------- 1 | __* -------------------------------------------------------------------------------- /rehype-waves/__file_snapshots__/codeblock.mdx-0: -------------------------------------------------------------------------------- 1 | /* @jsx mdx */ 2 | import { CodeWave } from "waves"; 3 | 4 | const makeShortcode = name => function MDXDefaultShortcode(props) { 5 | console.warn("Component " + name + " was not imported, exported, or provided by MDXProvider as global scope") 6 | return
7 | }; 8 | 9 | const layoutProps = { 10 | 11 | }; 12 | const MDXLayout = "wrapper" 13 | export default function MDXContent({ 14 | components, 15 | ...props 16 | }) { 17 | return 18 | 19 | 50 |
51 |
52 |

{`Markdown`}

53 |
{`// nested
56 | `}
57 |
58 |
59 |
60 |

Foo

61 | 62 |

63 | 64 |

65 |
66 | 67 |
{`// nested 2
70 | `}
71 |
72 |
73 |
74 |

{`Bye`}

75 |
76 |
77 |
; 78 | } 79 | 80 | ; 81 | MDXContent.isMDXComponent = true; -------------------------------------------------------------------------------- /rehype-waves/__file_snapshots__/metastring.mdx-0: -------------------------------------------------------------------------------- 1 | /* @jsx mdx */ 2 | import { CodeWave } from "waves"; 3 | 4 | const makeShortcode = name => function MDXDefaultShortcode(props) { 5 | console.warn("Component " + name + " was not imported, exported, or provided by MDXProvider as global scope") 6 | return
7 | }; 8 | 9 | const layoutProps = { 10 | 11 | }; 12 | const MDXLayout = "wrapper" 13 | export default function MDXContent({ 14 | components, 15 | ...props 16 | }) { 17 | return 18 | 19 | 35 |
36 |

{`Markdown`}

37 |
38 |
39 |
; 40 | } 41 | 42 | ; 43 | MDXContent.isMDXComponent = true; -------------------------------------------------------------------------------- /rehype-waves/__file_snapshots__/minimal.mdx-0: -------------------------------------------------------------------------------- 1 | /* @jsx mdx */ 2 | import { CodeWave } from "waves"; 3 | 4 | const makeShortcode = name => function MDXDefaultShortcode(props) { 5 | console.warn("Component " + name + " was not imported, exported, or provided by MDXProvider as global scope") 6 | return
7 | }; 8 | 9 | const layoutProps = { 10 | 11 | }; 12 | const MDXLayout = "wrapper" 13 | export default function MDXContent({ 14 | components, 15 | ...props 16 | }) { 17 | return 18 | 19 | 34 |
35 |

{`Markdown`}

36 |
37 |
38 |
; 39 | } 40 | 41 | ; 42 | MDXContent.isMDXComponent = true; -------------------------------------------------------------------------------- /rehype-waves/__file_snapshots__/multi-steps.mdx-0: -------------------------------------------------------------------------------- 1 | /* @jsx mdx */ 2 | 3 | 4 | const makeShortcode = name => function MDXDefaultShortcode(props) { 5 | console.warn("Component " + name + " was not imported, exported, or provided by MDXProvider as global scope") 6 | return
7 | }; 8 | const CodeWave = makeShortcode("CodeWave"); 9 | const layoutProps = { 10 | 11 | }; 12 | const MDXLayout = "wrapper" 13 | export default function MDXContent({ 14 | components, 15 | ...props 16 | }) { 17 | return 18 | 41 |
42 |

{`M1`}

43 |

{`M2`}

44 |
45 |
46 |

{`M3`}

47 |
48 |
49 |
; 50 | } 51 | 52 | ; 53 | MDXContent.isMDXComponent = true; -------------------------------------------------------------------------------- /rehype-waves/__fixtures__/codeblock.mdx: -------------------------------------------------------------------------------- 1 | import { CodeWave } from "waves"; 2 | 3 | 4 | 5 | ```js 6 | x; 7 | ``` 8 | 9 |
10 | 11 | Markdown 12 | 13 | ```js 14 | // nested 15 | ``` 16 | 17 |
18 | 19 | ```js 20 | x2; 21 | ``` 22 | 23 |

Foo

24 | 25 | 26 |

27 | 28 |

29 |
30 | 31 | 32 | 33 | ```js 34 | // nested 2 35 | ``` 36 | 37 | 38 | 39 | ```js 40 | x3; 41 | ``` 42 | 43 | Bye 44 | 45 |
46 | -------------------------------------------------------------------------------- /rehype-waves/__fixtures__/metastring.mdx: -------------------------------------------------------------------------------- 1 | import { CodeWave } from "waves"; 2 | 3 | 4 | 5 | ```python 1[3:4] title="T" 6 | # hi 7 | ``` 8 | 9 | Markdown 10 | 11 | 12 | -------------------------------------------------------------------------------- /rehype-waves/__fixtures__/minimal.mdx: -------------------------------------------------------------------------------- 1 | import { CodeWave } from "waves"; 2 | 3 | 4 | 5 | ```js 6 | x; 7 | ``` 8 | 9 | Markdown 10 | 11 | 12 | -------------------------------------------------------------------------------- /rehype-waves/__fixtures__/multi-steps.mdx: -------------------------------------------------------------------------------- 1 | 2 | 3 | ```js 4 | x; 5 | ``` 6 | 7 | # M1 8 | 9 | ## M2 10 | 11 | ```js 12 | x; 13 | ``` 14 | 15 | M3 16 | 17 | 18 | -------------------------------------------------------------------------------- /rehype-waves/index.js: -------------------------------------------------------------------------------- 1 | var visit = require("unist-util-visit"); 2 | const { parseSteps } = require("@code-surfer/step-parser"); 3 | const { readStepFromElement } = require("./step-reader"); 4 | const Prism = require("prismjs"); 5 | 6 | module.exports = slug; 7 | 8 | function slug() { 9 | return transformer; 10 | } 11 | 12 | function transformer(tree) { 13 | visit(tree, "jsx", (node, index, parent) => { 14 | // for each CodeWave 15 | if (node.value.startsWith("") { 24 | const sibling = siblings[i]; 25 | 26 | if (sibling.type === "jsx" && isOpenTag(sibling.value)) { 27 | nesting++; 28 | } 29 | if (sibling.type === "jsx" && isCloseTag(sibling.value)) { 30 | nesting--; 31 | } 32 | 33 | if (!nesting && sibling.tagName === "pre") { 34 | pres.push(sibling); 35 | } 36 | i++; 37 | } 38 | const lastChildIndex = i - 1; 39 | 40 | if (!pres.length) { 41 | return; 42 | } 43 | 44 | // replace the code blocks and wrap the markdown elements in divs 45 | siblings[siblings.indexOf(pres[0])] = { type: "jsx", value: "
" }; 46 | siblings.splice( 47 | lastChildIndex, 48 | 0, 49 | { type: "text", value: "\n" }, 50 | { type: "jsx", value: "
" } 51 | ); 52 | for (let prei = 1; prei < pres.length; prei++) { 53 | const siblingi = siblings.indexOf(pres[prei]); 54 | siblings.splice( 55 | siblingi, 56 | 1, 57 | { type: "jsx", value: "
" }, 58 | { type: "text", value: "\n" }, 59 | { type: "jsx", value: "
" } 60 | ); 61 | } 62 | 63 | // parse the codeblocks into input steps 64 | const steps = pres.map(readStepFromElement); 65 | 66 | // parse the input steps 67 | const lang = steps[0].lang; 68 | if (!Prism.languages[lang]) { 69 | require(`prismjs/components/prism-${lang}`); 70 | } 71 | 72 | const s = parseSteps(steps); 73 | 74 | // pass the parsed steps prop to CodeWave 75 | node.value = node.value.replace( 76 | ">", 77 | ` parsedSteps={${JSON.stringify(s)}}>` 78 | ); 79 | } 80 | }); 81 | } 82 | 83 | function isOpenTag(value) { 84 | return /^\s*<([^\/>]*)>\s*$/.test(value); 85 | } 86 | 87 | function isCloseTag(value) { 88 | return /^\s*<\/([^\/>]*)>\s*$/.test(value); 89 | } 90 | -------------------------------------------------------------------------------- /rehype-waves/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rehype-waves", 3 | "version": "0.1.6", 4 | "author": "Rodrigo Pombo", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/pomber/gatsby-theme-waves.git" 8 | }, 9 | "license": "MIT", 10 | "devDependencies": { 11 | "@mdx-js/mdx": "^1.4.0", 12 | "jest": "^24.9.0", 13 | "jest-file-snapshot": "^0.3.7" 14 | }, 15 | "scripts": { 16 | "test": "jest", 17 | "watch": "jest --watch -u" 18 | }, 19 | "jest": { 20 | "watchPathIgnorePatterns": [ 21 | "__file_snapshots__" 22 | ] 23 | }, 24 | "dependencies": { 25 | "@code-surfer/step-parser": "3.1.1", 26 | "shell-quote": "^1.7.2", 27 | "unist-util-visit": "^2.0.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /rehype-waves/parser.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function _interopDefault(ex) { 4 | return ex && typeof ex === "object" && "default" in ex ? ex["default"] : ex; 5 | } 6 | 7 | var diff = require("diff"); 8 | var React = _interopDefault(require("react")); 9 | var Prism = _interopDefault(require("prismjs")); 10 | var flat = _interopDefault(require("array.prototype.flat")); 11 | 12 | function _extends() { 13 | _extends = 14 | Object.assign || 15 | function(target) { 16 | for (var i = 1; i < arguments.length; i++) { 17 | var source = arguments[i]; 18 | 19 | for (var key in source) { 20 | if (Object.prototype.hasOwnProperty.call(source, key)) { 21 | target[key] = source[key]; 22 | } 23 | } 24 | } 25 | 26 | return target; 27 | }; 28 | 29 | return _extends.apply(this, arguments); 30 | } 31 | 32 | function _objectWithoutPropertiesLoose(source, excluded) { 33 | if (source == null) return {}; 34 | var target = {}; 35 | var sourceKeys = Object.keys(source); 36 | var key, i; 37 | 38 | for (i = 0; i < sourceKeys.length; i++) { 39 | key = sourceKeys[i]; 40 | if (excluded.indexOf(key) >= 0) continue; 41 | target[key] = source[key]; 42 | } 43 | 44 | return target; 45 | } 46 | 47 | function grammarNotFound(_ref2) { 48 | var lang = _ref2.lang; 49 | return { 50 | element: React.createElement(ErrorBox, { 51 | header: "Oops, there's a problem", 52 | body: React.createElement( 53 | React.Fragment, 54 | null, 55 | "Syntax highlighter for ", 56 | React.createElement(Mark, null, '"', lang, '"'), 57 | " not found.", 58 | React.createElement( 59 | "p", 60 | null, 61 | "You can try importing it from prismjs with: ", 62 | React.createElement("br", null), 63 | React.createElement( 64 | Mark, 65 | null, 66 | 'import "prismjs/components/prism-', 67 | lang, 68 | '"' 69 | ) 70 | ), 71 | "(See", 72 | " ", 73 | React.createElement( 74 | "a", 75 | { 76 | href: "https://prismjs.com/#supported-languages", 77 | style: { 78 | color: "grey" 79 | } 80 | }, 81 | "all the supported languages" 82 | ), 83 | ")" 84 | ) 85 | }) 86 | }; 87 | } 88 | function invalidFocusNumber(n) { 89 | return { 90 | withFocusString: function withFocusString(focusString) { 91 | return { 92 | withStepIndex: function withStepIndex(stepIndex) { 93 | return { 94 | element: React.createElement(ErrorBox, { 95 | header: React.createElement(StepErrorHeader, { 96 | stepIndex: stepIndex 97 | }), 98 | body: React.createElement( 99 | React.Fragment, 100 | null, 101 | React.createElement(Mark, null, '"', n, '"'), 102 | " isn't a valid number", 103 | " ", 104 | n != focusString && 105 | React.createElement(Mark, null, ' (in "', focusString, '")') 106 | ) 107 | }) 108 | }; 109 | } 110 | }; 111 | } 112 | }; 113 | } 114 | function invalidLineOrColumnNumber() { 115 | return { 116 | withFocusString: function withFocusString(focusString) { 117 | return { 118 | withStepIndex: function withStepIndex(stepIndex) { 119 | return { 120 | element: React.createElement(ErrorBox, { 121 | header: React.createElement(StepErrorHeader, { 122 | stepIndex: stepIndex 123 | }), 124 | body: React.createElement( 125 | React.Fragment, 126 | null, 127 | 'Are you using "0" as a line or column number', 128 | " ", 129 | React.createElement(Mark, null, 'in "', focusString, '"'), 130 | "?", 131 | React.createElement("br", null), 132 | "(Line and column numbers should start at 1, not 0) ", 133 | React.createElement("br", null) 134 | ) 135 | }) 136 | }; 137 | } 138 | }; 139 | } 140 | }; 141 | } 142 | 143 | function ErrorBox(_ref3) { 144 | var header = _ref3.header, 145 | body = _ref3.body; 146 | return React.createElement( 147 | "div", 148 | { 149 | style: { 150 | background: "#290000", 151 | color: "#b96f70", 152 | border: "2px solid #b96f70", 153 | padding: "10px 30px", 154 | maxWidth: "90vw", 155 | margin: "0 auto", 156 | fontFamily: "monospace", 157 | fontSize: "1rem" 158 | } 159 | }, 160 | React.createElement("h3", null, header), 161 | React.createElement("p", null, body) 162 | ); 163 | } 164 | 165 | function StepErrorHeader(_ref4) { 166 | var stepIndex = _ref4.stepIndex; 167 | return React.createElement( 168 | React.Fragment, 169 | null, 170 | "Oops, there's a problem with the", 171 | " ", 172 | React.createElement( 173 | Mark, 174 | null, 175 | stepIndex + 1, 176 | React.createElement("sup", null, ordinal(stepIndex + 1)), 177 | " step" 178 | ) 179 | ); 180 | } 181 | 182 | function Mark(_ref5) { 183 | var children = _ref5.children; 184 | return React.createElement( 185 | "mark", 186 | { 187 | style: { 188 | background: "none", 189 | color: "pink", 190 | fontWeight: "bolder" 191 | } 192 | }, 193 | children 194 | ); 195 | } 196 | 197 | function ordinal(i) { 198 | var j = i % 10, 199 | k = i % 100; 200 | 201 | if (j == 1 && k != 11) { 202 | return "st"; 203 | } 204 | 205 | if (j == 2 && k != 12) { 206 | return "nd"; 207 | } 208 | 209 | if (j == 3 && k != 13) { 210 | return "rd"; 211 | } 212 | 213 | return "th"; 214 | } 215 | 216 | var newlineRe = /\r\n|\r|\n/; // Take a list of nested tokens 217 | // (token.content may contain an array of tokens) 218 | // and flatten it so content is always a string 219 | // and type the type of the leaf 220 | 221 | function flattenTokens(tokens) { 222 | var flatList = []; 223 | tokens.forEach(function(token) { 224 | var type = token.type, 225 | content = token.content; 226 | 227 | if (Array.isArray(content)) { 228 | flatList.push.apply(flatList, flattenTokens(content)); 229 | } else { 230 | flatList.push({ 231 | type: type, 232 | content: content 233 | }); 234 | } 235 | }); 236 | return flatList; 237 | } 238 | 239 | function wrapToken(prismToken, parentType) { 240 | if (parentType === void 0) { 241 | parentType = "plain"; 242 | } 243 | 244 | if (typeof prismToken === "string") { 245 | return { 246 | type: parentType, 247 | content: prismToken 248 | }; 249 | } 250 | 251 | if (Array.isArray(prismToken.content)) { 252 | return { 253 | type: prismToken.type, 254 | content: tokenizeStrings(prismToken.content, prismToken.type) 255 | }; 256 | } 257 | 258 | return wrapToken(prismToken.content, prismToken.type); 259 | } // Wrap strings in tokens 260 | 261 | function tokenizeStrings(prismTokens, parentType) { 262 | if (parentType === void 0) { 263 | parentType = "plain"; 264 | } 265 | 266 | return prismTokens.map(function(prismToken) { 267 | return wrapToken(prismToken, parentType); 268 | }); 269 | } 270 | 271 | function tokenize(code, language) { 272 | if (language === void 0) { 273 | language = "javascript"; 274 | } 275 | 276 | var grammar = Prism.languages[language]; 277 | 278 | if (!grammar) { 279 | throw grammarNotFound({ 280 | lang: language 281 | }); 282 | } 283 | 284 | var prismTokens = Prism.tokenize(code, Prism.languages[language]); 285 | var nestedTokens = tokenizeStrings(prismTokens); 286 | var tokens = flattenTokens(nestedTokens); 287 | var currentLine = []; 288 | var lines = [currentLine]; 289 | tokens.forEach(function(token) { 290 | var contentLines = token.content.split(newlineRe); 291 | var firstContent = contentLines.shift(); 292 | 293 | if (firstContent !== undefined && firstContent !== "") { 294 | currentLine.push({ 295 | type: token.type, 296 | content: firstContent 297 | }); 298 | } 299 | 300 | contentLines.forEach(function(content) { 301 | currentLine = []; 302 | lines.push(currentLine); 303 | 304 | if (content !== "") { 305 | currentLine.push({ 306 | type: token.type, 307 | content: content 308 | }); 309 | } 310 | }); 311 | }); 312 | return lines; 313 | } 314 | 315 | var newlineRe$1 = /\r\n|\r|\n/; 316 | 317 | function myDiff(oldCode, newCode) { 318 | var changes = diff.diffLines(oldCode || "", newCode); 319 | var oldIndex = -1; 320 | return changes.map(function(_ref) { 321 | var value = _ref.value, 322 | count = _ref.count, 323 | removed = _ref.removed, 324 | added = _ref.added; 325 | var lines = value.split(newlineRe$1); // check if last line is empty, if it is, remove it 326 | 327 | var lastLine = lines.pop(); 328 | 329 | if (lastLine) { 330 | lines.push(lastLine); 331 | } 332 | 333 | var result = { 334 | oldIndex: oldIndex, 335 | lines: lines, 336 | count: count, 337 | removed: removed, 338 | added: added 339 | }; 340 | 341 | if (!added) { 342 | oldIndex += count || 0; 343 | } 344 | 345 | return result; 346 | }); 347 | } 348 | 349 | function insert(array, index, elements) { 350 | return array.splice.apply(array, [index, 0].concat(elements)); 351 | } 352 | 353 | function slideDiff(lines, codes, slideIndex, language) { 354 | var prevLines = lines.filter(function(l) { 355 | return l.slides.includes(slideIndex - 1); 356 | }); 357 | var prevCode = codes[slideIndex - 1] || ""; 358 | var currCode = codes[slideIndex]; 359 | var changes = myDiff(prevCode, currCode); 360 | changes.forEach(function(change) { 361 | if (change.added) { 362 | var prevLine = prevLines[change.oldIndex]; 363 | var addAtIndex = lines.indexOf(prevLine) + 1; 364 | var addLines = change.lines.map(function(content) { 365 | return { 366 | content: content, 367 | slides: [slideIndex], 368 | tokens: [] 369 | }; 370 | }); 371 | insert(lines, addAtIndex, addLines); 372 | } else if (!change.removed) { 373 | for (var j = 1; j <= (change.count || 0); j++) { 374 | prevLines[change.oldIndex + j].slides.push(slideIndex); 375 | } 376 | } 377 | }); 378 | var tokenLines = tokenize(currCode, language); 379 | var currLines = lines.filter(function(l) { 380 | return l.slides.includes(slideIndex); 381 | }); 382 | currLines.forEach(function(line, index) { 383 | return (line.tokens = tokenLines[index]); 384 | }); 385 | } 386 | 387 | function parseLines(codes, language) { 388 | var lines = []; 389 | 390 | for (var slideIndex = 0; slideIndex < codes.length; slideIndex++) { 391 | slideDiff(lines, codes, slideIndex, language); 392 | } 393 | 394 | return lines; 395 | } 396 | function getSlides(codes, language) { 397 | // codes are in reverse cronological order 398 | var lines = parseLines(codes, language); // console.log("lines", lines); 399 | 400 | return codes.map(function(_, slideIndex) { 401 | return lines 402 | .map(function(line, lineIndex) { 403 | return { 404 | content: line.content, 405 | tokens: line.tokens, 406 | isNew: !line.slides.includes(slideIndex + 1), 407 | show: line.slides.includes(slideIndex), 408 | key: lineIndex 409 | }; 410 | }) 411 | .filter(function(line) { 412 | return line.show; 413 | }); 414 | }); 415 | } 416 | function getCodes(rawSteps) { 417 | var codes = []; 418 | rawSteps.forEach(function(s, i) { 419 | if (s.lang === "diff" && i > 0) { 420 | codes[i] = diff.applyPatch(codes[i - 1], s.code); 421 | } else { 422 | codes[i] = s.code; 423 | } 424 | }); 425 | return codes; 426 | } 427 | 428 | function parseFocus(focus) { 429 | if (!focus) { 430 | throw new Error("Focus cannot be empty"); 431 | } 432 | 433 | try { 434 | var parts = focus.split(/,(?![^\[]*\])/g).map(parsePart); 435 | return new Map(flat(parts)); 436 | } catch (error) { 437 | if (error.withFocusString) { 438 | throw error.withFocusString(focus); 439 | } else { 440 | throw error; 441 | } 442 | } 443 | } 444 | 445 | function parsePart(part) { 446 | // a part could be 447 | // - a line number: "2" 448 | // - a line range: "5:9" 449 | // - a line number with a column selector: "2[1,3:5,9]" 450 | var columnsMatch = part.match(/(\d+)\[(.+)\]/); 451 | 452 | if (columnsMatch) { 453 | var line = columnsMatch[1], 454 | columns = columnsMatch[2]; 455 | var columnsList = columns.split(",").map(expandString); 456 | var lineIndex = Number(line) - 1; 457 | var columnIndexes = flat(columnsList).map(function(c) { 458 | return c - 1; 459 | }); 460 | return [[lineIndex, columnIndexes]]; 461 | } else { 462 | return expandString(part).map(function(lineNumber) { 463 | return [lineNumber - 1, true]; 464 | }); 465 | } 466 | } 467 | 468 | function expandString(part) { 469 | // Transforms something like 470 | // - "1:3" to [1,2,3] 471 | // - "4" to [4] 472 | var _part$split = part.split(":"), 473 | start = _part$split[0], 474 | end = _part$split[1]; // todo check if start is 0, line numbers and column numbers start at 1 475 | 476 | if (!isNaturalNumber(start)) { 477 | throw invalidFocusNumber(start); 478 | } 479 | 480 | var startNumber = Number(start); 481 | 482 | if (startNumber < 1) { 483 | throw invalidLineOrColumnNumber(); 484 | } 485 | 486 | if (!end) { 487 | return [startNumber]; 488 | } else { 489 | if (!isNaturalNumber(end)) { 490 | throw invalidFocusNumber(end); 491 | } 492 | 493 | var list = []; 494 | 495 | for (var i = startNumber; i <= +end; i++) { 496 | list.push(i); 497 | } 498 | 499 | return list; 500 | } 501 | } 502 | 503 | function isNaturalNumber(n) { 504 | n = n.toString(); // force the value in case it is not 505 | 506 | var n1 = Math.abs(n), 507 | n2 = parseInt(n, 10); 508 | return !isNaN(n1) && n2 === n1 && n1.toString() === n; 509 | } 510 | 511 | function parseSteps(rawSteps, lang) { 512 | var codes = getCodes(rawSteps); 513 | var stepsLines = getSlides(codes.reverse(), lang).reverse(); 514 | var steps = rawSteps.map(function(step, i) { 515 | var lines = stepsLines[i]; 516 | 517 | try { 518 | return parseStep(step, lines); 519 | } catch (e) { 520 | if (e.withStepIndex) { 521 | throw e.withStepIndex(i); 522 | } else { 523 | throw e; 524 | } 525 | } 526 | }); 527 | steps.forEach(function(step) { 528 | var lines = step.lines, 529 | focusMap = step.focusMap; 530 | lines.forEach(function(line, index) { 531 | line.focus = focusMap.has(index); 532 | var columnFocus = focusMap.get(index); 533 | line.focusPerToken = Array.isArray(columnFocus); 534 | 535 | if (Array.isArray(columnFocus)) { 536 | // this mutates the tokens array in order to change it to the same line in other steps 537 | splitTokensToColumns(line.tokens); 538 | line.tokens = setTokenFocus(line.tokens, columnFocus); 539 | } 540 | }); 541 | }); 542 | return steps; 543 | } 544 | 545 | function parseStep(step, lines) { 546 | var focus = step.focus, 547 | rest = _objectWithoutPropertiesLoose(step, ["focus"]); 548 | 549 | var focusMap = focus ? parseFocus(focus) : getDefaultFocus(lines); 550 | var focusIndexes = Array.from(focusMap.keys()); 551 | var focusStart = Math.min.apply(Math, focusIndexes); 552 | var focusEnd = Math.max.apply(Math, focusIndexes); 553 | return _extends( 554 | { 555 | lines: lines, 556 | focusMap: focusMap, 557 | focusStart: focusStart, 558 | focusEnd: focusEnd, 559 | focusCenter: (focusStart + focusEnd + 1) / 2, 560 | focusCount: focusEnd - focusStart + 1 561 | }, 562 | rest 563 | ); 564 | } 565 | 566 | function getDefaultFocus(lines) { 567 | var indexes = lines 568 | .map(function(line, index) { 569 | return line.isNew ? index : -1; 570 | }) 571 | .filter(function(index) { 572 | return index !== -1; 573 | }); 574 | return new Map( 575 | indexes.map(function(i) { 576 | return [i, true]; 577 | }) 578 | ); 579 | } 580 | 581 | function splitTokensToColumns(tokenArray) { 582 | var tokens = Array.from(tokenArray); 583 | var key = 0; 584 | tokenArray.splice(0, tokenArray.length); 585 | tokens.forEach(function(token) { 586 | var chars = Array.from(token.content); 587 | chars.forEach(function(_char) { 588 | return tokenArray.push( 589 | _extends({}, token, { 590 | content: _char, 591 | key: key++ 592 | }) 593 | ); 594 | }); 595 | }); 596 | } 597 | 598 | function setTokenFocus(tokens, focusColumns) { 599 | // Assumes that tokens are already splitted in columns 600 | // Return new token objects to avoid changing other steps tokens 601 | return tokens.map(function(token, i) { 602 | return _extends({}, token, { 603 | focus: focusColumns.includes(i) 604 | }); 605 | }); 606 | } 607 | 608 | exports.parseSteps = parseSteps; 609 | //# sourceMappingURL=parser.cjs.development.js.map 610 | -------------------------------------------------------------------------------- /rehype-waves/readme.md: -------------------------------------------------------------------------------- 1 | Rehype plugin for gatsby-theme-waves 2 | 3 | Features: 4 | 5 | - precalculate steps for 6 | -------------------------------------------------------------------------------- /rehype-waves/step-reader.js: -------------------------------------------------------------------------------- 1 | const { parse } = require("shell-quote"); 2 | 3 | module.exports.readStepFromElement = function(pre) { 4 | if (!pre.children || !pre.children[0]) { 5 | return null; 6 | } 7 | 8 | const codeElement = pre.children[0]; 9 | 10 | const { className, metastring } = codeElement.properties; 11 | const code = codeElement.children[0].value; 12 | 13 | return { 14 | code, 15 | lang: className[0].substring("language-".length), 16 | ...parseMetastring(metastring) 17 | }; 18 | }; 19 | 20 | function parseMetastring(metastring) { 21 | if (!metastring) { 22 | return {}; 23 | } 24 | 25 | const argv = parse(metastring); 26 | 27 | const result = {}; 28 | argv.forEach(arg => { 29 | if (!arg.includes("=")) { 30 | result.focus = arg; 31 | } else { 32 | const [key, value] = arg.split(/=(.*)/); 33 | result[key] = value; 34 | } 35 | }); 36 | return result; 37 | } 38 | -------------------------------------------------------------------------------- /rehype-waves/test.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const { toMatchFile } = require("jest-file-snapshot"); 3 | const compile = require("@mdx-js/mdx"); 4 | const plugin = require("./index"); 5 | 6 | expect.extend({ toMatchFile }); 7 | 8 | fs.readdirSync("__fixtures__/").forEach(filename => { 9 | test(filename, () => { 10 | const mdx = fs.readFileSync("__fixtures__/" + filename, "utf8"); 11 | expect(compile.sync(mdx, { rehypePlugins: [plugin] })).toMatchFile(); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /theme/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # dotenv environment variables file 55 | .env 56 | 57 | # gatsby files 58 | .cache/ 59 | public 60 | 61 | # Mac files 62 | .DS_Store 63 | 64 | # Yarn 65 | yarn-error.log 66 | .pnp/ 67 | .pnp.js 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | -------------------------------------------------------------------------------- /theme/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "lf", 3 | "semi": false, 4 | "singleQuote": false, 5 | "tabWidth": 2, 6 | "trailingComma": "es5" 7 | } 8 | -------------------------------------------------------------------------------- /theme/gatsby-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ["gatsby-plugin-theme-ui"], 3 | } 4 | -------------------------------------------------------------------------------- /theme/gatsby-node.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/gatsby-waves/43b088d266b079078a6d5c854493ba62931c6f13/theme/gatsby-node.js -------------------------------------------------------------------------------- /theme/index.js: -------------------------------------------------------------------------------- 1 | import * as codeThemes from "@code-surfer/standalone" 2 | export { default as CodeWave } from "./src/components/code-wave" 3 | export { default as ImageWave } from "./src/components/image-wave" 4 | export { codeThemes } 5 | -------------------------------------------------------------------------------- /theme/license: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Rodrigo Pombo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /theme/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-theme-waves", 3 | "description": "Bring scrollytelling to your mdx.", 4 | "author": "Rodrigo Pombo", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/pomber/gatsby-theme-waves.git" 8 | }, 9 | "version": "0.1.6", 10 | "main": "index.js", 11 | "license": "MIT", 12 | "peerDependencies": { 13 | "@emotion/core": "^10.0.14", 14 | "gatsby": "^2.13.24", 15 | "gatsby-plugin-theme-ui": "^0.2.2", 16 | "react": "^16.8.6", 17 | "react-dom": "^16.8.6", 18 | "theme-ui": "^0.2.2" 19 | }, 20 | "devDependencies": { 21 | "gatsby": "^2.13.24", 22 | "react": "^16.8.6", 23 | "react-dom": "^16.8.6" 24 | }, 25 | "dependencies": { 26 | "@code-surfer/standalone": "3.1.1", 27 | "@mdx-js/react": "^1.0.21", 28 | "rebound": "^0.1.0", 29 | "shell-quote": "^1.6.1", 30 | "use-spring": "^0.2.2" 31 | }, 32 | "keywords": [ 33 | "gatsby", 34 | "gatsby-theme", 35 | "gatsby-plugin", 36 | "code", 37 | "scrollytelling", 38 | "mdx", 39 | "blog" 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /theme/readme.md: -------------------------------------------------------------------------------- 1 | # Gatsby Theme Waves 2 | 3 | > Still experimental but you can give it a try 4 | 5 | Bring scrollytelling to your mdx. Animate code, images, charts, maps and more as you scroll. 6 | 7 | 13 | 14 | The MDX looks like this: 15 | 16 | ````md 17 | import { CodeWave } from "gatsby-theme-waves" 18 | 19 | 20 | 21 | ```py 22 | # some code 23 | ``` 24 | 25 | # Some markdown 26 | 27 | ```py 28 | # more code 29 | ``` 30 | 31 | More markdown 32 | 33 | > and more 34 | 35 | ```py 36 | # and more 37 | ``` 38 | 39 | - ok 40 | - that's enough 41 | 42 | 43 | ```` 44 | 45 | ## Installation 46 | 47 | You need a Gatsby site with MDX. For example, this is how you add gatsby-theme-waves to a site that uses [gatsby-theme-blog](https://www.npmjs.com/package/gatsby-theme-blog): 48 | 49 | 1. Install the theme (and `deepmerge` for merging the theme styles) 50 | 51 | ```sh 52 | npm install --save gatsby-theme-waves deepmerge 53 | ``` 54 | 55 | 2. Add the theme to your `gatsby-config.js` (at the end of the plugin list just in case) 56 | 57 | ```js 58 | module.exports = { 59 | plugins: [ 60 | "gatsby-theme-blog", 61 | "gatsby-theme-waves", // <-- add this 62 | ], 63 | } 64 | ``` 65 | 66 | 3. Merge the styles: create or edit `src/gatsby-plugin-theme-ui/index.js` 67 | 68 | ```js 69 | import wavesTheme from "gatsby-theme-waves/src/gatsby-plugin-theme-ui/index" 70 | import blogTheme from "gatsby-theme-blog/src/gatsby-plugin-theme-ui/index" 71 | import merge from "deepmerge" 72 | 73 | export default merge(blogTheme, wavesTheme) 74 | ``` 75 | 76 | 4) Import `CodeWave` and use it in any MDX file 77 | 78 | ````md 79 | import { CodeWave } from "gatsby-theme-waves" 80 | 81 | 82 | 83 | ```py 84 | # some code 85 | ``` 86 | 87 | # Some markdown 88 | 89 | ```py 90 | # more code 91 | ``` 92 | 93 | More markdown 94 | 95 | > and more 96 | 97 | ```py 98 | # and more 99 | ``` 100 | 101 | - ok 102 | - that's enough 103 | 104 | 105 | ```` 106 | 107 | Your set up should look like [this example](https://github.com/pomber/gatsby-theme-waves/tree/master/blog-demo). 108 | 109 | ### Code Blocks 110 | 111 | By default the lines that changed between two consecutive code blocks will be highlighted. You can change it to highlihgt the line (and columns) you want: 112 | 113 | ````md 114 | ```js 1:3,6 115 | // highlihgts line 1,2,3 and 6 116 | ``` 117 | 118 | ```js 5[1,3:6],8 119 | // highlihgts: 120 | // columns 1,3,4,5 and 6 from line 5 121 | // and line 8 122 | ``` 123 | ```` 124 | 125 | ## Coming Soon 126 | 127 | - Import code from files 128 | - Better custom code syntax highligthing using theme-ui 129 | - More waves 130 | - More docs 131 | -------------------------------------------------------------------------------- /theme/src/components/bar-scroller.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx } from "theme-ui" 3 | import { useSpring } from "use-spring" 4 | 5 | function Scroller({ steps, currentStep, progress, variant }) { 6 | const [fasterProgress] = useSpring(currentStep, { 7 | decimals: 3, 8 | stiffness: 52, 9 | damping: 14, 10 | mass: 0.1, 11 | }) 12 | 13 | const startBorder = Math.min(fasterProgress, progress) 14 | const endBorder = Math.max(fasterProgress, progress) 15 | 16 | const progressStyles = steps.map((_, i) => { 17 | const from = Math.max(startBorder - i, 0) 18 | const to = Math.min(endBorder + 1 - i, 1) 19 | 20 | if (to <= from) { 21 | return { top: "0%", bottom: "100%" } 22 | } else { 23 | const width = 3 / (1 + endBorder - startBorder) 24 | return { 25 | top: from * 100 + "%", 26 | bottom: 100 - to * 100 + "%", 27 | width, 28 | } 29 | } 30 | }) 31 | return ( 32 |
36 | {steps.map((step, i) => ( 37 |
43 |
47 | {step} 48 |
49 | ))} 50 |
51 | ) 52 | } 53 | 54 | export default Scroller 55 | -------------------------------------------------------------------------------- /theme/src/components/code-sticker.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx } from "theme-ui" 3 | import React from "react" 4 | import { CodeSurfer } from "@code-surfer/standalone" 5 | import { readStepFromElement } from "../stuff/step-reader" 6 | 7 | function CodeSticker({ steps: stepElements, progress, variant, parsedSteps }) { 8 | const steps = React.useMemo( 9 | () => 10 | parsedSteps 11 | ? undefined 12 | : stepElements.map(element => { 13 | const parsedStep = readStepFromElement(element) 14 | return parsedStep 15 | }), 16 | [] 17 | ) 18 | 19 | return ( 20 |
25 |
31 |
32 | 37 |
38 |
39 |
40 | ) 41 | } 42 | 43 | export default CodeSticker 44 | -------------------------------------------------------------------------------- /theme/src/components/code-wave.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx } from "theme-ui" 3 | import React from "react" 4 | import BarScroller from "./bar-scroller" 5 | import CodeSticker from "./code-sticker" 6 | import Wave from "./wave" 7 | 8 | /** 9 | * 10 | * There are two ways to use in MDX: 11 | * 12 | * 13 | * 14 | * 15 | * ```js 1:2 16 | * // some code 17 | * ``` 18 | * 19 | * ## some 20 | * 21 | * ## markdown 22 | * 23 | * ```js 24 | * // more code 25 | * ``` 26 | * 27 | * - more 28 | * - markdown 29 | * 30 | * 31 | * 32 | * 33 | * Or, using the output of rehype-waves: 34 | * 35 | * 36 | * 37 | * 38 | *
39 | * 40 | * ## some 41 | * 42 | * ## markdown 43 | * 44 | *
45 | * 46 | *
47 | * 48 | * - more 49 | * - markdown 50 | * 51 | *
52 | * 53 | *
54 | * 55 | * 56 | * 57 | */ 58 | 59 | function CodeWave(props) { 60 | const { parsedSteps } = props 61 | 62 | const childrenToColumns = children => { 63 | const kids = React.Children.toArray(children) 64 | if (parsedSteps) { 65 | return [[], React.Children.toArray(children)] 66 | } else { 67 | const columnCount = 2 68 | return toColumns(kids, columnCount) 69 | } 70 | } 71 | 72 | return ( 73 | 78 | ) 79 | } 80 | 81 | function toColumns(items, columnCount) { 82 | const columns = Array(columnCount) 83 | .fill() 84 | .map(() => []) 85 | 86 | items.forEach((item, i) => { 87 | const isCode = item.props && item.props.mdxType === "pre" 88 | if (isCode) { 89 | columns[0].push(item) 90 | columns[1].push(React.createElement("div", {}, [])) 91 | } else { 92 | const step = columns[0].length - 1 93 | columns[1][step].props.children.push(item) 94 | } 95 | }) 96 | 97 | return columns 98 | } 99 | 100 | export default CodeWave 101 | -------------------------------------------------------------------------------- /theme/src/components/image-sticker.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx } from "theme-ui" 3 | 4 | function ImageSticker({ progress, steps, variant }) { 5 | const currentStep = Math.round(progress) 6 | const prev = steps[currentStep - 1] 7 | const curr = steps[currentStep] 8 | const next = steps[currentStep + 1] 9 | 10 | return ( 11 |
12 |
13 |
21 | {prev && ( 22 |
27 | {prev} 28 |
29 | )} 30 |
35 | {curr} 36 |
37 | {next && ( 38 |
43 | {next} 44 |
45 | )} 46 |
54 |
55 |
56 | ) 57 | } 58 | 59 | export default ImageSticker 60 | -------------------------------------------------------------------------------- /theme/src/components/image-wave.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx } from "theme-ui" 3 | import React from "react" 4 | import OpacityScroller from "./opacity-scroller" 5 | import Wave from "./wave" 6 | import ImageSticker from "./image-sticker" 7 | 8 | function toColumns(items, columnCount) { 9 | const columns = Array(columnCount) 10 | .fill() 11 | .map(() => []) 12 | 13 | items.forEach((item, i) => { 14 | const isImg = 15 | item.props && 16 | item.props.mdxType === "p" && 17 | item.props.children && 18 | item.props.children.props && 19 | item.props.children.props.className === "gatsby-resp-image-wrapper" 20 | // console.log("item props", item.props, isImg) 21 | if (isImg) { 22 | const img = React.cloneElement( 23 | item.props.children.props.children[1].props.children[3], 24 | { style: { width: "100%", height: "100%", objectFit: "cover" } } 25 | ) 26 | columns[0].push(img) 27 | columns[1].push(React.createElement("div", {}, [])) 28 | } else { 29 | const step = columns[0].length - 1 30 | columns[1][step].props.children.push(item) 31 | } 32 | }) 33 | 34 | return columns 35 | } 36 | 37 | function ImageWave(props) { 38 | const childrenToColumns = children => { 39 | const items = React.Children.map(children, child => [child]) 40 | const columnCount = 2 41 | const columns = toColumns(items, columnCount) 42 | return columns 43 | } 44 | 45 | return ( 46 | 51 | ) 52 | } 53 | 54 | export default ImageWave 55 | -------------------------------------------------------------------------------- /theme/src/components/opacity-scroller.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx } from "theme-ui" 3 | 4 | function Scroller({ steps, progress, variant }) { 5 | return ( 6 |
12 | {steps.map((step, i) => ( 13 |
22 | {step} 23 |
24 | ))} 25 |
26 | ) 27 | } 28 | 29 | export default Scroller 30 | -------------------------------------------------------------------------------- /theme/src/components/wave.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx, useThemeUI } from "theme-ui" 3 | import React from "react" 4 | import { useSpring } from "use-spring" 5 | 6 | function getProgress(scroller, focusPoint) { 7 | const children = scroller.childNodes 8 | const middle = window.innerHeight * focusPoint 9 | let prevBottom = children[0].getBoundingClientRect().bottom 10 | for (let i = 1; i < children.length; i++) { 11 | const { top, bottom } = children[i].getBoundingClientRect() 12 | const breakpoint = (prevBottom + top) / 2 13 | if (middle < breakpoint) { 14 | return i - 1 15 | } 16 | prevBottom = bottom 17 | } 18 | return children.length - 1 19 | } 20 | 21 | function useFocusPoint(variant) { 22 | if (typeof window === "undefined") return false 23 | //TODO keep focus point in ref and update on window resize 24 | const { theme } = useThemeUI() 25 | const focus = theme.styles.waves[variant].focus || [0.7, 0.5] 26 | //TODO find out how to get default breakpoints from theme-ui 27 | const breakpoint = theme.breakpoints ? theme.breakpoints[0] : "40em" 28 | let mql = window.matchMedia(`(min-width: ${breakpoint})`) 29 | return mql.matches ? focus[1] : focus[0] 30 | } 31 | 32 | function useCurrentStep(ref, variant) { 33 | const [progress, setProgress] = React.useState(0) 34 | const focusPoint = useFocusPoint(variant) 35 | 36 | React.useEffect(() => { 37 | const scroller = ref.current.querySelector(".scroller") 38 | function onScroll() { 39 | const newProgress = getProgress(scroller, focusPoint) 40 | setProgress(newProgress) 41 | } 42 | document.addEventListener("scroll", onScroll) 43 | return () => { 44 | document.removeEventListener("scroll", onScroll) 45 | } 46 | }, []) 47 | 48 | return progress 49 | } 50 | 51 | function Wave({ 52 | children, 53 | variant = "default", 54 | columnComponents = [], 55 | childrenToStepColumns, 56 | ...rest 57 | }) { 58 | const ref = React.useRef() 59 | const currentStep = useCurrentStep(ref, variant) 60 | 61 | const [progress] = useSpring(currentStep, { 62 | decimals: 3, 63 | stiffness: 80, 64 | damping: 48, 65 | mass: 8, 66 | }) 67 | 68 | const columns = React.useMemo(() => { 69 | return childrenToStepColumns(children) 70 | }, []) 71 | 72 | return ( 73 |
74 | {columns.map((columnSteps, columnIndex) => { 75 | const Component = columnComponents[columnIndex] 76 | //TODO rename currentStep to currentStepIndex 77 | return ( 78 | 86 | ) 87 | })} 88 |
89 | ) 90 | } 91 | 92 | export default Wave 93 | -------------------------------------------------------------------------------- /theme/src/gatsby-plugin-theme-ui/index.js: -------------------------------------------------------------------------------- 1 | import waves from "./waves" 2 | 3 | /** 4 | * This theme uses `theme-ui` under the hood. 5 | * @see https://theme-ui.com/ 6 | * @see https://theme-ui.com/gatsby-plugin/ 7 | */ 8 | export default { 9 | styles: { 10 | waves, 11 | }, 12 | } 13 | -------------------------------------------------------------------------------- /theme/src/gatsby-plugin-theme-ui/waves.js: -------------------------------------------------------------------------------- 1 | export default { 2 | default: { 3 | Wave: { 4 | width: ["100%", "960px"], 5 | marginTop: "40px", 6 | marginLeft: [0, "calc(50% - 480px)"], 7 | marginBottom: "40px", 8 | position: "relative", 9 | display: ["block", "flex"], 10 | }, 11 | ScrollerContainer: { 12 | flex: 1, 13 | paddingLeft: [0, "50px"], 14 | paddingTop: ["50px", 0], 15 | }, 16 | ScrollerStep: { 17 | position: "relative", 18 | padding: [0, "0 10px"], 19 | minHeight: "250px", 20 | display: "flex", 21 | alignItems: "center", 22 | borderLeft: ["none", "3px solid transparent"], 23 | }, 24 | ScrollerProgress: { 25 | position: "absolute", 26 | left: ["-12px", "-3px"], 27 | backgroundColor: "primary", 28 | }, 29 | StickerContainer: { 30 | width: ["100vw", "50%"], 31 | marginLeft: ["calc(50% - 50vw)", 0], 32 | position: ["sticky", "static"], 33 | top: [0, "auto"], 34 | zIndex: [1, "auto"], 35 | height: ["50vh", "auto"], 36 | }, 37 | Sticker: { 38 | position: ["static", "sticky"], 39 | width: "100%", 40 | height: ["100%", "60vh"], 41 | top: ["auto", "20vh"], 42 | border: ["none", "1px solid"], 43 | borderColor: "secondary", 44 | }, 45 | // this is used to select the active scroller step 46 | // 0.5 selects the step that is at half the screen height 47 | // 0.7 the step that is at 70% the screen height 48 | focus: [0.7, 0.5], 49 | }, 50 | } 51 | -------------------------------------------------------------------------------- /theme/src/stuff/step-reader.js: -------------------------------------------------------------------------------- 1 | import { parse } from "shell-quote" 2 | 3 | export function readStepFromElement(element) { 4 | if (!element.props.children || !element.props.children.props) { 5 | return null 6 | } 7 | const { props } = element.props.children 8 | const className = props.className 9 | return { 10 | code: props.children, 11 | lang: className.substring("language-".length), 12 | ...parseMetastring(props.metastring), 13 | } 14 | } 15 | 16 | function parseMetastring(metastring) { 17 | if (!metastring) { 18 | return {} 19 | } 20 | 21 | const argv = parse(metastring) 22 | 23 | const result = {} 24 | argv.forEach(arg => { 25 | if (!arg.includes("=")) { 26 | result.focus = arg 27 | } else { 28 | const [key, value] = arg.split(/=(.*)/) 29 | result[key] = value 30 | } 31 | }) 32 | return result 33 | } 34 | --------------------------------------------------------------------------------