├── .github ├── blocks │ └── folder │ │ └── githubnext__blocks-examples__infinite-canvas-block │ │ ├── scripts.json │ │ └── src.json └── workflows │ └── diagram.yml ├── .gitignore ├── .nvmrc ├── .prettierrc ├── .vscode ├── launch.json └── settings.json ├── Makefile ├── README.md ├── config.json ├── diagram-test.svg ├── diagram.svg ├── docs ├── assets │ ├── global.css │ ├── normalize.css │ ├── pudding-fonts │ │ ├── national │ │ │ ├── National2NarrowWeb-Black.woff │ │ │ ├── National2NarrowWeb-Black.woff2 │ │ │ ├── National2NarrowWeb-Bold.woff │ │ │ ├── National2NarrowWeb-Bold.woff2 │ │ │ ├── National2NarrowWeb-Extralight.woff │ │ │ ├── National2NarrowWeb-Extralight.woff2 │ │ │ ├── National2NarrowWeb-Regular.woff │ │ │ ├── National2NarrowWeb-Regular.woff2 │ │ │ ├── National2Web-Bold.woff │ │ │ ├── National2Web-Bold.woff2 │ │ │ ├── National2Web-Regular.woff │ │ │ └── National2Web-Regular.woff2 │ │ └── tiempos │ │ │ ├── TiemposHeadlineWeb-Regular.woff │ │ │ ├── TiemposHeadlineWeb-Regular.woff2 │ │ │ ├── TiemposTextWeb-Bold.woff │ │ │ ├── TiemposTextWeb-Bold.woff2 │ │ │ ├── TiemposTextWeb-Regular.woff │ │ │ └── TiemposTextWeb-Regular.woff2 │ ├── reset.css │ ├── styles │ │ ├── font.css │ │ ├── global.css │ │ ├── normalize.css │ │ └── water.css │ ├── toast.png │ └── water.css ├── build │ ├── bundle.css │ ├── bundle.css.map │ ├── bundle.js │ ├── bundle.js.map │ └── main.js └── index.html ├── output-diagram.svg ├── package-lock.json ├── package.json ├── public ├── assets │ ├── favicon.svg │ ├── obama.png │ ├── pattern.svg │ ├── styles │ │ ├── font.css │ │ ├── global.css │ │ ├── normalize.css │ │ └── water.css │ ├── toast.png │ ├── worker-image.js │ └── worker.js ├── build │ ├── bundle.css │ └── bundle.js └── index.html ├── rollup.config-ssr.js ├── rollup.config.js ├── scripts ├── copy-template.js ├── export-processed.svg ├── export.svg ├── fetch-google.js ├── outline-svg.js └── pre-render.js ├── src ├── actions │ ├── .gitkeep │ ├── css.js │ └── inView.js ├── all-patterns.svg ├── components │ ├── App.svelte │ ├── Canvas.svelte │ ├── Controls.svelte │ ├── Meta.svelte │ ├── PatternPicker.svelte │ ├── Wrapper.svelte │ ├── helpers │ │ ├── Icon.svelte │ │ ├── Slider.Slide.svelte │ │ ├── Slider.svelte │ │ ├── Tap.svelte │ │ └── Window.svelte │ ├── patterns.js │ ├── patterns │ │ ├── a.svg │ │ ├── b.svg │ │ ├── c.svg │ │ ├── d.svg │ │ ├── e.svg │ │ ├── f.svg │ │ ├── g.svg │ │ ├── h.svg │ │ ├── i.svg │ │ ├── j.svg │ │ ├── k.svg │ │ ├── l.svg │ │ ├── m.svg │ │ ├── n.svg │ │ ├── named │ │ │ ├── asa-no-ha1.svg │ │ │ ├── asa-no-ha2.svg │ │ │ ├── asa-no-ha3.svg │ │ │ ├── asa-no-ha4.svg │ │ │ ├── asa-no-ha5.svg │ │ │ ├── kuruma1.svg │ │ │ ├── kuruma2.svg │ │ │ ├── kuruma3.svg │ │ │ ├── misc1.svg │ │ │ ├── misc2.svg │ │ │ ├── misc3.svg │ │ │ ├── misc4.svg │ │ │ ├── misc5.svg │ │ │ ├── misc6.svg │ │ │ ├── misc7.svg │ │ │ ├── rindo1.svg │ │ │ ├── rindo2.svg │ │ │ ├── rindo3.svg │ │ │ ├── sakura1.svg │ │ │ ├── sakura1b.svg │ │ │ ├── sakura2.svg │ │ │ ├── sakura3.svg │ │ │ └── sakura4.svg │ │ ├── o.svg │ │ ├── p.svg │ │ ├── q.svg │ │ ├── r.svg │ │ ├── s.svg │ │ ├── t.svg │ │ ├── u.svg │ │ ├── v.svg │ │ ├── w.svg │ │ ├── x.svg │ │ └── y.svg │ └── pudding │ │ ├── Footer.svelte │ │ └── Header.svelte ├── data │ └── demo │ │ ├── copy.json │ │ └── sample.csv ├── image-utils.js ├── main.js ├── stores │ ├── global.js │ ├── prefersReducedMotion.js │ ├── scrollY.js │ ├── timer.js │ └── viewport.js ├── svg │ └── pudding │ │ ├── logo.svg │ │ └── wordmark.svg ├── template.html ├── utils.js └── utils │ ├── mapToArray.js │ ├── move.js │ └── transformSvg.js ├── test.json ├── test.md └── yarn.lock /.github/blocks/folder/githubnext__blocks-examples__infinite-canvas-block/scripts.json: -------------------------------------------------------------------------------- 1 | { 2 | "items": { 3 | "0": { 4 | "id": 0, 5 | "type": "text", 6 | "text": "test1fgf", 7 | "position": [ 8 | 2400, 9 | 2450 10 | ], 11 | "dimensions": [ 12 | 200, 13 | 100 14 | ] 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /.github/blocks/folder/githubnext__blocks-examples__infinite-canvas-block/src.json: -------------------------------------------------------------------------------- 1 | { 2 | "items": { 3 | "0": { 4 | "id": 0, 5 | "type": "text", 6 | "text": "Start tkyping or grab a file", 7 | "position": [ 8 | 2400, 9 | 2450 10 | ], 11 | "dimensions": [ 12 | 200, 13 | 100 14 | ] 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /.github/workflows/diagram.yml: -------------------------------------------------------------------------------- 1 | name: Create diagram 2 | on: 3 | workflow_dispatch: {} 4 | push: 5 | branches: 6 | - master 7 | jobs: 8 | get_data: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout code 12 | uses: actions/checkout@master 13 | - name: Update diagram 14 | uses: githubocto/repo-visualizer@main 15 | with: 16 | excluded_paths: "docs,.vscode,.gitignore,.nvmrc,.prettierrc" 17 | commit_message: "Update diagram [skip ci]" 18 | excluded_globs: "scripts/**.*" 19 | output_file: "output-diagram.svg" 20 | artifact_name: "my-diagram" 21 | file_colors: '{"js":"#45aeb1"}' 22 | - name: Get artifact 23 | uses: actions/download-artifact@v2 24 | with: 25 | name: "my-diagram" 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | yarn-error.log 4 | .tmp 5 | ssr 6 | public/bundle/ -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 14.15.0 -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "svelteSortOrder": "scripts-markup-styles", 3 | "svelteStrictMode": true 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "pwa-node", 9 | "request": "launch", 10 | "name": "Clean svg", 11 | "skipFiles": [ 12 | "/**" 13 | ], 14 | "program": "${workspaceFolder}/scripts/outline-svg.js" 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.ignoreWords": [ 3 | "darknesses" 4 | ] 5 | } -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PHONY: github pudding 2 | 3 | github: 4 | rm -rf docs 5 | cp -r ssr docs 6 | git add -A 7 | git commit -m "update github pages" 8 | git push 9 | 10 | # aws-sync: 11 | # aws s3 sync ssr s3://pudding.cool/year/month/name --delete --cache-control 'max-age=31536000' 12 | 13 | # aws-cache: 14 | # aws cloudfront create-invalidation --distribution-id E13X38CRR4E04D --paths '/year/month/name*' 15 | 16 | # pudding: aws-sync aws-cache -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Svelte Starter 2 | 3 | ![Repo diagram test](./diagram-test.svg) 4 | 5 | ![Repo diagram](./diagram.svg) 6 | 7 | This [starter template](https://github.com/the-pudding/svelte-starter) aims for fast and easy web development with HMR, and pre-rendered HTML for optimal static hosting. 8 | 9 | _Please note: do not use or reproduce The Pudding logos or fonts without written permission._ 10 | 11 | #### Features 12 | 13 | - [HMR](https://github.com/rixo/svelte-hmr) for lightning fast development 14 | - [Feather Icons](https://github.com/feathericons/feather) for simple/easy svg icons 15 | - [ArchieML](http://archieml.org/) for micro-CMS powered by Google Docs and Sheets 16 | - [LayerCake](https://layercake.graphics/) enabled by default for chart 17 | - [Water.css](https://github.com/kognise/water.css) for default styling 18 | - Includes csv, json, and svg imports by default 19 | - Pre-renders HTML on deploy with content that is hydrated on load 20 | - Configured to make easy deploment to Github Pages 21 | 22 | ## Quickstart 23 | 24 | New school: just click the `Use this template` button above. 25 | 26 | Old school: 27 | 28 | ```bash 29 | npx degit the-pudding/svelte-starter my-project 30 | ``` 31 | 32 | Then in your local repo: 33 | 34 | ```bash 35 | npm install 36 | npm run build 37 | ``` 38 | 39 | ## Development 40 | 41 | To start the dev server: 42 | 43 | ```bash 44 | npm run dev 45 | ``` 46 | 47 | Modify content in `src` and `public/assets`. 48 | test 49 | 50 | ## Deploy 51 | 52 | ```bash 53 | npm run deploy 54 | ``` 55 | 56 | This generates a directory called `ssr` with the server-side rendered static-hostable app. 57 | 58 | If deploying to github pages: 59 | 60 | ```bash 61 | make github 62 | ``` 63 | 64 | ## Style 65 | 66 | There are a few stylesheets included by default in `template.html`. Modify `global.css` variables to make changes to `water.css` defaults. 67 | 68 | You can use SCSS or another CSS preprocessor by installing the module (eg. `node-sass`) and including the property in the svelte-preprocess in the rollup config files. 69 | 70 | ## Google Docs and Sheets 71 | 72 | - Create a Google Doc or Sheet 73 | - Click `Share` button -> advanced -> Change... -> to "Anyone with this link" 74 | - In the address bar, grab the ID - eg. ...com/document/d/**1IiA5a5iCjbjOYvZVgPcjGzMy5PyfCzpPF-LnQdCdFI0**/edit 75 | - paste in the ID above into `config.json`, and set the filepath to where you want the file saved 76 | - If you want to do a Google Sheet, be sure to include the `gid` value in the url as well 77 | 78 | Running `npm run gdoc` at any point (even in new tab while server is running) will fetch the latest from all Docs and Sheets. 79 | 80 | ## Pre-loaded helpers 81 | 82 | ### Helper Components 83 | 84 | Located in `src/components/helpers`. 85 | 86 | - `Window.svelte`: A wrapper around svelte:window that automatically debounces resize and throttles scroll, storing `innerHeight`, `innerWidth`, and `scrollY` as global stores. 87 | - `Icon.svelte`: Simple integration with Feather Icons. 88 | - `Slider.svelte (and Slider.Slide.svelte)`: A slider widget, especially useful for swipe/slide stories. 89 | - `Tap.svelte`: Edge-of-screen tapping library, designed to integrate with slider. 90 | 91 | ### Pudding Components 92 | 93 | Located in `src/components/pudding`. 94 | 95 | - `Footer.svelte`: Pudding recirculation and social links. 96 | - `Header.svelte`: Pudding logo. 97 | 98 | ### Actions 99 | 100 | Located in `src/actions`. 101 | 102 | - `inView.js`: detect when an element enters or exits the viewport. 103 | - `css.js`: dynmically change the value of a CSS variable. 104 | 105 | ### Utils 106 | 107 | Located in `src/utils/`. 108 | 109 | - `mapToArray.js`: Convenience function to convert maps (generated from d3 group and rollup) to iterable array of objects. 110 | - `move.js`: transform translate function shorthand. 111 | 112 | ### Preset Stores 113 | 114 | These are located in `src/stores`, to include them do this (replacing `name`): 115 | 116 | ```js 117 | import name from "../stores/name.js"; 118 | ``` 119 | 120 | - `prefersReducedMotion`: returns a boolean if the user has this CSS media query enabled or not. 121 | 122 | - `viewport`: returns an object `{ width, height }` of the viewport dimensions. It is debounced for performance. 123 | 124 | - `scrollY`: returns an number window vertical scroll position. It is throttled using rAF for performance. 125 | 126 | - `timer`: returns an object { timer, elapsed }. `timer` has 5 methods (start, stop, toggle, set, reset) and `elapsed` is a store that is the number of ms. 127 | 128 | ### Utils 129 | 130 | `transformSvg.js`: this custom transition lets you apply an svg transform property with the in/out svelte transition. Parameters (with defaults): 131 | 132 | ```js 133 | { 134 | target: "", // string: transform properties [required] 135 | delay: 0, // number: ms 136 | duration: 250, // number: in ms 137 | easing: linear, // function: svelte easing function 138 | relative: false, // boolean: adds target onto pre-existing transform 139 | opacity: false // boolean: to fade in/out as well 140 | } 141 | ``` 142 | 143 | **Usage** 144 | 145 | ```svelte 146 | 147 | ``` 148 | 149 | ## Notes 150 | 151 | Any @html tags, e.g., `{@html user}` must be the child of a dom element so they can be properly hydrated. 152 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "google": [ 3 | { 4 | "id": "1352iFuTSDDFPNAXBbOaEXkF8mCdjPu6B43hpUF2P3C4", 5 | "filepath": "src/data/doc.json" 6 | }, 7 | { 8 | "id": "1te65h_nywgXVAzvV-9E5fmHGblcKvctf_cNZgeam9Tk", 9 | "gid": "0", 10 | "filepath": "src/data/sheet.csv" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /docs/assets/global.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --sans: "National 2 Web", Helvetica, Arial, sans-serif; 3 | --serif: "Tiempos Text Web", Georgia, Times, serif; 4 | --mono: Menlo, Consolas, Monaco, "Courier New", monospace; 5 | 6 | --z-bottom: -100; 7 | --z-middle: 0; 8 | --z-top: 100; 9 | --z-overlay: 1000; 10 | 11 | --black: #000; 12 | --off-black: #282828; 13 | --gray-dark: #5b5b5b; 14 | --gray: #949494; 15 | --gray-light: #c9c9c9; 16 | --off-white: #ebeaee; 17 | --white: #fff; 18 | --purple: #a239ca; 19 | --blue: #4717f6; 20 | --green: #34a29e; 21 | --red: #ff533d; 22 | --yellow: #e5e338; 23 | 24 | /* water.css */ 25 | 26 | --body-font: var(--serif); 27 | --background-body: var(--white); 28 | --background: var(--off-white); 29 | --background-alt: var(--off-white); 30 | --selection: var(--gray); 31 | --text-main: var(--off-black); 32 | --links: var(--purple); 33 | --focus: var(--green); 34 | --border: var(--gray-light); 35 | --animation-duration: 0.1s; 36 | --button-hover: var(--gray-light); 37 | --scrollbar-thumb: color-mod(var(--button-hover) lightness(-3%)); 38 | --scrollbar-thumb-hover: color-mod(var(--button-hover) lightness(-10%)); 39 | --form-placeholder: var(--gray-dark); 40 | --form-font: var(--sans); 41 | --form-text: var(--gray-dark); 42 | --input-thumb: var(--gray-dark); 43 | --highlight: var(--yellow); 44 | } 45 | 46 | .skip-to-main { 47 | border: none; 48 | width: 1px; 49 | height: 1px; 50 | overflow: hidden; 51 | position: absolute; 52 | } 53 | 54 | .skip-to-main:focus { 55 | width: auto; 56 | height: auto; 57 | padding: 0.5em; 58 | z-index: 1000; 59 | } 60 | 61 | /* pudding */ 62 | .wordmark svg path { 63 | fill: currentColor; 64 | } 65 | 66 | /* demo */ 67 | #demo svg { 68 | width: 1em; 69 | vertical-align: middle; 70 | } 71 | -------------------------------------------------------------------------------- /docs/assets/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | /* Document 4 | ========================================================================== */ 5 | 6 | /** 7 | * 1. Correct the line height in all browsers. 8 | * 2. Prevent adjustments of font size after orientation changes in iOS. 9 | */ 10 | 11 | html { 12 | line-height: 1.15; /* 1 */ 13 | -webkit-text-size-adjust: 100%; /* 2 */ 14 | } 15 | 16 | /* Sections 17 | ========================================================================== */ 18 | 19 | /** 20 | * Remove the margin in all browsers. 21 | */ 22 | 23 | body { 24 | margin: 0; 25 | } 26 | 27 | /** 28 | * Render the `main` element consistently in IE. 29 | */ 30 | 31 | main { 32 | display: block; 33 | } 34 | 35 | /** 36 | * Correct the font size and margin on `h1` elements within `section` and 37 | * `article` contexts in Chrome, Firefox, and Safari. 38 | */ 39 | 40 | h1 { 41 | font-size: 2em; 42 | margin: 0.67em 0; 43 | } 44 | 45 | /* Grouping content 46 | ========================================================================== */ 47 | 48 | /** 49 | * 1. Add the correct box sizing in Firefox. 50 | * 2. Show the overflow in Edge and IE. 51 | */ 52 | 53 | hr { 54 | box-sizing: content-box; /* 1 */ 55 | height: 0; /* 1 */ 56 | overflow: visible; /* 2 */ 57 | } 58 | 59 | /** 60 | * 1. Correct the inheritance and scaling of font size in all browsers. 61 | * 2. Correct the odd `em` font sizing in all browsers. 62 | */ 63 | 64 | pre { 65 | font-family: monospace, monospace; /* 1 */ 66 | font-size: 1em; /* 2 */ 67 | } 68 | 69 | /* Text-level semantics 70 | ========================================================================== */ 71 | 72 | /** 73 | * Remove the gray background on active links in IE 10. 74 | */ 75 | 76 | a { 77 | background-color: transparent; 78 | } 79 | 80 | /** 81 | * 1. Remove the bottom border in Chrome 57- 82 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. 83 | */ 84 | 85 | abbr[title] { 86 | border-bottom: none; /* 1 */ 87 | text-decoration: underline; /* 2 */ 88 | text-decoration: underline dotted; /* 2 */ 89 | } 90 | 91 | /** 92 | * Add the correct font weight in Chrome, Edge, and Safari. 93 | */ 94 | 95 | b, 96 | strong { 97 | font-weight: bolder; 98 | } 99 | 100 | /** 101 | * 1. Correct the inheritance and scaling of font size in all browsers. 102 | * 2. Correct the odd `em` font sizing in all browsers. 103 | */ 104 | 105 | code, 106 | kbd, 107 | samp { 108 | font-family: monospace, monospace; /* 1 */ 109 | font-size: 1em; /* 2 */ 110 | } 111 | 112 | /** 113 | * Add the correct font size in all browsers. 114 | */ 115 | 116 | small { 117 | font-size: 80%; 118 | } 119 | 120 | /** 121 | * Prevent `sub` and `sup` elements from affecting the line height in 122 | * all browsers. 123 | */ 124 | 125 | sub, 126 | sup { 127 | font-size: 75%; 128 | line-height: 0; 129 | position: relative; 130 | vertical-align: baseline; 131 | } 132 | 133 | sub { 134 | bottom: -0.25em; 135 | } 136 | 137 | sup { 138 | top: -0.5em; 139 | } 140 | 141 | /* Embedded content 142 | ========================================================================== */ 143 | 144 | /** 145 | * Remove the border on images inside links in IE 10. 146 | */ 147 | 148 | img { 149 | border-style: none; 150 | } 151 | 152 | /* Forms 153 | ========================================================================== */ 154 | 155 | /** 156 | * 1. Change the font styles in all browsers. 157 | * 2. Remove the margin in Firefox and Safari. 158 | */ 159 | 160 | button, 161 | input, 162 | optgroup, 163 | select, 164 | textarea { 165 | font-family: inherit; /* 1 */ 166 | font-size: 100%; /* 1 */ 167 | line-height: 1.15; /* 1 */ 168 | margin: 0; /* 2 */ 169 | } 170 | 171 | /** 172 | * Show the overflow in IE. 173 | * 1. Show the overflow in Edge. 174 | */ 175 | 176 | button, 177 | input { /* 1 */ 178 | overflow: visible; 179 | } 180 | 181 | /** 182 | * Remove the inheritance of text transform in Edge, Firefox, and IE. 183 | * 1. Remove the inheritance of text transform in Firefox. 184 | */ 185 | 186 | button, 187 | select { /* 1 */ 188 | text-transform: none; 189 | } 190 | 191 | /** 192 | * Correct the inability to style clickable types in iOS and Safari. 193 | */ 194 | 195 | button, 196 | [type="button"], 197 | [type="reset"], 198 | [type="submit"] { 199 | -webkit-appearance: button; 200 | } 201 | 202 | /** 203 | * Remove the inner border and padding in Firefox. 204 | */ 205 | 206 | button::-moz-focus-inner, 207 | [type="button"]::-moz-focus-inner, 208 | [type="reset"]::-moz-focus-inner, 209 | [type="submit"]::-moz-focus-inner { 210 | border-style: none; 211 | padding: 0; 212 | } 213 | 214 | /** 215 | * Restore the focus styles unset by the previous rule. 216 | */ 217 | 218 | button:-moz-focusring, 219 | [type="button"]:-moz-focusring, 220 | [type="reset"]:-moz-focusring, 221 | [type="submit"]:-moz-focusring { 222 | outline: 1px dotted ButtonText; 223 | } 224 | 225 | /** 226 | * Correct the padding in Firefox. 227 | */ 228 | 229 | fieldset { 230 | padding: 0.35em 0.75em 0.625em; 231 | } 232 | 233 | /** 234 | * 1. Correct the text wrapping in Edge and IE. 235 | * 2. Correct the color inheritance from `fieldset` elements in IE. 236 | * 3. Remove the padding so developers are not caught out when they zero out 237 | * `fieldset` elements in all browsers. 238 | */ 239 | 240 | legend { 241 | box-sizing: border-box; /* 1 */ 242 | color: inherit; /* 2 */ 243 | display: table; /* 1 */ 244 | max-width: 100%; /* 1 */ 245 | padding: 0; /* 3 */ 246 | white-space: normal; /* 1 */ 247 | } 248 | 249 | /** 250 | * Add the correct vertical alignment in Chrome, Firefox, and Opera. 251 | */ 252 | 253 | progress { 254 | vertical-align: baseline; 255 | } 256 | 257 | /** 258 | * Remove the default vertical scrollbar in IE 10+. 259 | */ 260 | 261 | textarea { 262 | overflow: auto; 263 | } 264 | 265 | /** 266 | * 1. Add the correct box sizing in IE 10. 267 | * 2. Remove the padding in IE 10. 268 | */ 269 | 270 | [type="checkbox"], 271 | [type="radio"] { 272 | box-sizing: border-box; /* 1 */ 273 | padding: 0; /* 2 */ 274 | } 275 | 276 | /** 277 | * Correct the cursor style of increment and decrement buttons in Chrome. 278 | */ 279 | 280 | [type="number"]::-webkit-inner-spin-button, 281 | [type="number"]::-webkit-outer-spin-button { 282 | height: auto; 283 | } 284 | 285 | /** 286 | * 1. Correct the odd appearance in Chrome and Safari. 287 | * 2. Correct the outline style in Safari. 288 | */ 289 | 290 | [type="search"] { 291 | -webkit-appearance: textfield; /* 1 */ 292 | outline-offset: -2px; /* 2 */ 293 | } 294 | 295 | /** 296 | * Remove the inner padding in Chrome and Safari on macOS. 297 | */ 298 | 299 | [type="search"]::-webkit-search-decoration { 300 | -webkit-appearance: none; 301 | } 302 | 303 | /** 304 | * 1. Correct the inability to style clickable types in iOS and Safari. 305 | * 2. Change font properties to `inherit` in Safari. 306 | */ 307 | 308 | ::-webkit-file-upload-button { 309 | -webkit-appearance: button; /* 1 */ 310 | font: inherit; /* 2 */ 311 | } 312 | 313 | /* Interactive 314 | ========================================================================== */ 315 | 316 | /* 317 | * Add the correct display in Edge, IE 10+, and Firefox. 318 | */ 319 | 320 | details { 321 | display: block; 322 | } 323 | 324 | /* 325 | * Add the correct display in all browsers. 326 | */ 327 | 328 | summary { 329 | display: list-item; 330 | } 331 | 332 | /* Misc 333 | ========================================================================== */ 334 | 335 | /** 336 | * Add the correct display in IE 10+. 337 | */ 338 | 339 | template { 340 | display: none; 341 | } 342 | 343 | /** 344 | * Add the correct display in IE 10. 345 | */ 346 | 347 | [hidden] { 348 | display: none; 349 | } 350 | 351 | 352 | 353 | /*! https://github.com/a11yproject/a11yproject.com/blob/main/src/css/base/_resets.scss */ 354 | *, 355 | *::before, 356 | *::after { 357 | box-sizing: border-box; 358 | margin: 0; 359 | padding: 0; 360 | vertical-align: baseline; 361 | } 362 | 363 | /* Removes borders from linked images */ 364 | a img { 365 | border: none; 366 | } 367 | 368 | 369 | b, 370 | strong { 371 | font-weight: 700; 372 | } 373 | 374 | button, 375 | input[type="button"] { 376 | border: 0; 377 | } 378 | 379 | 380 | em, 381 | cite, 382 | i { 383 | font-style: italic; 384 | } 385 | 386 | img, 387 | figure, 388 | picture { 389 | border: 0; 390 | display: block; 391 | height: auto; 392 | max-width: 100%; 393 | } 394 | 395 | h1, 396 | h2, 397 | h3, 398 | h4, 399 | h5, 400 | h6 { 401 | font-weight: 500; 402 | } 403 | 404 | sub { 405 | text-transform: lowercase; 406 | font-size: inherit; 407 | font-variant-position: sub; 408 | } 409 | 410 | sup { 411 | text-transform: lowercase; 412 | font-variant-position: super; 413 | } 414 | 415 | textarea { 416 | overflow: auto; 417 | resize: vertical; 418 | } -------------------------------------------------------------------------------- /docs/assets/pudding-fonts/national/National2NarrowWeb-Black.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/docs/assets/pudding-fonts/national/National2NarrowWeb-Black.woff -------------------------------------------------------------------------------- /docs/assets/pudding-fonts/national/National2NarrowWeb-Black.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/docs/assets/pudding-fonts/national/National2NarrowWeb-Black.woff2 -------------------------------------------------------------------------------- /docs/assets/pudding-fonts/national/National2NarrowWeb-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/docs/assets/pudding-fonts/national/National2NarrowWeb-Bold.woff -------------------------------------------------------------------------------- /docs/assets/pudding-fonts/national/National2NarrowWeb-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/docs/assets/pudding-fonts/national/National2NarrowWeb-Bold.woff2 -------------------------------------------------------------------------------- /docs/assets/pudding-fonts/national/National2NarrowWeb-Extralight.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/docs/assets/pudding-fonts/national/National2NarrowWeb-Extralight.woff -------------------------------------------------------------------------------- /docs/assets/pudding-fonts/national/National2NarrowWeb-Extralight.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/docs/assets/pudding-fonts/national/National2NarrowWeb-Extralight.woff2 -------------------------------------------------------------------------------- /docs/assets/pudding-fonts/national/National2NarrowWeb-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/docs/assets/pudding-fonts/national/National2NarrowWeb-Regular.woff -------------------------------------------------------------------------------- /docs/assets/pudding-fonts/national/National2NarrowWeb-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/docs/assets/pudding-fonts/national/National2NarrowWeb-Regular.woff2 -------------------------------------------------------------------------------- /docs/assets/pudding-fonts/national/National2Web-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/docs/assets/pudding-fonts/national/National2Web-Bold.woff -------------------------------------------------------------------------------- /docs/assets/pudding-fonts/national/National2Web-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/docs/assets/pudding-fonts/national/National2Web-Bold.woff2 -------------------------------------------------------------------------------- /docs/assets/pudding-fonts/national/National2Web-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/docs/assets/pudding-fonts/national/National2Web-Regular.woff -------------------------------------------------------------------------------- /docs/assets/pudding-fonts/national/National2Web-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/docs/assets/pudding-fonts/national/National2Web-Regular.woff2 -------------------------------------------------------------------------------- /docs/assets/pudding-fonts/tiempos/TiemposHeadlineWeb-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/docs/assets/pudding-fonts/tiempos/TiemposHeadlineWeb-Regular.woff -------------------------------------------------------------------------------- /docs/assets/pudding-fonts/tiempos/TiemposHeadlineWeb-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/docs/assets/pudding-fonts/tiempos/TiemposHeadlineWeb-Regular.woff2 -------------------------------------------------------------------------------- /docs/assets/pudding-fonts/tiempos/TiemposTextWeb-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/docs/assets/pudding-fonts/tiempos/TiemposTextWeb-Bold.woff -------------------------------------------------------------------------------- /docs/assets/pudding-fonts/tiempos/TiemposTextWeb-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/docs/assets/pudding-fonts/tiempos/TiemposTextWeb-Bold.woff2 -------------------------------------------------------------------------------- /docs/assets/pudding-fonts/tiempos/TiemposTextWeb-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/docs/assets/pudding-fonts/tiempos/TiemposTextWeb-Regular.woff -------------------------------------------------------------------------------- /docs/assets/pudding-fonts/tiempos/TiemposTextWeb-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/docs/assets/pudding-fonts/tiempos/TiemposTextWeb-Regular.woff2 -------------------------------------------------------------------------------- /docs/assets/reset.css: -------------------------------------------------------------------------------- 1 | * { 2 | -moz-box-sizing: border-box; 3 | box-sizing: border-box; 4 | } 5 | html, 6 | body, 7 | div, 8 | span, 9 | applet, 10 | object, 11 | iframe, 12 | h1, 13 | h2, 14 | h3, 15 | h4, 16 | h5, 17 | h6, 18 | p, 19 | blockquote, 20 | pre, 21 | a, 22 | abbr, 23 | acronym, 24 | address, 25 | big, 26 | cite, 27 | code, 28 | del, 29 | dfn, 30 | em, 31 | img, 32 | ins, 33 | kbd, 34 | q, 35 | s, 36 | samp, 37 | small, 38 | strike, 39 | strong, 40 | sub, 41 | sup, 42 | tt, 43 | var, 44 | b, 45 | u, 46 | i, 47 | center, 48 | dl, 49 | dt, 50 | dd, 51 | ol, 52 | ul, 53 | li, 54 | fieldset, 55 | form, 56 | label, 57 | legend, 58 | table, 59 | caption, 60 | tbody, 61 | tfoot, 62 | thead, 63 | tr, 64 | th, 65 | td, 66 | article, 67 | aside, 68 | canvas, 69 | details, 70 | embed, 71 | figure, 72 | figcaption, 73 | footer, 74 | header, 75 | hgroup, 76 | menu, 77 | nav, 78 | output, 79 | ruby, 80 | section, 81 | summary, 82 | time, 83 | mark, 84 | audio, 85 | video { 86 | margin: 0; 87 | padding: 0; 88 | border: 0; 89 | font-size: 100%; 90 | font: inherit; 91 | vertical-align: baseline; 92 | } 93 | article, 94 | aside, 95 | details, 96 | figcaption, 97 | figure, 98 | footer, 99 | header, 100 | hgroup, 101 | main, 102 | menu, 103 | nav, 104 | section { 105 | display: block; 106 | } 107 | a img { 108 | border: none; 109 | } 110 | blockquote { 111 | quotes: none; 112 | } 113 | blockquote:before, 114 | blockquote:after { 115 | content: ""; 116 | content: none; 117 | } 118 | table { 119 | border-collapse: collapse; 120 | border-spacing: 0; 121 | } 122 | caption, 123 | th, 124 | td { 125 | text-align: left; 126 | font-weight: normal; 127 | vertical-align: middle; 128 | } 129 | -------------------------------------------------------------------------------- /docs/assets/styles/font.css: -------------------------------------------------------------------------------- 1 | /* 2 | This font software is the property of Commercial Type. 3 | 4 | You may not modify the font software, use it on another website, or install it on a computer. 5 | 6 | License information is available at http://commercialtype.com/eula 7 | For more information please visit Commercial Type at http://commercialtype.com or email us at info[at]commercialtype.com 8 | 9 | Copyright (C) 2017 Schwartzco Inc. 10 | License: 1704-GNCLGK 11 | */ 12 | 13 | /* 14 | ******************** 15 | National 16 | ******************** 17 | */ 18 | 19 | @font-face { 20 | font-family: 'National 2 Web'; 21 | src: url('../pudding-fonts/national/National2Web-Regular.woff2') format('woff2'), 22 | url('../pudding-fonts/national/National2Web-Regular.woff') format('woff'); 23 | font-weight: 500; 24 | font-style: normal; 25 | font-stretch: normal; 26 | font-display: swap; 27 | } 28 | 29 | @font-face { 30 | font-family: 'National 2 Web'; 31 | src: url('../pudding-fonts/national/National2Web-Bold.woff2') format('woff2'), 32 | url('../pudding-fonts/national/National2Web-Bold.woff') format('woff'); 33 | font-weight: 700; 34 | font-style: normal; 35 | font-stretch: normal; 36 | font-display: swap; 37 | } 38 | 39 | /* 40 | ******************** 41 | National Narrow 42 | ******************** 43 | */ 44 | 45 | /* 46 | @font-face { 47 | font-family: 'National 2 Narrow Web'; 48 | src: url('../pudding-fonts/national/National2NarrowWeb-Extralight.woff2') format('woff2'), 49 | url('../pudding-fonts/national/National2NarrowWeb-Extralight.woff') format('woff'); 50 | font-weight: 200; 51 | font-style: normal; 52 | font-stretch: normal; 53 | font-display: swap; 54 | } 55 | 56 | @font-face { 57 | font-family: 'National 2 Narrow Web'; 58 | src: url('../pudding-fonts/national/National2NarrowWeb-Regular.woff2') format('woff2'), 59 | url('../pudding-fonts/national/National2NarrowWeb-Regular.woff') format('woff'); 60 | font-weight: 500; 61 | font-style: normal; 62 | font-stretch: normal; 63 | font-display: swap; 64 | } 65 | 66 | @font-face { 67 | font-family: 'National 2 Narrow Web'; 68 | src: url('../pudding-fonts/national/National2NarrowWeb-Bold.woff2') format('woff2'), 69 | url('../pudding-fonts/national/National2NarrowWeb-Bold.woff') format('woff'); 70 | font-weight: 700; 71 | font-style: normal; 72 | font-stretch: normal; 73 | font-display: swap; 74 | } 75 | 76 | /* 77 | @font-face { 78 | font-family: 'National 2 Narrow Web'; 79 | src: url('../pudding-fonts/national/National2NarrowWeb-Black.woff2') format('woff2'), 80 | url('../pudding-fonts/national/National2NarrowWeb-Black.woff') format('woff'); 81 | font-weight: 900; 82 | font-style: normal; 83 | font-stretch: normal; 84 | font-display: swap; 85 | } 86 | */ 87 | 88 | /* 89 | ******************** 90 | Tiempos Text 91 | ******************** 92 | */ 93 | 94 | @font-face { 95 | font-family: 'Tiempos Text Web'; 96 | src: url('../pudding-fonts/tiempos/TiemposTextWeb-Regular.woff2') format('woff2'), 97 | url('../pudding-fonts/tiempos/TiemposTextWeb-Regular.woff') format('woff'); 98 | font-weight: 500; 99 | font-style: normal; 100 | font-stretch: normal; 101 | font-display: swap; 102 | } 103 | 104 | @font-face { 105 | font-family: 'Tiempos Text Web'; 106 | src: url('../pudding-fonts/tiempos/TiemposTextWeb-Bold.woff2') format('woff2'), 107 | url('../pudding-fonts/tiempos/TiemposTextWeb-Bold.woff') format('woff'); 108 | font-weight: 700; 109 | font-style: normal; 110 | font-stretch: normal; 111 | font-display: swap; 112 | } 113 | 114 | /* 115 | ******************** 116 | Tiempos Headline 117 | ******************** 118 | */ 119 | 120 | /* 121 | @font-face { 122 | font-family: 'Tiempos Headline Web'; 123 | src: url('../pudding-fonts/tiempos/TiemposHeadlineWeb-Regular.woff2') format('woff2'), 124 | url('../pudding-fonts/tiempos/TiemposHeadlineWeb-Regular.woff') format('woff'); 125 | font-weight: 500; 126 | font-style: normal; 127 | font-stretch: normal; 128 | font-display: swap; 129 | } 130 | */ -------------------------------------------------------------------------------- /docs/assets/styles/global.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --sans: "National 2 Web", Helvetica, Arial, sans-serif; 3 | --serif: "Tiempos Text Web", Georgia, Times, serif; 4 | --mono: Menlo, Consolas, Monaco, "Courier New", monospace; 5 | 6 | --z-bottom: -100; 7 | --z-middle: 0; 8 | --z-top: 100; 9 | --z-overlay: 1000; 10 | 11 | --black: #000; 12 | --off-black: #282828; 13 | --gray-dark: #5b5b5b; 14 | --gray: #949494; 15 | --gray-light: #c9c9c9; 16 | --off-white: #f0f0f0; 17 | --white: #fff; 18 | --purple: #a239ca; 19 | --blue: #4717f6; 20 | --green: #34a29e; 21 | --red: #ff533d; 22 | --yellow: #e5e338; 23 | 24 | --bg: var(--white); 25 | --fg: var(--off-black); 26 | --default: var(--gray-light); 27 | --primary: var(--red); 28 | --secondary: var(--green); 29 | 30 | /* water.css */ 31 | 32 | --body-font: var(--sans); 33 | --background-body: var(--white); 34 | --background-ui: var(--off-white); 35 | --background-alt: var(--off-white); 36 | --selection: var(--gray); 37 | --text-main: var(--off-black); 38 | --links: var(--purple); 39 | --focus: var(--green); 40 | --border: var(--gray-light); 41 | --animation-duration: 0.1s; 42 | --button-hover: var(--gray-light); 43 | --scrollbar-thumb: var(--gray-light); 44 | --scrollbar-thumb-hover: var(--gray-dark); 45 | --form-placeholder: var(--gray-dark); 46 | --form-font: var(--sans); 47 | --form-text: var(--gray-dark); 48 | --input-thumb: var(--gray-dark); 49 | --highlight: var(--yellow); 50 | } 51 | 52 | .skip-to-main { 53 | border: none; 54 | width: 1px; 55 | height: 1px; 56 | overflow: hidden; 57 | position: absolute; 58 | } 59 | 60 | .skip-to-main:focus { 61 | width: auto; 62 | height: auto; 63 | padding: 0.5em; 64 | z-index: 1000; 65 | } 66 | 67 | /* pudding */ 68 | .wordmark svg path { 69 | fill: currentColor; 70 | } 71 | 72 | /* demo */ 73 | #demo svg { 74 | width: 1em; 75 | vertical-align: middle; 76 | } -------------------------------------------------------------------------------- /docs/assets/styles/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | /* Document 4 | ========================================================================== */ 5 | 6 | /** 7 | * 1. Correct the line height in all browsers. 8 | * 2. Prevent adjustments of font size after orientation changes in iOS. 9 | */ 10 | 11 | html { 12 | line-height: 1.15; /* 1 */ 13 | -webkit-text-size-adjust: 100%; /* 2 */ 14 | } 15 | 16 | /* Sections 17 | ========================================================================== */ 18 | 19 | /** 20 | * Remove the margin in all browsers. 21 | */ 22 | 23 | body { 24 | margin: 0; 25 | } 26 | 27 | /** 28 | * Render the `main` element consistently in IE. 29 | */ 30 | 31 | main { 32 | display: block; 33 | } 34 | 35 | /** 36 | * Correct the font size and margin on `h1` elements within `section` and 37 | * `article` contexts in Chrome, Firefox, and Safari. 38 | */ 39 | 40 | h1 { 41 | font-size: 2em; 42 | margin: 0.67em 0; 43 | } 44 | 45 | /* Grouping content 46 | ========================================================================== */ 47 | 48 | /** 49 | * 1. Add the correct box sizing in Firefox. 50 | * 2. Show the overflow in Edge and IE. 51 | */ 52 | 53 | hr { 54 | box-sizing: content-box; /* 1 */ 55 | height: 0; /* 1 */ 56 | overflow: visible; /* 2 */ 57 | } 58 | 59 | /** 60 | * 1. Correct the inheritance and scaling of font size in all browsers. 61 | * 2. Correct the odd `em` font sizing in all browsers. 62 | */ 63 | 64 | pre { 65 | font-family: monospace, monospace; /* 1 */ 66 | font-size: 1em; /* 2 */ 67 | } 68 | 69 | /* Text-level semantics 70 | ========================================================================== */ 71 | 72 | /** 73 | * Remove the gray background on active links in IE 10. 74 | */ 75 | 76 | a { 77 | background-color: transparent; 78 | } 79 | 80 | /** 81 | * 1. Remove the bottom border in Chrome 57- 82 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. 83 | */ 84 | 85 | abbr[title] { 86 | border-bottom: none; /* 1 */ 87 | text-decoration: underline; /* 2 */ 88 | text-decoration: underline dotted; /* 2 */ 89 | } 90 | 91 | /** 92 | * Add the correct font weight in Chrome, Edge, and Safari. 93 | */ 94 | 95 | b, 96 | strong { 97 | font-weight: bolder; 98 | } 99 | 100 | /** 101 | * 1. Correct the inheritance and scaling of font size in all browsers. 102 | * 2. Correct the odd `em` font sizing in all browsers. 103 | */ 104 | 105 | code, 106 | kbd, 107 | samp { 108 | font-family: monospace, monospace; /* 1 */ 109 | font-size: 1em; /* 2 */ 110 | } 111 | 112 | /** 113 | * Add the correct font size in all browsers. 114 | */ 115 | 116 | small { 117 | font-size: 80%; 118 | } 119 | 120 | /** 121 | * Prevent `sub` and `sup` elements from affecting the line height in 122 | * all browsers. 123 | */ 124 | 125 | sub, 126 | sup { 127 | font-size: 75%; 128 | line-height: 0; 129 | position: relative; 130 | vertical-align: baseline; 131 | } 132 | 133 | sub { 134 | bottom: -0.25em; 135 | } 136 | 137 | sup { 138 | top: -0.5em; 139 | } 140 | 141 | /* Embedded content 142 | ========================================================================== */ 143 | 144 | /** 145 | * Remove the border on images inside links in IE 10. 146 | */ 147 | 148 | img { 149 | border-style: none; 150 | } 151 | 152 | /* Forms 153 | ========================================================================== */ 154 | 155 | /** 156 | * 1. Change the font styles in all browsers. 157 | * 2. Remove the margin in Firefox and Safari. 158 | */ 159 | 160 | button, 161 | input, 162 | optgroup, 163 | select, 164 | textarea { 165 | font-family: inherit; /* 1 */ 166 | font-size: 100%; /* 1 */ 167 | line-height: 1.15; /* 1 */ 168 | margin: 0; /* 2 */ 169 | } 170 | 171 | /** 172 | * Show the overflow in IE. 173 | * 1. Show the overflow in Edge. 174 | */ 175 | 176 | button, 177 | input { /* 1 */ 178 | overflow: visible; 179 | } 180 | 181 | /** 182 | * Remove the inheritance of text transform in Edge, Firefox, and IE. 183 | * 1. Remove the inheritance of text transform in Firefox. 184 | */ 185 | 186 | button, 187 | select { /* 1 */ 188 | text-transform: none; 189 | } 190 | 191 | /** 192 | * Correct the inability to style clickable types in iOS and Safari. 193 | */ 194 | 195 | button, 196 | [type="button"], 197 | [type="reset"], 198 | [type="submit"] { 199 | -webkit-appearance: button; 200 | } 201 | 202 | /** 203 | * Remove the inner border and padding in Firefox. 204 | */ 205 | 206 | button::-moz-focus-inner, 207 | [type="button"]::-moz-focus-inner, 208 | [type="reset"]::-moz-focus-inner, 209 | [type="submit"]::-moz-focus-inner { 210 | border-style: none; 211 | padding: 0; 212 | } 213 | 214 | /** 215 | * Restore the focus styles unset by the previous rule. 216 | */ 217 | 218 | button:-moz-focusring, 219 | [type="button"]:-moz-focusring, 220 | [type="reset"]:-moz-focusring, 221 | [type="submit"]:-moz-focusring { 222 | outline: 1px dotted ButtonText; 223 | } 224 | 225 | /** 226 | * Correct the padding in Firefox. 227 | */ 228 | 229 | fieldset { 230 | padding: 0.35em 0.75em 0.625em; 231 | } 232 | 233 | /** 234 | * 1. Correct the text wrapping in Edge and IE. 235 | * 2. Correct the color inheritance from `fieldset` elements in IE. 236 | * 3. Remove the padding so developers are not caught out when they zero out 237 | * `fieldset` elements in all browsers. 238 | */ 239 | 240 | legend { 241 | box-sizing: border-box; /* 1 */ 242 | color: inherit; /* 2 */ 243 | display: table; /* 1 */ 244 | max-width: 100%; /* 1 */ 245 | padding: 0; /* 3 */ 246 | white-space: normal; /* 1 */ 247 | } 248 | 249 | /** 250 | * Add the correct vertical alignment in Chrome, Firefox, and Opera. 251 | */ 252 | 253 | progress { 254 | vertical-align: baseline; 255 | } 256 | 257 | /** 258 | * Remove the default vertical scrollbar in IE 10+. 259 | */ 260 | 261 | textarea { 262 | overflow: auto; 263 | } 264 | 265 | /** 266 | * 1. Add the correct box sizing in IE 10. 267 | * 2. Remove the padding in IE 10. 268 | */ 269 | 270 | [type="checkbox"], 271 | [type="radio"] { 272 | box-sizing: border-box; /* 1 */ 273 | padding: 0; /* 2 */ 274 | } 275 | 276 | /** 277 | * Correct the cursor style of increment and decrement buttons in Chrome. 278 | */ 279 | 280 | [type="number"]::-webkit-inner-spin-button, 281 | [type="number"]::-webkit-outer-spin-button { 282 | height: auto; 283 | } 284 | 285 | /** 286 | * 1. Correct the odd appearance in Chrome and Safari. 287 | * 2. Correct the outline style in Safari. 288 | */ 289 | 290 | [type="search"] { 291 | -webkit-appearance: textfield; /* 1 */ 292 | outline-offset: -2px; /* 2 */ 293 | } 294 | 295 | /** 296 | * Remove the inner padding in Chrome and Safari on macOS. 297 | */ 298 | 299 | [type="search"]::-webkit-search-decoration { 300 | -webkit-appearance: none; 301 | } 302 | 303 | /** 304 | * 1. Correct the inability to style clickable types in iOS and Safari. 305 | * 2. Change font properties to `inherit` in Safari. 306 | */ 307 | 308 | ::-webkit-file-upload-button { 309 | -webkit-appearance: button; /* 1 */ 310 | font: inherit; /* 2 */ 311 | } 312 | 313 | /* Interactive 314 | ========================================================================== */ 315 | 316 | /* 317 | * Add the correct display in Edge, IE 10+, and Firefox. 318 | */ 319 | 320 | details { 321 | display: block; 322 | } 323 | 324 | /* 325 | * Add the correct display in all browsers. 326 | */ 327 | 328 | summary { 329 | display: list-item; 330 | } 331 | 332 | /* Misc 333 | ========================================================================== */ 334 | 335 | /** 336 | * Add the correct display in IE 10+. 337 | */ 338 | 339 | template { 340 | display: none; 341 | } 342 | 343 | /** 344 | * Add the correct display in IE 10. 345 | */ 346 | 347 | [hidden] { 348 | display: none; 349 | } 350 | 351 | 352 | 353 | /*! https://github.com/a11yproject/a11yproject.com/blob/main/src/css/base/_resets.scss */ 354 | *, 355 | *::before, 356 | *::after { 357 | box-sizing: border-box; 358 | margin: 0; 359 | padding: 0; 360 | vertical-align: baseline; 361 | } 362 | 363 | /* Removes borders from linked images */ 364 | a img { 365 | border: none; 366 | } 367 | 368 | 369 | b, 370 | strong { 371 | font-weight: 700; 372 | } 373 | 374 | button, 375 | input[type="button"] { 376 | border: 0; 377 | } 378 | 379 | 380 | em, 381 | cite, 382 | i { 383 | font-style: italic; 384 | } 385 | 386 | img, 387 | figure, 388 | picture { 389 | border: 0; 390 | display: block; 391 | height: auto; 392 | max-width: 100%; 393 | } 394 | 395 | h1, 396 | h2, 397 | h3, 398 | h4, 399 | h5, 400 | h6 { 401 | font-weight: 500; 402 | } 403 | 404 | sub { 405 | text-transform: lowercase; 406 | font-size: inherit; 407 | font-variant-position: sub; 408 | } 409 | 410 | sup { 411 | text-transform: lowercase; 412 | font-variant-position: super; 413 | } 414 | 415 | textarea { 416 | overflow: auto; 417 | resize: vertical; 418 | } -------------------------------------------------------------------------------- /docs/assets/styles/water.css: -------------------------------------------------------------------------------- 1 | /* adapted from https://github.com/kognise/water.css */ 2 | :root { 3 | --body-font: serif; 4 | --background-body: #fff; 5 | --background-ui: #f7f7f7; 6 | --background-alt: #f7f7f7; 7 | --selection: #9e9e9e; 8 | --text-main: #363636; 9 | --links: #0076d1; 10 | --focus: rgba(0, 150, 191, 0.67); 11 | --border: #dbdbdb; 12 | --animation-duration: 0.1s; 13 | --button-hover: #ddd; 14 | --scrollbar-thumb: #d5d5d5; 15 | --scrollbar-thumb-hover: #c4c4c4; 16 | --form-font: sans-serif; 17 | --form-placeholder: #949494; 18 | --form-text: #000; 19 | --input-thumb: #000; 20 | --highlight: #ff0; 21 | --select-arrow: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='63' width='117' fill='%23161f27'%3E%3Cpath d='M115 2c-1-2-4-2-5 0L59 53 7 2a4 4 0 00-5 5l54 54 2 2 3-2 54-54c2-1 2-4 0-5z'/%3E%3C/svg%3E"); 22 | } 23 | html { 24 | scrollbar-color: var(--scrollbar-thumb) var(--background-body); 25 | scrollbar-width: thin; 26 | } 27 | body { 28 | line-height: 1.4; 29 | word-wrap: break-word; 30 | color: var(--text-main); 31 | background: var(--background-body); 32 | font-family: var(--body-font); 33 | text-rendering: optimizeLegibility; 34 | font-feature-settings: 'kern' 1, 'onum' 0, 'liga' 0, 'tnum' 1; 35 | } 36 | h1, 37 | h2, 38 | h3, 39 | h4, 40 | h5, 41 | h6 { 42 | margin: 1rem 0; 43 | } 44 | p { 45 | margin: 1rem 0; 46 | } 47 | button, 48 | input, 49 | textarea { 50 | transition: background-color var(--animation-duration) linear, border-color var(--animation-duration) linear, color var(--animation-duration) linear, box-shadow var(--animation-duration) linear, transform var(--animation-duration) ease; 51 | } 52 | mark { 53 | background-color: var(--highlight); 54 | border-radius: 2px; 55 | padding: 0 2px; 56 | } 57 | button, 58 | input[type="button"], 59 | input[type="checkbox"], 60 | input[type="radio"], 61 | input[type="range"], 62 | input[type="submit"], 63 | select { 64 | cursor: pointer; 65 | } 66 | input:not([type="checkbox"]):not([type="radio"]), 67 | select { 68 | display: block; 69 | } 70 | button, 71 | input, 72 | select, 73 | textarea { 74 | color: var(--form-text); 75 | background-color: var(--background-ui); 76 | font-family: var(--form-font); 77 | font-size: inherit; 78 | padding: 0.5em; 79 | border: none; 80 | border-radius: 4px; 81 | outline: none; 82 | } 83 | input[type="checkbox"], 84 | input[type="radio"] { 85 | height: 1em; 86 | width: 1em; 87 | } 88 | input[type="radio"] { 89 | border-radius: 100%; 90 | } 91 | input { 92 | vertical-align: top; 93 | } 94 | label { 95 | vertical-align: middle; 96 | margin-bottom: 4px; 97 | display: inline-block; 98 | } 99 | button, 100 | input:not([type="checkbox"]):not([type="radio"]), 101 | input[type="range"], 102 | select, 103 | textarea { 104 | -webkit-appearance: none; 105 | } 106 | textarea { 107 | display: block; 108 | margin-right: 0; 109 | box-sizing: border-box; 110 | resize: vertical; 111 | } 112 | textarea:not([cols]) { 113 | width: 100%; 114 | } 115 | textarea:not([rows]) { 116 | min-height: 40px; 117 | height: 140px; 118 | } 119 | select { 120 | background: var(--background-ui) var(--select-arrow) calc(100% - 12px) 50%/12px no-repeat; 121 | padding-right: 32px; 122 | } 123 | select::-ms-expand { 124 | display: none; 125 | } 126 | select[multiple] { 127 | padding-right: 8px; 128 | background-image: none; 129 | overflow-y: auto; 130 | } 131 | button:hover, 132 | input[type="button"]:hover, 133 | input[type="submit"]:hover { 134 | background: var(--button-hover); 135 | } 136 | button:focus, 137 | input:focus, 138 | select:focus, 139 | textarea:focus { 140 | box-shadow: 0 0 0 2px rgba(0, 150, 191, 0.67); 141 | box-shadow: 0 0 0 2px var(--focus); 142 | } 143 | button:disabled, 144 | input:disabled, 145 | select:disabled, 146 | textarea:disabled { 147 | cursor: not-allowed; 148 | opacity: 0.5; 149 | } 150 | ::-moz-placeholder { 151 | color: var(--form-placeholder); 152 | } 153 | :-ms-input-placeholder { 154 | color: var(--form-placeholder); 155 | } 156 | ::-ms-input-placeholder { 157 | color: var(--form-placeholder); 158 | } 159 | ::placeholder { 160 | color: var(--form-placeholder); 161 | } 162 | fieldset { 163 | border: 1px solid var(--focus); 164 | border-radius: 6px; 165 | margin: 0 0 12px; 166 | padding: 10px; 167 | } 168 | legend { 169 | font-size: 0.9em; 170 | font-weight: 600; 171 | } 172 | input[type="range"] { 173 | padding: 0; 174 | margin: 0; 175 | background: transparent; 176 | } 177 | input[type="range"]:focus { 178 | outline: none; 179 | } 180 | input[type="range"]::-webkit-slider-runnable-track { 181 | width: 100%; 182 | height: 10px; 183 | -webkit-transition: 0.2s; 184 | transition: 0.2s; 185 | background: var(--background-ui); 186 | border-radius: 4px; 187 | } 188 | input[type="range"]::-webkit-slider-thumb { 189 | height: 20px; 190 | width: 20px; 191 | border-radius: 50%; 192 | background: var(--input-thumb); 193 | -webkit-appearance: none; 194 | margin-top: -5px; 195 | } 196 | input[type="range"]:focus::-webkit-slider-runnable-track { 197 | background: var(--background-ui); 198 | } 199 | input[type="range"]::-moz-range-track { 200 | width: 100%; 201 | height: 10px; 202 | -moz-transition: 0.2s; 203 | transition: 0.2s; 204 | background: var(--background-ui); 205 | border-radius: 4px; 206 | } 207 | input[type="range"]::-moz-range-thumb { 208 | box-shadow: 1px 1px 1px #000, 0 0 1px #0d0d0d; 209 | height: 20px; 210 | width: 20px; 211 | border-radius: 50%; 212 | background: var(--input-thumb); 213 | } 214 | input[type="range"]::-ms-track { 215 | width: 100%; 216 | height: 10px; 217 | background: transparent; 218 | border-color: transparent; 219 | border-width: 16px 0; 220 | color: transparent; 221 | } 222 | input[type="range"]::-ms-fill-lower, 223 | input[type="range"]::-ms-fill-upper { 224 | background: var(--background-ui); 225 | border: 0.2px solid #010101; 226 | border-radius: 4px; 227 | box-shadow: 1px 1px 1px #000, 0 0 1px #0d0d0d; 228 | } 229 | input[type="range"]::-ms-thumb { 230 | height: 20px; 231 | width: 20px; 232 | border-radius: 50%; 233 | background: var(--input-thumb); 234 | } 235 | input[type="range"]:focus::-ms-fill-lower, 236 | input[type="range"]:focus::-ms-fill-upper { 237 | background: var(--background-ui); 238 | } 239 | a { 240 | color: var(--links); 241 | } 242 | a:hover { 243 | 244 | } 245 | img, 246 | video { 247 | max-width: 100%; 248 | height: auto; 249 | } 250 | hr { 251 | border: none; 252 | border-top: 1px solid var(--border); 253 | } 254 | table { 255 | border-collapse: collapse; 256 | margin-bottom: 10px; 257 | width: 100%; 258 | table-layout: fixed; 259 | } 260 | table caption, 261 | td, 262 | th { 263 | text-align: left; 264 | } 265 | td, 266 | th { 267 | padding: 6px; 268 | vertical-align: top; 269 | word-wrap: break-word; 270 | } 271 | thead { 272 | border-bottom: 1px solid var(--border); 273 | } 274 | tfoot { 275 | border-top: 1px solid var(--border); 276 | } 277 | tbody tr:nth-child(2n) { 278 | background-color: var(--background-alt); 279 | } 280 | ::-webkit-scrollbar { 281 | height: 10px; 282 | width: 10px; 283 | } 284 | ::-webkit-scrollbar-track { 285 | background: var(--background-ui); 286 | border-radius: 6px; 287 | } 288 | ::-webkit-scrollbar-thumb { 289 | background: var(--scrollbar-thumb); 290 | border-radius: 6px; 291 | } 292 | ::-webkit-scrollbar-thumb:hover { 293 | background: var(--scrollbar-thumb-hover); 294 | } 295 | ::-moz-selection { 296 | background-color: var(--selection); 297 | } 298 | ::selection { 299 | background-color: var(--selection); 300 | } 301 | details { 302 | display: flex; 303 | flex-direction: column; 304 | align-items: flex-start; 305 | background-color: var(--background-alt); 306 | padding: 10px 10px 0; 307 | margin: 1em 0; 308 | border-radius: 6px; 309 | overflow: hidden; 310 | } 311 | details[open] { 312 | padding: 10px; 313 | } 314 | details > :last-child { 315 | margin-bottom: 0; 316 | } 317 | details[open] summary { 318 | margin-bottom: 10px; 319 | } 320 | summary { 321 | display: list-item; 322 | background-color: var(--background-ui); 323 | padding: 10px; 324 | margin: -10px -10px 0; 325 | cursor: pointer; 326 | outline: none; 327 | } 328 | summary:focus, 329 | summary:hover { 330 | text-decoration: underline; 331 | } 332 | details > :not(summary) { 333 | margin-top: 0; 334 | } 335 | summary::-webkit-details-marker { 336 | color: var(--text-main); 337 | } 338 | -------------------------------------------------------------------------------- /docs/assets/toast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/docs/assets/toast.png -------------------------------------------------------------------------------- /docs/assets/water.css: -------------------------------------------------------------------------------- 1 | /* adapted from https://github.com/kognise/water.css */ 2 | :root { 3 | --body-font: serif; 4 | --background-body: #fff; 5 | --background: #efefef; 6 | --background-alt: #f7f7f7; 7 | --selection: #9e9e9e; 8 | --text-main: #363636; 9 | --links: #0076d1; 10 | --focus: rgba(0, 150, 191, 0.67); 11 | --border: #dbdbdb; 12 | --animation-duration: 0.1s; 13 | --button-hover: #ddd; 14 | --scrollbar-thumb: #d5d5d5; 15 | --scrollbar-thumb-hover: #c4c4c4; 16 | --form-font: sans-serif; 17 | --form-placeholder: #949494; 18 | --form-text: #000; 19 | --input-thumb: #000; 20 | --highlight: #ff0; 21 | --select-arrow: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='63' width='117' fill='%23161f27'%3E%3Cpath d='M115 2c-1-2-4-2-5 0L59 53 7 2a4 4 0 00-5 5l54 54 2 2 3-2 54-54c2-1 2-4 0-5z'/%3E%3C/svg%3E"); 22 | } 23 | html { 24 | scrollbar-color: var(--scrollbar-thumb) var(--background-body); 25 | scrollbar-width: thin; 26 | } 27 | body { 28 | line-height: 1.4; 29 | word-wrap: break-word; 30 | color: var(--text-main); 31 | background: var(--background-body); 32 | font-family: var(--body-font); 33 | text-rendering: optimizeLegibility; 34 | } 35 | h1, 36 | h2, 37 | h3, 38 | h4, 39 | h5, 40 | h6 { 41 | margin: 1rem 0; 42 | } 43 | p { 44 | margin: 1rem 0; 45 | } 46 | button, 47 | input, 48 | textarea { 49 | transition: background-color var(--animation-duration) linear, border-color var(--animation-duration) linear, color var(--animation-duration) linear, box-shadow var(--animation-duration) linear, transform var(--animation-duration) ease; 50 | } 51 | mark { 52 | background-color: var(--highlight); 53 | border-radius: 2px; 54 | padding: 0 2px; 55 | } 56 | button, 57 | input[type="button"], 58 | input[type="checkbox"], 59 | input[type="radio"], 60 | input[type="range"], 61 | input[type="submit"], 62 | select { 63 | cursor: pointer; 64 | } 65 | input:not([type="checkbox"]):not([type="radio"]), 66 | select { 67 | display: block; 68 | } 69 | button, 70 | input, 71 | select, 72 | textarea { 73 | color: var(--form-text); 74 | background-color: var(--background); 75 | font-family: var(--form-font); 76 | font-size: inherit; 77 | padding: 0.5em; 78 | border: none; 79 | border-radius: 4px; 80 | outline: none; 81 | } 82 | input[type="checkbox"], 83 | input[type="radio"] { 84 | height: 1em; 85 | width: 1em; 86 | } 87 | input[type="radio"] { 88 | border-radius: 100%; 89 | } 90 | input { 91 | vertical-align: top; 92 | } 93 | label { 94 | vertical-align: middle; 95 | margin-bottom: 4px; 96 | display: inline-block; 97 | } 98 | button, 99 | input:not([type="checkbox"]):not([type="radio"]), 100 | input[type="range"], 101 | select, 102 | textarea { 103 | -webkit-appearance: none; 104 | } 105 | textarea { 106 | display: block; 107 | margin-right: 0; 108 | box-sizing: border-box; 109 | resize: vertical; 110 | } 111 | textarea:not([cols]) { 112 | width: 100%; 113 | } 114 | textarea:not([rows]) { 115 | min-height: 40px; 116 | height: 140px; 117 | } 118 | select { 119 | background: var(--background) var(--select-arrow) calc(100% - 12px) 50%/12px no-repeat; 120 | padding-right: 32px; 121 | } 122 | select::-ms-expand { 123 | display: none; 124 | } 125 | select[multiple] { 126 | padding-right: 8px; 127 | background-image: none; 128 | overflow-y: auto; 129 | } 130 | button:hover, 131 | input[type="button"]:hover, 132 | input[type="submit"]:hover { 133 | background: var(--button-hover); 134 | } 135 | button:focus, 136 | input:focus, 137 | select:focus, 138 | textarea:focus { 139 | box-shadow: 0 0 0 2px rgba(0, 150, 191, 0.67); 140 | box-shadow: 0 0 0 2px var(--focus); 141 | } 142 | button:disabled, 143 | input:disabled, 144 | select:disabled, 145 | textarea:disabled { 146 | cursor: not-allowed; 147 | opacity: 0.5; 148 | } 149 | ::-moz-placeholder { 150 | color: var(--form-placeholder); 151 | } 152 | :-ms-input-placeholder { 153 | color: var(--form-placeholder); 154 | } 155 | ::-ms-input-placeholder { 156 | color: var(--form-placeholder); 157 | } 158 | ::placeholder { 159 | color: var(--form-placeholder); 160 | } 161 | fieldset { 162 | border: 1px solid var(--focus); 163 | border-radius: 6px; 164 | margin: 0 0 12px; 165 | padding: 10px; 166 | } 167 | legend { 168 | font-size: 0.9em; 169 | font-weight: 600; 170 | } 171 | input[type="range"] { 172 | padding: 0; 173 | margin: 0; 174 | background: transparent; 175 | } 176 | input[type="range"]:focus { 177 | outline: none; 178 | } 179 | input[type="range"]::-webkit-slider-runnable-track { 180 | width: 100%; 181 | height: 10px; 182 | -webkit-transition: 0.2s; 183 | transition: 0.2s; 184 | background: var(--background); 185 | border-radius: 4px; 186 | } 187 | input[type="range"]::-webkit-slider-thumb { 188 | height: 20px; 189 | width: 20px; 190 | border-radius: 50%; 191 | background: var(--input-thumb); 192 | -webkit-appearance: none; 193 | margin-top: -5px; 194 | } 195 | input[type="range"]:focus::-webkit-slider-runnable-track { 196 | background: var(--background); 197 | } 198 | input[type="range"]::-moz-range-track { 199 | width: 100%; 200 | height: 10px; 201 | -moz-transition: 0.2s; 202 | transition: 0.2s; 203 | background: var(--background); 204 | border-radius: 4px; 205 | } 206 | input[type="range"]::-moz-range-thumb { 207 | box-shadow: 1px 1px 1px #000, 0 0 1px #0d0d0d; 208 | height: 20px; 209 | width: 20px; 210 | border-radius: 50%; 211 | background: var(--input-thumb); 212 | } 213 | input[type="range"]::-ms-track { 214 | width: 100%; 215 | height: 10px; 216 | background: transparent; 217 | border-color: transparent; 218 | border-width: 16px 0; 219 | color: transparent; 220 | } 221 | input[type="range"]::-ms-fill-lower, 222 | input[type="range"]::-ms-fill-upper { 223 | background: var(--background); 224 | border: 0.2px solid #010101; 225 | border-radius: 4px; 226 | box-shadow: 1px 1px 1px #000, 0 0 1px #0d0d0d; 227 | } 228 | input[type="range"]::-ms-thumb { 229 | height: 20px; 230 | width: 20px; 231 | border-radius: 50%; 232 | background: var(--input-thumb); 233 | } 234 | input[type="range"]:focus::-ms-fill-lower, 235 | input[type="range"]:focus::-ms-fill-upper { 236 | background: var(--background); 237 | } 238 | a { 239 | color: var(--links); 240 | } 241 | a:hover { 242 | 243 | } 244 | img, 245 | video { 246 | max-width: 100%; 247 | height: auto; 248 | } 249 | hr { 250 | border: none; 251 | border-top: 1px solid var(--border); 252 | } 253 | table { 254 | border-collapse: collapse; 255 | margin-bottom: 10px; 256 | width: 100%; 257 | table-layout: fixed; 258 | } 259 | table caption, 260 | td, 261 | th { 262 | text-align: left; 263 | } 264 | td, 265 | th { 266 | padding: 6px; 267 | vertical-align: top; 268 | word-wrap: break-word; 269 | } 270 | thead { 271 | border-bottom: 1px solid var(--border); 272 | } 273 | tfoot { 274 | border-top: 1px solid var(--border); 275 | } 276 | tbody tr:nth-child(2n) { 277 | background-color: var(--background-alt); 278 | } 279 | ::-webkit-scrollbar { 280 | height: 10px; 281 | width: 10px; 282 | } 283 | ::-webkit-scrollbar-track { 284 | background: var(--background); 285 | border-radius: 6px; 286 | } 287 | ::-webkit-scrollbar-thumb { 288 | background: var(--scrollbar-thumb); 289 | border-radius: 6px; 290 | } 291 | ::-webkit-scrollbar-thumb:hover { 292 | background: var(--scrollbar-thumb-hover); 293 | } 294 | ::-moz-selection { 295 | background-color: var(--selection); 296 | } 297 | ::selection { 298 | background-color: var(--selection); 299 | } 300 | details { 301 | display: flex; 302 | flex-direction: column; 303 | align-items: flex-start; 304 | background-color: var(--background-alt); 305 | padding: 10px 10px 0; 306 | margin: 1em 0; 307 | border-radius: 6px; 308 | overflow: hidden; 309 | } 310 | details[open] { 311 | padding: 10px; 312 | } 313 | details > :last-child { 314 | margin-bottom: 0; 315 | } 316 | details[open] summary { 317 | margin-bottom: 10px; 318 | } 319 | summary { 320 | display: list-item; 321 | background-color: var(--background); 322 | padding: 10px; 323 | margin: -10px -10px 0; 324 | cursor: pointer; 325 | outline: none; 326 | } 327 | summary:focus, 328 | summary:hover { 329 | text-decoration: underline; 330 | } 331 | details > :not(summary) { 332 | margin-top: 0; 333 | } 334 | summary::-webkit-details-marker { 335 | color: var(--text-main); 336 | } 337 | -------------------------------------------------------------------------------- /docs/build/bundle.css: -------------------------------------------------------------------------------- 1 | .layercake-container.svelte-1ll0j6t,.layercake-container.svelte-1ll0j6t *{box-sizing:border-box}.layercake-container.svelte-1ll0j6t{width:100%;height:100%} 2 | div.svelte-1u9nfei,slot.svelte-1u9nfei{position:absolute;top:0;left:0} 3 | svg.svelte-ocozda{position:absolute;width:100%;height:100%;overflow:visible}svg.svelte-ocozda *{vector-effect:non-scaling-stroke} 4 | svg.svelte-17l4rdd{position:absolute;top:0;left:0;overflow:visible} 5 | section.svelte-yrsd42{padding:1rem}div.svelte-yrsd42{margin-bottom:2rem}img.svelte-yrsd42{width:20rem}td.svelte-yrsd42:nth-child(2),th.svelte-yrsd42:nth-child(2){text-align:right;padding:0.5em} 6 | p.svelte-omfgrc{position:absolute;margin:0;line-height:1;transform:translate(-50%, 50%)} 7 | .chart-container.svelte-1sls8yb{width:50%;max-width:480px}figure.svelte-1sls8yb{position:relative;width:100%} 8 | svg.svelte-1l6t571{width:1em;height:1em;overflow:visible;transform-origin:50% 50%} 9 | footer.svelte-1p6xswo.svelte-1p6xswo{background-color:var(--text-main);color:var(--background-body);font-family:var(--sans);padding:3em 1em;margin-top:3em}a.svelte-1p6xswo.svelte-1p6xswo,a.svelte-1p6xswo.svelte-1p6xswo:visited,a.svelte-1p6xswo.svelte-1p6xswo:hover{color:var(--background-body)}.stories.svelte-1p6xswo.svelte-1p6xswo{margin:0 auto;display:flex;flex-wrap:wrap;justify-content:space-between;max-width:70em}.story.svelte-1p6xswo.svelte-1p6xswo{display:block;width:100%;border:none;margin-bottom:3rem}.story.svelte-1p6xswo a.svelte-1p6xswo{display:block;font-weight:700;text-decoration:none}.story.svelte-1p6xswo span.svelte-1p6xswo{display:block;margin-top:1em;line-height:1.2}.wordmark.svelte-1p6xswo.svelte-1p6xswo{max-width:10em;margin:1em auto}.about.svelte-1p6xswo.svelte-1p6xswo{margin:3rem auto;margin-top:0;text-align:center}.links.svelte-1p6xswo ul.svelte-1p6xswo{display:flex;flex-wrap:wrap;justify-content:center}.links.svelte-1p6xswo li.svelte-1p6xswo{display:flex;padding:0.5em 1em}.links.svelte-1p6xswo a.svelte-1p6xswo{display:flex;border:none;align-items:center;text-decoration:none}.links.svelte-1p6xswo span.svelte-1p6xswo{margin-left:0.5em}@media only screen and (min-width: 30em){.story.svelte-1p6xswo.svelte-1p6xswo{width:50%;padding:0 1em}}@media only screen and (min-width: 50em){.story.svelte-1p6xswo.svelte-1p6xswo{width:25%;padding:0 1em}} 10 | .wordmark.svelte-c6yjz3.svelte-c6yjz3{max-width:10em;margin:1em auto}.wordmark.svelte-c6yjz3 a.svelte-c6yjz3{border:none;color:var(--fg)}.wordmark.svelte-c6yjz3 a.svelte-c6yjz3:hover{background-color:transparent} 11 | 12 | /*# sourceMappingURL=bundle.css.map */ -------------------------------------------------------------------------------- /docs/build/main.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var d = window.document 3 | var wsServerUrl = window.location.protocol 4 | + '//' + (window.location.host || 'localhost').split(':')[0] 5 | + ':38670/'; 6 | 7 | if (!window['__ROLLUP_PLUGIN_HOT_RUNTIME']) { 8 | var loaded = false; 9 | var callbacks = []; 10 | window['__ROLLUP_PLUGIN_HOT_RUNTIME'] = { 11 | host: null, 12 | port: 38670, 13 | ws: false, 14 | then: function(cb) { 15 | if (loaded) { 16 | setTimeout(cb, 0); 17 | } else { 18 | callbacks.push(cb); 19 | } 20 | } 21 | }; 22 | var script = d.createElement('script'); 23 | script.async = 1; 24 | script.src = wsServerUrl + 'runtime/hmr-runtime.js'; 25 | script.onload = () => { 26 | loaded = true; 27 | callbacks.splice(0, callbacks.length).forEach(function(cb) { 28 | cb(); 29 | }); 30 | }; 31 | d.head.appendChild(script); 32 | } 33 | window['__ROLLUP_PLUGIN_HOT_RUNTIME'].then(function() { 34 | System.import("undefinedsrc/main.js", wsServerUrl).catch(err => { 35 | console.error(err && err.stack || err); 36 | }); 37 | }); 38 | 39 | })(); 40 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Svelte Starter 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Skip to main content 16 |
17 | 18 | 19 | 20 |
51 |
52 | 53 |
54 |

This is a headline from a copy doc

55 | 56 |

Hello svelter! Here is an inline svg icon: 57 | 58 |

59 | 60 |

A table from CSV data

61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 |
NameValue
Russell1
Amelia2
69 | 70 |

An image from "public/assets"

71 | 72 | sad toast
73 | 74 |

A server-side rendered chart using Layercake

75 | 76 |
81 |

A

B

C

82 |
83 |
84 | 85 |

Heading 1

86 |

Heading 2

87 |

Heading 3

88 |

Heading 4

89 |
Heading 5
90 |
Heading 6
91 |

This is a paragraph with a strong tag and an 92 | em tag. And here is a mark tag. Oh and a 93 | link tag. 94 |

95 | 96 |

Some Elements:

97 |

98 |

99 |

100 |

101 |
102 | 103 | 159 |
160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-starter", 3 | "version": "2.3.1", 4 | "engines": { 5 | "node": "14.15.0" 6 | }, 7 | "devDependencies": { 8 | "@rollup/plugin-commonjs": "^17.1.0", 9 | "@rollup/plugin-dsv": "^2.0.1", 10 | "@rollup/plugin-json": "^4.1.0", 11 | "@rollup/plugin-node-resolve": "^11.2.0", 12 | "@rollup/plugin-replace": "^2.3.4", 13 | "archieml": "^0.4.2", 14 | "autoprefixer": "^10.2.4", 15 | "compression": "^1.7.4", 16 | "d3-interpolate": "^2.0.1", 17 | "feather-icons": "^4.28.0", 18 | "layercake": "^4.0.3", 19 | "lodash.debounce": "^4.0.8", 20 | "node-fetch": "^2.6.1", 21 | "postcss": "^8.2.6", 22 | "rollup": "^2.39.0", 23 | "rollup-plugin-execute": "^1.1.1", 24 | "rollup-plugin-hot": "^0.1.1", 25 | "rollup-plugin-svelte": "^7.1.0", 26 | "rollup-plugin-svelte-hot": "^0.13.0", 27 | "rollup-plugin-svg": "^2.0.0", 28 | "rollup-plugin-terser": "^7.0.2", 29 | "shelljs": "^0.8.4", 30 | "sirv-cli": "^1.0.11", 31 | "svelte": "^3.32.3", 32 | "svelte-preprocess": "^4.6.9" 33 | }, 34 | "scripts": { 35 | "build": "rollup -c", 36 | "dev:rollup": "rollup -c -w", 37 | "dev:livereload": "rollup -c -w --environment LIVERELOAD", 38 | "gdoc": "node scripts/fetch-google.js", 39 | "dev": "npm run dev:rollup", 40 | "predeploy": "npm run build", 41 | "deploy": "rollup -c rollup.config-ssr.js", 42 | "start": "sirv public" 43 | }, 44 | "dependencies": { 45 | "paper": "^0.12.11", 46 | "paper-clipper": "^1.0.2", 47 | "paper-jsdom": "^0.12.11", 48 | "svg-outline-stroke": "^1.3.0" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /public/assets/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /public/assets/obama.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/public/assets/obama.png -------------------------------------------------------------------------------- /public/assets/styles/font.css: -------------------------------------------------------------------------------- 1 | /* 2 | This font software is the property of Commercial Type. 3 | 4 | You may not modify the font software, use it on another website, or install it on a computer. 5 | 6 | License information is available at http://commercialtype.com/eula 7 | For more information please visit Commercial Type at http://commercialtype.com or email us at info[at]commercialtype.com 8 | 9 | Copyright (C) 2017 Schwartzco Inc. 10 | License: 1704-GNCLGK 11 | */ 12 | 13 | /* 14 | ******************** 15 | National 16 | ******************** 17 | */ 18 | 19 | @font-face { 20 | font-family: 'National 2 Web'; 21 | src: url('../pudding-fonts/national/National2Web-Regular.woff2') format('woff2'), 22 | url('../pudding-fonts/national/National2Web-Regular.woff') format('woff'); 23 | font-weight: 500; 24 | font-style: normal; 25 | font-stretch: normal; 26 | font-display: swap; 27 | } 28 | 29 | @font-face { 30 | font-family: 'National 2 Web'; 31 | src: url('../pudding-fonts/national/National2Web-Bold.woff2') format('woff2'), 32 | url('../pudding-fonts/national/National2Web-Bold.woff') format('woff'); 33 | font-weight: 700; 34 | font-style: normal; 35 | font-stretch: normal; 36 | font-display: swap; 37 | } 38 | 39 | /* 40 | ******************** 41 | National Narrow 42 | ******************** 43 | */ 44 | 45 | /* 46 | @font-face { 47 | font-family: 'National 2 Narrow Web'; 48 | src: url('../pudding-fonts/national/National2NarrowWeb-Extralight.woff2') format('woff2'), 49 | url('../pudding-fonts/national/National2NarrowWeb-Extralight.woff') format('woff'); 50 | font-weight: 200; 51 | font-style: normal; 52 | font-stretch: normal; 53 | font-display: swap; 54 | } 55 | 56 | @font-face { 57 | font-family: 'National 2 Narrow Web'; 58 | src: url('../pudding-fonts/national/National2NarrowWeb-Regular.woff2') format('woff2'), 59 | url('../pudding-fonts/national/National2NarrowWeb-Regular.woff') format('woff'); 60 | font-weight: 500; 61 | font-style: normal; 62 | font-stretch: normal; 63 | font-display: swap; 64 | } 65 | 66 | @font-face { 67 | font-family: 'National 2 Narrow Web'; 68 | src: url('../pudding-fonts/national/National2NarrowWeb-Bold.woff2') format('woff2'), 69 | url('../pudding-fonts/national/National2NarrowWeb-Bold.woff') format('woff'); 70 | font-weight: 700; 71 | font-style: normal; 72 | font-stretch: normal; 73 | font-display: swap; 74 | } 75 | 76 | /* 77 | @font-face { 78 | font-family: 'National 2 Narrow Web'; 79 | src: url('../pudding-fonts/national/National2NarrowWeb-Black.woff2') format('woff2'), 80 | url('../pudding-fonts/national/National2NarrowWeb-Black.woff') format('woff'); 81 | font-weight: 900; 82 | font-style: normal; 83 | font-stretch: normal; 84 | font-display: swap; 85 | } 86 | */ 87 | 88 | /* 89 | ******************** 90 | Tiempos Text 91 | ******************** 92 | */ 93 | 94 | @font-face { 95 | font-family: 'Tiempos Text Web'; 96 | src: url('../pudding-fonts/tiempos/TiemposTextWeb-Regular.woff2') format('woff2'), 97 | url('../pudding-fonts/tiempos/TiemposTextWeb-Regular.woff') format('woff'); 98 | font-weight: 500; 99 | font-style: normal; 100 | font-stretch: normal; 101 | font-display: swap; 102 | } 103 | 104 | @font-face { 105 | font-family: 'Tiempos Text Web'; 106 | src: url('../pudding-fonts/tiempos/TiemposTextWeb-Bold.woff2') format('woff2'), 107 | url('../pudding-fonts/tiempos/TiemposTextWeb-Bold.woff') format('woff'); 108 | font-weight: 700; 109 | font-style: normal; 110 | font-stretch: normal; 111 | font-display: swap; 112 | } 113 | 114 | /* 115 | ******************** 116 | Tiempos Headline 117 | ******************** 118 | */ 119 | 120 | /* 121 | @font-face { 122 | font-family: 'Tiempos Headline Web'; 123 | src: url('../pudding-fonts/tiempos/TiemposHeadlineWeb-Regular.woff2') format('woff2'), 124 | url('../pudding-fonts/tiempos/TiemposHeadlineWeb-Regular.woff') format('woff'); 125 | font-weight: 500; 126 | font-style: normal; 127 | font-stretch: normal; 128 | font-display: swap; 129 | } 130 | */ -------------------------------------------------------------------------------- /public/assets/styles/global.css: -------------------------------------------------------------------------------- 1 | :root { 2 | @import url("https://rsms.me/inter/inter.css"); 3 | 4 | --sans: "Inter", Helvetica, Arial, sans-serif; 5 | --serif: "Tiempos Text Web", Georgia, Times, serif; 6 | --mono: "Inter", Consolas, Monaco, "Courier New", monospace; 7 | 8 | --z-bottom: -100; 9 | --z-middle: 0; 10 | --z-top: 100; 11 | --z-overlay: 1000; 12 | 13 | --black: #000; 14 | --off-black: #424650; 15 | --gray-dark: #5c606d; 16 | --gray: #8d9099; 17 | --gray-light: #bfc3ce; 18 | --off-white: #f0f0f0; 19 | --white: #fff; 20 | --accent-lighter: #d1dbe2; 21 | --accent-light: #d4e4e5; 22 | --accent-light-2: #ded2c5; 23 | --accent-dark: #066470; 24 | --accent-darker: #253f4f; 25 | --blue: #4717f6; 26 | --green: #34a29e; 27 | --red: #ff533d; 28 | --yellow: #e5e338; 29 | 30 | --bg: var(--white); 31 | --fg: var(--off-black); 32 | --default: var(--gray-light); 33 | --primary: var(--red); 34 | --secondary: var(--green); 35 | 36 | /* water.css */ 37 | 38 | --body-font: var(--sans); 39 | --background-body: var(--white); 40 | --background-ui: var(--off-white); 41 | --background-alt: var(--off-white); 42 | --selection: var(--gray); 43 | --text-main: var(--off-black); 44 | --links: var(--purple); 45 | --focus: var(--green); 46 | --border: var(--gray-light); 47 | --animation-duration: 0.1s; 48 | --button-hover: var(--gray-light); 49 | --scrollbar-thumb: var(--gray-light); 50 | --scrollbar-thumb-hover: var(--gray-dark); 51 | --form-placeholder: var(--gray-dark); 52 | --form-font: var(--sans); 53 | --form-text: var(--gray-dark); 54 | --input-thumb: var(--gray-dark); 55 | --highlight: var(--yellow); 56 | } 57 | 58 | .skip-to-main { 59 | border: none; 60 | width: 1px; 61 | height: 1px; 62 | overflow: hidden; 63 | position: absolute; 64 | } 65 | 66 | .skip-to-main:focus { 67 | width: auto; 68 | height: auto; 69 | padding: 0.5em; 70 | z-index: 1000; 71 | } 72 | 73 | /* pudding */ 74 | .wordmark svg path { 75 | fill: currentColor; 76 | } 77 | 78 | /* demo */ 79 | #demo svg { 80 | width: 1em; 81 | vertical-align: middle; 82 | } 83 | -------------------------------------------------------------------------------- /public/assets/styles/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | /* Document 4 | ========================================================================== */ 5 | 6 | /** 7 | * 1. Correct the line height in all browsers. 8 | * 2. Prevent adjustments of font size after orientation changes in iOS. 9 | */ 10 | 11 | html { 12 | line-height: 1.15; /* 1 */ 13 | -webkit-text-size-adjust: 100%; /* 2 */ 14 | } 15 | 16 | /* Sections 17 | ========================================================================== */ 18 | 19 | /** 20 | * Remove the margin in all browsers. 21 | */ 22 | 23 | body { 24 | margin: 0; 25 | } 26 | 27 | /** 28 | * Render the `main` element consistently in IE. 29 | */ 30 | 31 | main { 32 | display: block; 33 | } 34 | 35 | /** 36 | * Correct the font size and margin on `h1` elements within `section` and 37 | * `article` contexts in Chrome, Firefox, and Safari. 38 | */ 39 | 40 | h1 { 41 | font-size: 2em; 42 | margin: 0.67em 0; 43 | } 44 | 45 | /* Grouping content 46 | ========================================================================== */ 47 | 48 | /** 49 | * 1. Add the correct box sizing in Firefox. 50 | * 2. Show the overflow in Edge and IE. 51 | */ 52 | 53 | hr { 54 | box-sizing: content-box; /* 1 */ 55 | height: 0; /* 1 */ 56 | overflow: visible; /* 2 */ 57 | } 58 | 59 | /** 60 | * 1. Correct the inheritance and scaling of font size in all browsers. 61 | * 2. Correct the odd `em` font sizing in all browsers. 62 | */ 63 | 64 | pre { 65 | font-family: monospace, monospace; /* 1 */ 66 | font-size: 1em; /* 2 */ 67 | } 68 | 69 | /* Text-level semantics 70 | ========================================================================== */ 71 | 72 | /** 73 | * Remove the gray background on active links in IE 10. 74 | */ 75 | 76 | a { 77 | background-color: transparent; 78 | } 79 | 80 | /** 81 | * 1. Remove the bottom border in Chrome 57- 82 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. 83 | */ 84 | 85 | abbr[title] { 86 | border-bottom: none; /* 1 */ 87 | text-decoration: underline; /* 2 */ 88 | text-decoration: underline dotted; /* 2 */ 89 | } 90 | 91 | /** 92 | * Add the correct font weight in Chrome, Edge, and Safari. 93 | */ 94 | 95 | b, 96 | strong { 97 | font-weight: bolder; 98 | } 99 | 100 | /** 101 | * 1. Correct the inheritance and scaling of font size in all browsers. 102 | * 2. Correct the odd `em` font sizing in all browsers. 103 | */ 104 | 105 | code, 106 | kbd, 107 | samp { 108 | font-family: monospace, monospace; /* 1 */ 109 | font-size: 1em; /* 2 */ 110 | } 111 | 112 | /** 113 | * Add the correct font size in all browsers. 114 | */ 115 | 116 | small { 117 | font-size: 80%; 118 | } 119 | 120 | /** 121 | * Prevent `sub` and `sup` elements from affecting the line height in 122 | * all browsers. 123 | */ 124 | 125 | sub, 126 | sup { 127 | font-size: 75%; 128 | line-height: 0; 129 | position: relative; 130 | vertical-align: baseline; 131 | } 132 | 133 | sub { 134 | bottom: -0.25em; 135 | } 136 | 137 | sup { 138 | top: -0.5em; 139 | } 140 | 141 | /* Embedded content 142 | ========================================================================== */ 143 | 144 | /** 145 | * Remove the border on images inside links in IE 10. 146 | */ 147 | 148 | img { 149 | border-style: none; 150 | } 151 | 152 | /* Forms 153 | ========================================================================== */ 154 | 155 | /** 156 | * 1. Change the font styles in all browsers. 157 | * 2. Remove the margin in Firefox and Safari. 158 | */ 159 | 160 | button, 161 | input, 162 | optgroup, 163 | select, 164 | textarea { 165 | font-family: inherit; /* 1 */ 166 | font-size: 100%; /* 1 */ 167 | line-height: 1.15; /* 1 */ 168 | margin: 0; /* 2 */ 169 | } 170 | 171 | /** 172 | * Show the overflow in IE. 173 | * 1. Show the overflow in Edge. 174 | */ 175 | 176 | button, 177 | input { /* 1 */ 178 | overflow: visible; 179 | } 180 | 181 | /** 182 | * Remove the inheritance of text transform in Edge, Firefox, and IE. 183 | * 1. Remove the inheritance of text transform in Firefox. 184 | */ 185 | 186 | button, 187 | select { /* 1 */ 188 | text-transform: none; 189 | } 190 | 191 | /** 192 | * Correct the inability to style clickable types in iOS and Safari. 193 | */ 194 | 195 | button, 196 | [type="button"], 197 | [type="reset"], 198 | [type="submit"] { 199 | -webkit-appearance: button; 200 | } 201 | 202 | /** 203 | * Remove the inner border and padding in Firefox. 204 | */ 205 | 206 | button::-moz-focus-inner, 207 | [type="button"]::-moz-focus-inner, 208 | [type="reset"]::-moz-focus-inner, 209 | [type="submit"]::-moz-focus-inner { 210 | border-style: none; 211 | padding: 0; 212 | } 213 | 214 | /** 215 | * Restore the focus styles unset by the previous rule. 216 | */ 217 | 218 | button:-moz-focusring, 219 | [type="button"]:-moz-focusring, 220 | [type="reset"]:-moz-focusring, 221 | [type="submit"]:-moz-focusring { 222 | outline: 1px dotted ButtonText; 223 | } 224 | 225 | /** 226 | * Correct the padding in Firefox. 227 | */ 228 | 229 | fieldset { 230 | padding: 0.35em 0.75em 0.625em; 231 | } 232 | 233 | /** 234 | * 1. Correct the text wrapping in Edge and IE. 235 | * 2. Correct the color inheritance from `fieldset` elements in IE. 236 | * 3. Remove the padding so developers are not caught out when they zero out 237 | * `fieldset` elements in all browsers. 238 | */ 239 | 240 | legend { 241 | box-sizing: border-box; /* 1 */ 242 | color: inherit; /* 2 */ 243 | display: table; /* 1 */ 244 | max-width: 100%; /* 1 */ 245 | padding: 0; /* 3 */ 246 | white-space: normal; /* 1 */ 247 | } 248 | 249 | /** 250 | * Add the correct vertical alignment in Chrome, Firefox, and Opera. 251 | */ 252 | 253 | progress { 254 | vertical-align: baseline; 255 | } 256 | 257 | /** 258 | * Remove the default vertical scrollbar in IE 10+. 259 | */ 260 | 261 | textarea { 262 | overflow: auto; 263 | } 264 | 265 | /** 266 | * 1. Add the correct box sizing in IE 10. 267 | * 2. Remove the padding in IE 10. 268 | */ 269 | 270 | [type="checkbox"], 271 | [type="radio"] { 272 | box-sizing: border-box; /* 1 */ 273 | padding: 0; /* 2 */ 274 | } 275 | 276 | /** 277 | * Correct the cursor style of increment and decrement buttons in Chrome. 278 | */ 279 | 280 | [type="number"]::-webkit-inner-spin-button, 281 | [type="number"]::-webkit-outer-spin-button { 282 | height: auto; 283 | } 284 | 285 | /** 286 | * 1. Correct the odd appearance in Chrome and Safari. 287 | * 2. Correct the outline style in Safari. 288 | */ 289 | 290 | [type="search"] { 291 | -webkit-appearance: textfield; /* 1 */ 292 | outline-offset: -2px; /* 2 */ 293 | } 294 | 295 | /** 296 | * Remove the inner padding in Chrome and Safari on macOS. 297 | */ 298 | 299 | [type="search"]::-webkit-search-decoration { 300 | -webkit-appearance: none; 301 | } 302 | 303 | /** 304 | * 1. Correct the inability to style clickable types in iOS and Safari. 305 | * 2. Change font properties to `inherit` in Safari. 306 | */ 307 | 308 | ::-webkit-file-upload-button { 309 | -webkit-appearance: button; /* 1 */ 310 | font: inherit; /* 2 */ 311 | } 312 | 313 | /* Interactive 314 | ========================================================================== */ 315 | 316 | /* 317 | * Add the correct display in Edge, IE 10+, and Firefox. 318 | */ 319 | 320 | details { 321 | display: block; 322 | } 323 | 324 | /* 325 | * Add the correct display in all browsers. 326 | */ 327 | 328 | summary { 329 | display: list-item; 330 | } 331 | 332 | /* Misc 333 | ========================================================================== */ 334 | 335 | /** 336 | * Add the correct display in IE 10+. 337 | */ 338 | 339 | template { 340 | display: none; 341 | } 342 | 343 | /** 344 | * Add the correct display in IE 10. 345 | */ 346 | 347 | [hidden] { 348 | display: none; 349 | } 350 | 351 | 352 | 353 | /*! https://github.com/a11yproject/a11yproject.com/blob/main/src/css/base/_resets.scss */ 354 | *, 355 | *::before, 356 | *::after { 357 | box-sizing: border-box; 358 | margin: 0; 359 | padding: 0; 360 | vertical-align: baseline; 361 | } 362 | 363 | /* Removes borders from linked images */ 364 | a img { 365 | border: none; 366 | } 367 | 368 | 369 | b, 370 | strong { 371 | font-weight: 700; 372 | } 373 | 374 | button, 375 | input[type="button"] { 376 | border: 0; 377 | } 378 | 379 | 380 | em, 381 | cite, 382 | i { 383 | font-style: italic; 384 | } 385 | 386 | img, 387 | figure, 388 | picture { 389 | border: 0; 390 | display: block; 391 | height: auto; 392 | max-width: 100%; 393 | } 394 | 395 | h1, 396 | h2, 397 | h3, 398 | h4, 399 | h5, 400 | h6 { 401 | font-weight: 500; 402 | } 403 | 404 | sub { 405 | text-transform: lowercase; 406 | font-size: inherit; 407 | font-variant-position: sub; 408 | } 409 | 410 | sup { 411 | text-transform: lowercase; 412 | font-variant-position: super; 413 | } 414 | 415 | textarea { 416 | overflow: auto; 417 | resize: vertical; 418 | } -------------------------------------------------------------------------------- /public/assets/styles/water.css: -------------------------------------------------------------------------------- 1 | /* adapted from https://github.com/kognise/water.css */ 2 | :root { 3 | --body-font: serif; 4 | --background-body: #fff; 5 | --background-ui: #f7f7f7; 6 | --background-alt: #f7f7f7; 7 | --selection: #9e9e9e; 8 | --text-main: #363636; 9 | --links: #0076d1; 10 | --focus: rgba(0, 150, 191, 0.67); 11 | --border: #dbdbdb; 12 | --animation-duration: 0.1s; 13 | --button-hover: #ddd; 14 | --scrollbar-thumb: #d5d5d5; 15 | --scrollbar-thumb-hover: #c4c4c4; 16 | --form-font: sans-serif; 17 | --form-placeholder: #949494; 18 | --form-text: #000; 19 | --input-thumb: #000; 20 | --highlight: #ff0; 21 | --select-arrow: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='63' width='117' fill='%23161f27'%3E%3Cpath d='M115 2c-1-2-4-2-5 0L59 53 7 2a4 4 0 00-5 5l54 54 2 2 3-2 54-54c2-1 2-4 0-5z'/%3E%3C/svg%3E"); 22 | } 23 | html { 24 | scrollbar-color: var(--scrollbar-thumb) var(--background-body); 25 | scrollbar-width: thin; 26 | } 27 | body { 28 | line-height: 1.4; 29 | word-wrap: break-word; 30 | color: var(--text-main); 31 | background: var(--background-body); 32 | font-family: var(--body-font); 33 | text-rendering: optimizeLegibility; 34 | font-feature-settings: 'kern' 1, 'onum' 0, 'liga' 0, 'tnum' 1; 35 | } 36 | h1, 37 | h2, 38 | h3, 39 | h4, 40 | h5, 41 | h6 { 42 | margin: 1rem 0; 43 | } 44 | p { 45 | margin: 1rem 0; 46 | } 47 | button, 48 | input, 49 | textarea { 50 | transition: background-color var(--animation-duration) linear, border-color var(--animation-duration) linear, color var(--animation-duration) linear, box-shadow var(--animation-duration) linear, transform var(--animation-duration) ease; 51 | } 52 | mark { 53 | background-color: var(--highlight); 54 | border-radius: 2px; 55 | padding: 0 2px; 56 | } 57 | button, 58 | input[type="button"], 59 | input[type="checkbox"], 60 | input[type="radio"], 61 | input[type="range"], 62 | input[type="submit"], 63 | select { 64 | cursor: pointer; 65 | } 66 | input:not([type="checkbox"]):not([type="radio"]), 67 | select { 68 | display: block; 69 | } 70 | button, 71 | input, 72 | select, 73 | textarea { 74 | color: var(--form-text); 75 | background-color: var(--background-ui); 76 | font-family: var(--form-font); 77 | font-size: inherit; 78 | padding: 0.5em; 79 | border: none; 80 | border-radius: 4px; 81 | outline: none; 82 | } 83 | input[type="checkbox"], 84 | input[type="radio"] { 85 | height: 1em; 86 | width: 1em; 87 | } 88 | input[type="radio"] { 89 | border-radius: 100%; 90 | } 91 | input { 92 | vertical-align: top; 93 | } 94 | label { 95 | vertical-align: middle; 96 | margin-bottom: 4px; 97 | display: inline-block; 98 | } 99 | button, 100 | input:not([type="checkbox"]):not([type="radio"]), 101 | input[type="range"], 102 | select, 103 | textarea { 104 | -webkit-appearance: none; 105 | } 106 | textarea { 107 | display: block; 108 | margin-right: 0; 109 | box-sizing: border-box; 110 | resize: vertical; 111 | } 112 | textarea:not([cols]) { 113 | width: 100%; 114 | } 115 | textarea:not([rows]) { 116 | min-height: 40px; 117 | height: 140px; 118 | } 119 | select { 120 | background: var(--background-ui) var(--select-arrow) calc(100% - 12px) 50%/12px no-repeat; 121 | padding-right: 32px; 122 | } 123 | select::-ms-expand { 124 | display: none; 125 | } 126 | select[multiple] { 127 | padding-right: 8px; 128 | background-image: none; 129 | overflow-y: auto; 130 | } 131 | button:hover, 132 | input[type="button"]:hover, 133 | input[type="submit"]:hover { 134 | background: var(--button-hover); 135 | } 136 | button:focus, 137 | input:focus, 138 | select:focus, 139 | textarea:focus { 140 | box-shadow: 0 0 0 2px rgba(0, 150, 191, 0.67); 141 | box-shadow: 0 0 0 2px var(--focus); 142 | } 143 | button:disabled, 144 | input:disabled, 145 | select:disabled, 146 | textarea:disabled { 147 | cursor: not-allowed; 148 | opacity: 0.5; 149 | } 150 | ::-moz-placeholder { 151 | color: var(--form-placeholder); 152 | } 153 | :-ms-input-placeholder { 154 | color: var(--form-placeholder); 155 | } 156 | ::-ms-input-placeholder { 157 | color: var(--form-placeholder); 158 | } 159 | ::placeholder { 160 | color: var(--form-placeholder); 161 | } 162 | fieldset { 163 | border: 1px solid var(--focus); 164 | border-radius: 6px; 165 | margin: 0 0 12px; 166 | padding: 10px; 167 | } 168 | legend { 169 | font-size: 0.9em; 170 | font-weight: 600; 171 | } 172 | input[type="range"] { 173 | padding: 0; 174 | margin: 0; 175 | background: transparent; 176 | } 177 | input[type="range"]:focus { 178 | outline: none; 179 | } 180 | input[type="range"]::-webkit-slider-runnable-track { 181 | width: 100%; 182 | height: 10px; 183 | -webkit-transition: 0.2s; 184 | transition: 0.2s; 185 | background: var(--background-ui); 186 | border-radius: 4px; 187 | } 188 | input[type="range"]::-webkit-slider-thumb { 189 | height: 20px; 190 | width: 20px; 191 | border-radius: 50%; 192 | background: var(--input-thumb); 193 | -webkit-appearance: none; 194 | margin-top: -5px; 195 | } 196 | input[type="range"]:focus::-webkit-slider-runnable-track { 197 | background: var(--background-ui); 198 | } 199 | input[type="range"]::-moz-range-track { 200 | width: 100%; 201 | height: 10px; 202 | -moz-transition: 0.2s; 203 | transition: 0.2s; 204 | background: var(--background-ui); 205 | border-radius: 4px; 206 | } 207 | input[type="range"]::-moz-range-thumb { 208 | box-shadow: 1px 1px 1px #000, 0 0 1px #0d0d0d; 209 | height: 20px; 210 | width: 20px; 211 | border-radius: 50%; 212 | background: var(--input-thumb); 213 | } 214 | input[type="range"]::-ms-track { 215 | width: 100%; 216 | height: 10px; 217 | background: transparent; 218 | border-color: transparent; 219 | border-width: 16px 0; 220 | color: transparent; 221 | } 222 | input[type="range"]::-ms-fill-lower, 223 | input[type="range"]::-ms-fill-upper { 224 | background: var(--background-ui); 225 | border: 0.2px solid #010101; 226 | border-radius: 4px; 227 | box-shadow: 1px 1px 1px #000, 0 0 1px #0d0d0d; 228 | } 229 | input[type="range"]::-ms-thumb { 230 | height: 20px; 231 | width: 20px; 232 | border-radius: 50%; 233 | background: var(--input-thumb); 234 | } 235 | input[type="range"]:focus::-ms-fill-lower, 236 | input[type="range"]:focus::-ms-fill-upper { 237 | background: var(--background-ui); 238 | } 239 | a { 240 | color: var(--links); 241 | } 242 | a:hover { 243 | 244 | } 245 | img, 246 | video { 247 | max-width: 100%; 248 | height: auto; 249 | } 250 | hr { 251 | border: none; 252 | border-top: 1px solid var(--border); 253 | } 254 | table { 255 | border-collapse: collapse; 256 | margin-bottom: 10px; 257 | width: 100%; 258 | table-layout: fixed; 259 | } 260 | table caption, 261 | td, 262 | th { 263 | text-align: left; 264 | } 265 | td, 266 | th { 267 | padding: 6px; 268 | vertical-align: top; 269 | word-wrap: break-word; 270 | } 271 | thead { 272 | border-bottom: 1px solid var(--border); 273 | } 274 | tfoot { 275 | border-top: 1px solid var(--border); 276 | } 277 | tbody tr:nth-child(2n) { 278 | background-color: var(--background-alt); 279 | } 280 | ::-webkit-scrollbar { 281 | height: 10px; 282 | width: 10px; 283 | } 284 | ::-webkit-scrollbar-track { 285 | background: var(--background-ui); 286 | border-radius: 6px; 287 | } 288 | ::-webkit-scrollbar-thumb { 289 | background: var(--scrollbar-thumb); 290 | border-radius: 6px; 291 | } 292 | ::-webkit-scrollbar-thumb:hover { 293 | background: var(--scrollbar-thumb-hover); 294 | } 295 | ::-moz-selection { 296 | background-color: var(--selection); 297 | } 298 | ::selection { 299 | background-color: var(--selection); 300 | } 301 | details { 302 | display: flex; 303 | flex-direction: column; 304 | align-items: flex-start; 305 | background-color: var(--background-alt); 306 | padding: 10px 10px 0; 307 | margin: 1em 0; 308 | border-radius: 6px; 309 | overflow: hidden; 310 | } 311 | details[open] { 312 | padding: 10px; 313 | } 314 | details > :last-child { 315 | margin-bottom: 0; 316 | } 317 | details[open] summary { 318 | margin-bottom: 10px; 319 | } 320 | summary { 321 | display: list-item; 322 | background-color: var(--background-ui); 323 | padding: 10px; 324 | margin: -10px -10px 0; 325 | cursor: pointer; 326 | outline: none; 327 | } 328 | summary:focus, 329 | summary:hover { 330 | text-decoration: underline; 331 | } 332 | details > :not(summary) { 333 | margin-top: 0; 334 | } 335 | summary::-webkit-details-marker { 336 | color: var(--text-main); 337 | } 338 | -------------------------------------------------------------------------------- /public/assets/toast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/public/assets/toast.png -------------------------------------------------------------------------------- /public/assets/worker-image.js: -------------------------------------------------------------------------------- 1 | onmessage = function (event) { 2 | const { newImageData, contrast, brightness } = event.data; 3 | 4 | if (contrast != 0) { 5 | const newPixels = updateContrast(contrast, newImageData.data); 6 | newImageData.data.set(newPixels); 7 | } 8 | 9 | if (brightness != 0) { 10 | const newPixels = updateBrightness(brightness, newImageData.data); 11 | newImageData.data.set(newPixels); 12 | } 13 | 14 | postMessage({ newImageData }); 15 | }; 16 | 17 | const updateContrast = (value, pixelArray) => { 18 | let newPixelArray = [...pixelArray]; 19 | value = (parseFloat(value) || 0) + 1; 20 | 21 | for (let i = 0; i < newPixelArray.length; i += 4) { 22 | newPixelArray[i] = ((newPixelArray[i] / 255 - 0.5) * value + 0.5) * 255; 23 | newPixelArray[i + 1] = 24 | ((newPixelArray[i + 1] / 255 - 0.5) * value + 0.5) * 255; 25 | newPixelArray[i + 2] = 26 | ((newPixelArray[i + 2] / 255 - 0.5) * value + 0.5) * 255; 27 | } 28 | return newPixelArray; 29 | }; 30 | 31 | const updateBrightness = (value, pixelArray) => { 32 | let newPixelArray = [...pixelArray]; 33 | value = (parseFloat(value) || 0) + 1; 34 | 35 | for (let i = 0; i < newPixelArray.length; i += 4) { 36 | newPixelArray[i] += value; 37 | newPixelArray[i + 1] += value; 38 | newPixelArray[i + 2] += value; 39 | } 40 | return newPixelArray; 41 | }; 42 | -------------------------------------------------------------------------------- /public/assets/worker.js: -------------------------------------------------------------------------------- 1 | onmessage = function (event) { 2 | const { 3 | width, 4 | numberOfColumns, 5 | numberOfTrianglesHigh, 6 | numberOfPixelsPerTriangle, 7 | triangleHeight, 8 | triangleWidth, 9 | imagePixels, 10 | triangleIndices, 11 | invertedTriangleIndices, 12 | patternDarknesses, 13 | ratio, 14 | cachedTriangles, 15 | } = event.data; 16 | 17 | updateTriangles({ 18 | cachedTriangles, 19 | width, 20 | numberOfColumns, 21 | numberOfTrianglesHigh, 22 | numberOfPixelsPerTriangle, 23 | triangleHeight, 24 | triangleWidth, 25 | imagePixels, 26 | triangleIndices, 27 | invertedTriangleIndices, 28 | patternDarknesses, 29 | ratio, 30 | }); 31 | }; 32 | const updateTriangles = ({ 33 | cachedTriangles, 34 | width, 35 | numberOfColumns, 36 | numberOfTrianglesHigh, 37 | numberOfPixelsPerTriangle, 38 | triangleHeight, 39 | triangleWidth, 40 | imagePixels, 41 | triangleIndices, 42 | invertedTriangleIndices, 43 | patternDarknesses, 44 | ratio, 45 | }) => { 46 | let triangles = []; 47 | 48 | const getClosestPatternIndex = (darkness) => { 49 | const bucket = 50 | patternDarknesses.find((d) => d.start <= darkness && d.end >= darkness) || 51 | {}; 52 | return bucket.i || 0; 53 | }; 54 | const getModifiedTriangle = (triangle) => { 55 | let { patternIndex = 0, indices = [], rawRotation } = triangle; 56 | 57 | let rotation = rawRotation; 58 | let scaleY = 1; 59 | 60 | const flippedPatternIndices = [39]; 61 | 62 | let offset = [0, 0]; 63 | if (rotation == 330) { 64 | offset = [-62, -33]; 65 | } else if (rotation == 30) { 66 | offset = [65, -33]; 67 | } else if (rotation == 90) { 68 | offset = [0, 5]; 69 | } else if (rotation == 150) { 70 | offset = [65, 39]; 71 | } else if (rotation == 210) { 72 | offset = [-63, 36]; 73 | } else if (rotation == 270) { 74 | offset = [2, 2]; 75 | } 76 | 77 | if ( 78 | flippedPatternIndices.includes(patternIndex) && 79 | (indices[0] + indices[1]) % 2 == 0 80 | ) { 81 | if (rotation == 330) { 82 | rotation = 210; 83 | offset = [-63, 216]; 84 | } else if (rotation == 210) { 85 | rotation = 330; 86 | offset = [-63, 288]; 87 | } else if (rotation == 90) { 88 | offset = [0, 251]; 89 | } 90 | scaleY = -1; 91 | } 92 | 93 | return { 94 | ...triangle, 95 | offset, 96 | rotation, 97 | scaleY, 98 | }; 99 | }; 100 | 101 | if (!cachedTriangles) { 102 | const numbersPerPixel = ratio * 4; 103 | const triangleHalfHeight = triangleHeight / 2; 104 | 105 | getRange(numberOfColumns).forEach((columnIndex) => { 106 | getRange(numberOfTrianglesHigh).forEach((triangleIndex) => { 107 | const isInverted = !!(columnIndex % 2); 108 | 109 | let x1 = columnIndex * triangleWidth; 110 | let x2 = (columnIndex + 1) * triangleWidth; 111 | const y1 = triangleIndex * triangleHalfHeight; 112 | // const y2 = (triangleIndex + 1) * triangleHalfHeight; 113 | // const y3 = (triangleIndex + 2) * triangleHalfHeight; 114 | let topLeftCorner = [x1, y1]; 115 | if (isInverted) [x1, x2] = [x2, x1]; 116 | // (i) * n + j 117 | 118 | const pixelIndexStart = 119 | Math.round(topLeftCorner[1]) * Math.floor(width) + 120 | Math.round(topLeftCorner[0]); 121 | const pixelIndexEnd = pixelIndexStart + numberOfPixelsPerTriangle; 122 | 123 | const activePixelRange = imagePixels.slice( 124 | pixelIndexStart * numbersPerPixel, 125 | pixelIndexEnd * numbersPerPixel 126 | ); 127 | const activePixels = getRange(numberOfPixelsPerTriangle).map((i) => 128 | activePixelRange.slice( 129 | i * numbersPerPixel, 130 | i * numbersPerPixel + numbersPerPixel 131 | ) 132 | ); 133 | const indices = isInverted ? invertedTriangleIndices : triangleIndices; 134 | 135 | const activePixelDarknesses = indices.map((i) => { 136 | const [r, g, b, a] = activePixels[i] || []; 137 | return (a / 255) * (255 - sum([r, g, b]) / 3); 138 | }); 139 | const averageDarkness = 140 | sum(activePixelDarknesses) / activePixelDarknesses.length / 255; 141 | let closestPatternIndex = getClosestPatternIndex(averageDarkness); 142 | // if (averageDarkness == 1) debugger; 143 | if (averageDarkness < 0.001) return; 144 | // if (columnIndex == 3 && triangleIndex == 10) debugger; 145 | 146 | const rotations = [330, 150, 90, 30, 210, 270]; 147 | 148 | const rotationIndex = ((triangleIndex % 6) + (isInverted ? 3 : 0)) % 6; 149 | const rawRotation = rotations[rotationIndex]; 150 | 151 | const newTriangle = getModifiedTriangle({ 152 | // points: [ 153 | // [x1, y1], 154 | // [x2, y2], 155 | // [x1, y3], 156 | // [x1, y1], 157 | // ], 158 | averageDarkness, 159 | topLeftCorner, 160 | isInverted, 161 | indices: [columnIndex, triangleIndex], 162 | patternIndex: closestPatternIndex, 163 | rawRotation, 164 | }); 165 | 166 | triangles.push(newTriangle); 167 | postMessage({ triangles }); 168 | }); 169 | }); 170 | } else { 171 | triangles = cachedTriangles.map((triangle) => { 172 | const patternIndex = getClosestPatternIndex(triangle["averageDarkness"]); 173 | return getModifiedTriangle({ ...triangle, patternIndex }); 174 | }); 175 | } 176 | 177 | postMessage({ triangles, isFinished: true }); 178 | cachedTriangles = triangles; 179 | }; 180 | 181 | const getRange = (n) => new Array(n).fill(0).map((_, i) => i); 182 | 183 | const flatten = (arr) => arr.reduce((a, b) => [...a, ...b]); 184 | 185 | const sum = (arr) => arr.reduce((a, b) => a + b, 0); 186 | -------------------------------------------------------------------------------- /public/build/bundle.css: -------------------------------------------------------------------------------- 1 | /* this file is blanked out when running in hot mode */ -------------------------------------------------------------------------------- /public/build/bundle.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | const d = window.document 3 | let wsServerUrl = window.location.protocol 4 | + '//' + (window.location.host || 'localhost').split(':')[0] 5 | + ':33440/'; 6 | 7 | if (!window['__ROLLUP_PLUGIN_HOT_RUNTIME']) { 8 | let loaded = false; 9 | const callbacks = []; 10 | window['__ROLLUP_PLUGIN_HOT_RUNTIME'] = { 11 | host: null, 12 | port: 33440, 13 | ws: false, 14 | hot: true, 15 | then: function(cb) { 16 | if (loaded) { 17 | setTimeout(cb, 0); 18 | } else { 19 | callbacks.push(cb); 20 | } 21 | } 22 | }; 23 | const script = d.createElement('script'); 24 | script.async = 1; 25 | script.src = wsServerUrl + 'runtime/hmr-runtime.js'; 26 | script.onload = () => { 27 | loaded = true; 28 | callbacks.splice(0, callbacks.length).forEach(function(cb) { 29 | cb(); 30 | }); 31 | }; 32 | d.head.appendChild(script); 33 | } 34 | window['__ROLLUP_PLUGIN_HOT_RUNTIME'].then(function() { 35 | System.import("/build/bundle.js@hot/src/main.js", wsServerUrl).catch(err => { 36 | console.error(err && err.stack || err); 37 | }); 38 | }); 39 | 40 | })(); 41 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /rollup.config-ssr.js: -------------------------------------------------------------------------------- 1 | import svelte from "rollup-plugin-svelte"; 2 | import sveltePreprocess from "svelte-preprocess"; 3 | import resolve from "@rollup/plugin-node-resolve"; 4 | import commonjs from "@rollup/plugin-commonjs"; 5 | import svg from "rollup-plugin-svg"; 6 | import json from "@rollup/plugin-json"; 7 | import dsv from "@rollup/plugin-dsv"; 8 | import execute from "rollup-plugin-execute"; 9 | 10 | const preprocess = sveltePreprocess({ 11 | postcss: { 12 | plugins: [require("autoprefixer")] 13 | } 14 | }); 15 | 16 | export default { 17 | input: "src/components/App.svelte", 18 | output: { 19 | format: "cjs", 20 | file: ".tmp/ssr.js" 21 | }, 22 | plugins: [ 23 | svelte({ 24 | compilerOptions: { generate: "ssr" }, 25 | emitCss: false, 26 | preprocess 27 | }), 28 | resolve({ 29 | browser: true, 30 | dedupe: ["svelte"] 31 | }), 32 | commonjs(), 33 | json(), 34 | dsv(), 35 | svg(), 36 | execute("node scripts/pre-render.js") 37 | ] 38 | }; 39 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import svelte from "rollup-plugin-svelte-hot"; 2 | import sveltePreprocess from "svelte-preprocess"; 3 | import resolve from "@rollup/plugin-node-resolve"; 4 | import commonjs from "@rollup/plugin-commonjs"; 5 | import svg from "rollup-plugin-svg"; 6 | import json from "@rollup/plugin-json"; 7 | import dsv from "@rollup/plugin-dsv"; 8 | import hmr from "rollup-plugin-hot"; 9 | import execute from "rollup-plugin-execute"; 10 | import { terser } from "rollup-plugin-terser"; 11 | 12 | const isWatch = !!process.env.ROLLUP_WATCH; 13 | const isLiveReload = !!process.env.LIVERELOAD; 14 | const isDev = isWatch || isLiveReload; 15 | const isProduction = !isDev; 16 | const isHot = isWatch && !isLiveReload; 17 | 18 | const preprocess = sveltePreprocess({ 19 | postcss: { 20 | plugins: [require("autoprefixer")] 21 | } 22 | }); 23 | 24 | 25 | function serve() { 26 | let server; 27 | 28 | function toExit() { 29 | if (server) server.kill(0); 30 | } 31 | 32 | return { 33 | name: 'svelte/template:serve', 34 | writeBundle() { 35 | if (server) return; 36 | server = require('child_process').spawn( 37 | 'npm', 38 | ['run', 'start', '--', '--dev'], 39 | { 40 | stdio: ['ignore', 'inherit', 'inherit'], 41 | shell: true, 42 | } 43 | ); 44 | 45 | process.on('SIGTERM', toExit); 46 | process.on('exit', toExit); 47 | }, 48 | }; 49 | } 50 | 51 | export default { 52 | input: "src/main.js", 53 | output: { 54 | sourcemap: true, 55 | format: "iife", 56 | name: "app", 57 | file: "public/build/bundle.js" 58 | }, 59 | plugins: [ 60 | svelte({ 61 | dev: !isProduction, 62 | hydratable: isProduction, 63 | css: css => { 64 | css.write("bundle.css"); 65 | }, 66 | hot: isHot && { 67 | optimistic: true, 68 | }, 69 | preprocess 70 | }), 71 | resolve({ 72 | browser: true, 73 | dedupe: ["svelte"] 74 | }), 75 | commonjs(), 76 | json(), 77 | dsv(), 78 | svg(), 79 | 80 | // In dev mode, call `npm run start` once 81 | // the bundle has been generated 82 | isDev && serve(), 83 | 84 | // Watch the `public` directory and refresh the 85 | // browser on changes when not in production 86 | isLiveReload && livereload('public'), 87 | 88 | // If we're building for production (npm run build 89 | // instead of npm run dev), minify 90 | isProduction && terser(), 91 | 92 | 93 | isDev && 94 | hmr({ 95 | public: "public", 96 | inMemory: true, 97 | compatModuleHot: !isHot 98 | }), 99 | 100 | isDev && execute("node scripts/copy-template.js") 101 | ], 102 | watch: { 103 | clearScreen: false 104 | } 105 | }; 106 | -------------------------------------------------------------------------------- /scripts/copy-template.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | 4 | const CWD = process.cwd(); 5 | const templatePath = path.resolve(CWD, "src/template.html"); 6 | const indexPath = path.resolve(CWD, "public/index.html"); 7 | 8 | const template = fs.readFileSync(templatePath, "utf8"); 9 | 10 | fs.writeFileSync(indexPath, template); 11 | 12 | -------------------------------------------------------------------------------- /scripts/fetch-google.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const archieml = require("archieml"); 3 | const fetch = require('node-fetch'); 4 | 5 | const CWD = process.cwd(); 6 | const CONFIG_PATH = `${CWD}/config.json`; 7 | const CONFIG = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf8")); 8 | const { google } = CONFIG; 9 | 10 | const fetchGoogle = async ({ id, gid }) => { 11 | console.log(`fetching...${id}`); 12 | 13 | const base= "https://docs.google.com"; 14 | const post = gid ? `spreadsheets/u/1/d/${id}/export?format=csv&id=${id}&gid=${gid}` : `document/d/${id}/export?format=txt`; 15 | const url = `${base}/${post}`; 16 | 17 | try { 18 | const response = await fetch(url); 19 | const text = await response.text(); 20 | 21 | if (gid) return text; 22 | 23 | const parsed = archieml.load(text); 24 | const str = JSON.stringify(parsed); 25 | return str; 26 | 27 | } catch (err) { 28 | throw new Error(err); 29 | } 30 | }; 31 | 32 | (async () => { 33 | for (let d of google) { 34 | try { 35 | const str = await fetchGoogle(d); 36 | const file = `${CWD}/${d.filepath}`; 37 | fs.writeFileSync(file, str); 38 | } catch (err) { 39 | console.log(err); 40 | } 41 | } 42 | })(); -------------------------------------------------------------------------------- /scripts/outline-svg.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | const paper = require("paper"); 4 | const CWD = process.cwd(); 5 | const { clipperLib, clipperOffset, clipperUnite } = require("paper-clipper"); 6 | 7 | const outlineStroke = require("svg-outline-stroke"); 8 | const inPath = path.resolve(CWD, "scripts/export.svg"); 9 | const outPath = path.resolve(CWD, "scripts/export-processed.svg"); 10 | const inputStr = fs.readFileSync(inPath, "utf8"); 11 | 12 | const main = async () => { 13 | console.log("cleaning"); 14 | // const outlined = await outlineStroke(inputStr); 15 | const project = new paper.Project(); 16 | 17 | const svg = project.importSVG(inputStr); 18 | 19 | const clipper = await clipperLib.loadNativeClipperLibInstanceAsync( 20 | clipperLib.NativeClipperLibRequestedFormat.WasmWithAsmJsFallback 21 | ); 22 | 23 | console.log("outlining paths"); 24 | let runningPaths = []; 25 | const mergeChildren = async (group, depth = 0) => { 26 | return new Promise(async (resolve) => { 27 | if (group.children) { 28 | let i = 0; 29 | // const children = group.children.map((d) => d.clone()); 30 | for (const child of group.children) { 31 | i++; 32 | if (depth < 2) 33 | console.log(`outlining ${i} of ${group.children.length} paths`); 34 | await mergeChildren(child, depth + 1); 35 | } 36 | } else { 37 | if (group.segments && group.type != "rectangle" && group.strokeWidth) { 38 | try { 39 | const clone = { ...group }; 40 | const newPath = await clipperOffset(clipper)( 41 | clone, 42 | clone.strokeWidth 43 | ); 44 | runningPaths = [...runningPaths, ...newPath]; 45 | 46 | // if (runningPaths.length > 0) { 47 | // const unitedPaths = runningPaths[0].unite(newPath[0]); 48 | // runningPaths = [unitedPaths]; 49 | // } else { 50 | // runningPaths = [...runningPaths, ...newPath]; 51 | // } 52 | } catch (e) { 53 | console.log("Issue outlining path", group, e); 54 | } 55 | } 56 | } 57 | 58 | // if (runningPaths.length > 1000) { 59 | // const unitedPaths = await clipperUnite(clipper)(runningPaths); 60 | // runningPaths = [unitedPaths]; 61 | // } 62 | resolve(); 63 | }); 64 | }; 65 | await mergeChildren(svg); 66 | 67 | console.log(`uniting ${runningPaths.length} paths`); 68 | const unitedPaths = await clipperUnite(clipper)(runningPaths); 69 | 70 | // // Offset a Paper.js Path by 10 pixels 71 | // const offsetPaths = await clipperOffset(clipper)(path, 10) 72 | 73 | // // Unite two Paper.js Paths 74 | // const paths = [new paper.Path(..), new paper.Path(..)] 75 | // const unitedPaths = await clipperUnite(clipper)(paperPaths) 76 | 77 | const newLayer = new paper.Layer(); 78 | newLayer.addChildren(unitedPaths); 79 | 80 | svg.clear(); 81 | svg.addLayer(newLayer); 82 | 83 | console.log("exporting"); 84 | const result = project.exportSVG(svg); 85 | 86 | fs.writeFileSync(outPath, result); 87 | }; 88 | main(); 89 | -------------------------------------------------------------------------------- /scripts/pre-render.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | const shell = require("shelljs"); 4 | 5 | const CWD = process.cwd(); 6 | const templatePath = path.resolve(CWD, "src/template.html"); 7 | const inPath = path.resolve(CWD, "public"); 8 | const outPath = path.resolve(CWD, "ssr"); 9 | const tmpPath = path.resolve(CWD, ".tmp"); 10 | const ssrPath = `${tmpPath}/ssr.js`; 11 | 12 | shell.cp("-Rf", `${inPath}/*`, tmpPath); 13 | shell.mkdir("-p", outPath); 14 | shell.mkdir("-p", tmpPath); 15 | 16 | const template = fs.readFileSync(templatePath, "utf8"); 17 | const app = require(ssrPath); 18 | 19 | const version = Date.now(); 20 | const { html, head } = app.render(); 21 | 22 | const result = template 23 | .replace("", html) 24 | .replace("", head) 25 | .replace(/\.css/g, `.css?version=${version}`) 26 | .replace(/\.js/g, `.js?version=${version}`); 27 | 28 | fs.writeFileSync(`${tmpPath}/index.html`, result); 29 | shell.rm(`${tmpPath}/ssr.js`); 30 | shell.cp("-Rf", `${tmpPath}/*`, outPath); 31 | shell.rm("-Rf", tmpPath); 32 | 33 | process.exit(); 34 | -------------------------------------------------------------------------------- /src/actions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wattenberger/kumiko/c0f48ec892d22edbd6426fee1ddf6eee5d4b224e/src/actions/.gitkeep -------------------------------------------------------------------------------- /src/actions/css.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This action lets you dynmically change value of CSS variable 3 | * example: 4 | *

Hi

5 | * 6 | * in your style tag: 7 | * p { 8 | * color: var(--color); 9 | * } 10 | */ 11 | 12 | export default function css(node, properties) { 13 | function setProperties() { 14 | if (properties) { 15 | for (const prop of Object.keys(properties)) { 16 | node.style.setProperty(`--${prop}`, properties[prop]); 17 | } 18 | } 19 | } 20 | 21 | setProperties(); 22 | 23 | return { 24 | update(newProperties) { 25 | properties = newProperties; 26 | setProperties(); 27 | }, 28 | }; 29 | } -------------------------------------------------------------------------------- /src/actions/inView.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This action triggers a custom event on node entering/exiting the viewport. 3 | * example: 4 | *

console.log("enter")} 7 | * on:exit={() => console.log("exit")} 8 | * > 9 | * 10 | * optional params { root, top, bottom } 11 | * top and bottom are numbers 12 | * use:inView={ bottom: 100 } // 100 pixels from bottom of viewport 13 | */ 14 | 15 | export default function inView(node, params = {}) { 16 | let observer; 17 | 18 | const handleIntersect = (e) => { 19 | const v = e[0].isIntersecting ? "enter" : "exit"; 20 | node.dispatchEvent(new CustomEvent(v)); 21 | }; 22 | 23 | const setObserver = ({ root, top, bottom }) => { 24 | const marginTop = top ? top * -1 : 0; 25 | const marginBottom = bottom ? bottom * -1 : 0; 26 | const rootMargin = `${marginTop}px 0px ${marginBottom}px 0px`; 27 | const options = { root, rootMargin }; 28 | if (observer) observer.disconnect(); 29 | observer = new IntersectionObserver(handleIntersect, options);; 30 | observer.observe(node); 31 | } 32 | 33 | setObserver(params); 34 | 35 | return { 36 | update(params) { 37 | setObserver(params); 38 | }, 39 | 40 | destroy() { 41 | if (observer) observer.disconnect(); 42 | } 43 | }; 44 | } -------------------------------------------------------------------------------- /src/components/App.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 |

11 | 12 |
13 | background pattern 14 | background pattern 15 |
16 |
17 |

18 | Welcome! Kumiko is an ancient Japanese woodworking technique, which involves 19 | slotting together many tiny pieces into a lattice. Inspired by 20 | 24 | this video 25 | 26 | , this tool is here to help generate kumiko patterns, based on any image. 27 |

28 |

29 | Import your own photo, play around with different patterns, and export the 30 | svg to use as you like! I'll be using it to lasercut a wall panel, and would 31 | love to see what you create! Tweet me at 32 | 33 | @wattenberger 34 | 35 | . 36 |

37 |
38 | 39 | 40 | 41 |