├── .gitignore ├── README.md ├── env.d.ts ├── index.html ├── jsx ├── jsx-dev-runtime.ts └── jsx-runtime.ts ├── package-lock.json ├── package.json ├── public ├── favicon.png └── logo.png ├── src ├── components │ ├── App │ │ ├── app.module.css │ │ └── index.tsx │ ├── Footer │ │ ├── footer.module.css │ │ └── index.tsx │ ├── Header │ │ ├── header.module.css │ │ └── index.tsx │ ├── Router │ │ └── index.tsx │ └── StateViewer │ │ └── index.tsx ├── lib │ ├── global.css │ ├── main.tsx │ ├── router.ts │ ├── state.ts │ └── utils.module.css └── pages │ ├── About │ └── index.tsx │ ├── Home │ └── index.tsx │ └── NotFound │ └── index.tsx └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | Hyperapp starter logo 4 | 5 |

6 |

7 | Hyperapp starter 8 |

9 | 10 | Starter template to get started quickly with Hyperapp + TypeScript + Vite. 11 | 12 | ## 🚀 Quick start: 13 | 14 | [Click here to use this template](https://github.com/loteoo/hyperapp-starter/generate), or run these commands: 15 | 16 | ``` 17 | # Clone project 18 | git clone https://github.com/loteoo/hyperapp-starter.git 19 | 20 | cd hyperapp-starter 21 | 22 | npm i # Install dependencies 23 | npm run dev # Dev server 24 | ``` 25 | 26 | ``` 27 | npm run build # Build for production 28 | npm run preview # Preview production build 29 | ``` 30 | 31 | Or use a [.zip download](https://github.com/loteoo/hyperapp-starter/archive/main.zip) 32 | 33 | ## Features 34 | 35 | - [Vite](https://vitejs.dev/) for dev tooling 36 | - JSX ready to go 37 | - Strict TypeScript 38 | - Typed CSS modules (enable workspace TS version) 39 | - Pages + SPA router & navigation 40 | 41 | ## Live demo 42 | 43 | See live demo here: https://hyperapp-starter.pages.dev/ 44 | 45 | --- 46 | 47 | Basic CRUD actions with hyperapp 2.0 48 | https://github.com/loteoo/hyperapp-todolist 49 | 50 | 53 | 54 | --- 55 | 56 | Give the repo a star if you like this! 57 | -------------------------------------------------------------------------------- /env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import { VNode, ElementVNode, Props } from "hyperapp"; 4 | import { State } from '/src/lib/state' 5 | 6 | declare global { 7 | namespace JSX { 8 | type S = State; 9 | type Element = ElementVNode; 10 | interface IntrinsicElements { 11 | [elemName: string]: Props; 12 | } 13 | } 14 | } 15 | 16 | export { }; 17 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Hyperapp Starter 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /jsx/jsx-dev-runtime.ts: -------------------------------------------------------------------------------- 1 | export { jsx as jsxDEV } from './jsx-runtime' 2 | -------------------------------------------------------------------------------- /jsx/jsx-runtime.ts: -------------------------------------------------------------------------------- 1 | import { MaybeVNode, h, text } from "hyperapp" 2 | 3 | const childNode = (child: MaybeVNode) => ["string", "number"].includes(typeof child) ? text(child) : child; 4 | 5 | export const jsx = (tag: any, { children, ...props }: any, key: any) => 6 | typeof tag === "function" 7 | ? tag({ ...props, key }, children) 8 | : h( 9 | tag, 10 | { ...props, key }, 11 | [].concat(children).map(childNode) 12 | ) 13 | 14 | export const jsxs = jsx -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hyperapp-starter", 3 | "version": "0.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "hyperapp-starter", 9 | "version": "0.0.0", 10 | "dependencies": { 11 | "hyperapp": "^2.0.22" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.2.2", 15 | "typescript-plugin-css-modules": "^5.1.0", 16 | "vite": "^5.3.1" 17 | } 18 | }, 19 | "node_modules/@adobe/css-tools": { 20 | "version": "4.3.3", 21 | "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz", 22 | "integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==", 23 | "dev": true 24 | }, 25 | "node_modules/@esbuild/aix-ppc64": { 26 | "version": "0.21.5", 27 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", 28 | "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", 29 | "cpu": [ 30 | "ppc64" 31 | ], 32 | "dev": true, 33 | "optional": true, 34 | "os": [ 35 | "aix" 36 | ], 37 | "engines": { 38 | "node": ">=12" 39 | } 40 | }, 41 | "node_modules/@esbuild/android-arm": { 42 | "version": "0.21.5", 43 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", 44 | "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", 45 | "cpu": [ 46 | "arm" 47 | ], 48 | "dev": true, 49 | "optional": true, 50 | "os": [ 51 | "android" 52 | ], 53 | "engines": { 54 | "node": ">=12" 55 | } 56 | }, 57 | "node_modules/@esbuild/android-arm64": { 58 | "version": "0.21.5", 59 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", 60 | "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", 61 | "cpu": [ 62 | "arm64" 63 | ], 64 | "dev": true, 65 | "optional": true, 66 | "os": [ 67 | "android" 68 | ], 69 | "engines": { 70 | "node": ">=12" 71 | } 72 | }, 73 | "node_modules/@esbuild/android-x64": { 74 | "version": "0.21.5", 75 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", 76 | "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", 77 | "cpu": [ 78 | "x64" 79 | ], 80 | "dev": true, 81 | "optional": true, 82 | "os": [ 83 | "android" 84 | ], 85 | "engines": { 86 | "node": ">=12" 87 | } 88 | }, 89 | "node_modules/@esbuild/darwin-arm64": { 90 | "version": "0.21.5", 91 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", 92 | "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", 93 | "cpu": [ 94 | "arm64" 95 | ], 96 | "dev": true, 97 | "optional": true, 98 | "os": [ 99 | "darwin" 100 | ], 101 | "engines": { 102 | "node": ">=12" 103 | } 104 | }, 105 | "node_modules/@esbuild/darwin-x64": { 106 | "version": "0.21.5", 107 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", 108 | "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", 109 | "cpu": [ 110 | "x64" 111 | ], 112 | "dev": true, 113 | "optional": true, 114 | "os": [ 115 | "darwin" 116 | ], 117 | "engines": { 118 | "node": ">=12" 119 | } 120 | }, 121 | "node_modules/@esbuild/freebsd-arm64": { 122 | "version": "0.21.5", 123 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", 124 | "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", 125 | "cpu": [ 126 | "arm64" 127 | ], 128 | "dev": true, 129 | "optional": true, 130 | "os": [ 131 | "freebsd" 132 | ], 133 | "engines": { 134 | "node": ">=12" 135 | } 136 | }, 137 | "node_modules/@esbuild/freebsd-x64": { 138 | "version": "0.21.5", 139 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", 140 | "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", 141 | "cpu": [ 142 | "x64" 143 | ], 144 | "dev": true, 145 | "optional": true, 146 | "os": [ 147 | "freebsd" 148 | ], 149 | "engines": { 150 | "node": ">=12" 151 | } 152 | }, 153 | "node_modules/@esbuild/linux-arm": { 154 | "version": "0.21.5", 155 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", 156 | "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", 157 | "cpu": [ 158 | "arm" 159 | ], 160 | "dev": true, 161 | "optional": true, 162 | "os": [ 163 | "linux" 164 | ], 165 | "engines": { 166 | "node": ">=12" 167 | } 168 | }, 169 | "node_modules/@esbuild/linux-arm64": { 170 | "version": "0.21.5", 171 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", 172 | "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", 173 | "cpu": [ 174 | "arm64" 175 | ], 176 | "dev": true, 177 | "optional": true, 178 | "os": [ 179 | "linux" 180 | ], 181 | "engines": { 182 | "node": ">=12" 183 | } 184 | }, 185 | "node_modules/@esbuild/linux-ia32": { 186 | "version": "0.21.5", 187 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", 188 | "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", 189 | "cpu": [ 190 | "ia32" 191 | ], 192 | "dev": true, 193 | "optional": true, 194 | "os": [ 195 | "linux" 196 | ], 197 | "engines": { 198 | "node": ">=12" 199 | } 200 | }, 201 | "node_modules/@esbuild/linux-loong64": { 202 | "version": "0.21.5", 203 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", 204 | "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", 205 | "cpu": [ 206 | "loong64" 207 | ], 208 | "dev": true, 209 | "optional": true, 210 | "os": [ 211 | "linux" 212 | ], 213 | "engines": { 214 | "node": ">=12" 215 | } 216 | }, 217 | "node_modules/@esbuild/linux-mips64el": { 218 | "version": "0.21.5", 219 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", 220 | "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", 221 | "cpu": [ 222 | "mips64el" 223 | ], 224 | "dev": true, 225 | "optional": true, 226 | "os": [ 227 | "linux" 228 | ], 229 | "engines": { 230 | "node": ">=12" 231 | } 232 | }, 233 | "node_modules/@esbuild/linux-ppc64": { 234 | "version": "0.21.5", 235 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", 236 | "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", 237 | "cpu": [ 238 | "ppc64" 239 | ], 240 | "dev": true, 241 | "optional": true, 242 | "os": [ 243 | "linux" 244 | ], 245 | "engines": { 246 | "node": ">=12" 247 | } 248 | }, 249 | "node_modules/@esbuild/linux-riscv64": { 250 | "version": "0.21.5", 251 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", 252 | "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", 253 | "cpu": [ 254 | "riscv64" 255 | ], 256 | "dev": true, 257 | "optional": true, 258 | "os": [ 259 | "linux" 260 | ], 261 | "engines": { 262 | "node": ">=12" 263 | } 264 | }, 265 | "node_modules/@esbuild/linux-s390x": { 266 | "version": "0.21.5", 267 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", 268 | "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", 269 | "cpu": [ 270 | "s390x" 271 | ], 272 | "dev": true, 273 | "optional": true, 274 | "os": [ 275 | "linux" 276 | ], 277 | "engines": { 278 | "node": ">=12" 279 | } 280 | }, 281 | "node_modules/@esbuild/linux-x64": { 282 | "version": "0.21.5", 283 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", 284 | "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", 285 | "cpu": [ 286 | "x64" 287 | ], 288 | "dev": true, 289 | "optional": true, 290 | "os": [ 291 | "linux" 292 | ], 293 | "engines": { 294 | "node": ">=12" 295 | } 296 | }, 297 | "node_modules/@esbuild/netbsd-x64": { 298 | "version": "0.21.5", 299 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", 300 | "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", 301 | "cpu": [ 302 | "x64" 303 | ], 304 | "dev": true, 305 | "optional": true, 306 | "os": [ 307 | "netbsd" 308 | ], 309 | "engines": { 310 | "node": ">=12" 311 | } 312 | }, 313 | "node_modules/@esbuild/openbsd-x64": { 314 | "version": "0.21.5", 315 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", 316 | "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", 317 | "cpu": [ 318 | "x64" 319 | ], 320 | "dev": true, 321 | "optional": true, 322 | "os": [ 323 | "openbsd" 324 | ], 325 | "engines": { 326 | "node": ">=12" 327 | } 328 | }, 329 | "node_modules/@esbuild/sunos-x64": { 330 | "version": "0.21.5", 331 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", 332 | "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", 333 | "cpu": [ 334 | "x64" 335 | ], 336 | "dev": true, 337 | "optional": true, 338 | "os": [ 339 | "sunos" 340 | ], 341 | "engines": { 342 | "node": ">=12" 343 | } 344 | }, 345 | "node_modules/@esbuild/win32-arm64": { 346 | "version": "0.21.5", 347 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", 348 | "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", 349 | "cpu": [ 350 | "arm64" 351 | ], 352 | "dev": true, 353 | "optional": true, 354 | "os": [ 355 | "win32" 356 | ], 357 | "engines": { 358 | "node": ">=12" 359 | } 360 | }, 361 | "node_modules/@esbuild/win32-ia32": { 362 | "version": "0.21.5", 363 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", 364 | "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", 365 | "cpu": [ 366 | "ia32" 367 | ], 368 | "dev": true, 369 | "optional": true, 370 | "os": [ 371 | "win32" 372 | ], 373 | "engines": { 374 | "node": ">=12" 375 | } 376 | }, 377 | "node_modules/@esbuild/win32-x64": { 378 | "version": "0.21.5", 379 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", 380 | "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", 381 | "cpu": [ 382 | "x64" 383 | ], 384 | "dev": true, 385 | "optional": true, 386 | "os": [ 387 | "win32" 388 | ], 389 | "engines": { 390 | "node": ">=12" 391 | } 392 | }, 393 | "node_modules/@rollup/rollup-android-arm-eabi": { 394 | "version": "4.18.0", 395 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", 396 | "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", 397 | "cpu": [ 398 | "arm" 399 | ], 400 | "dev": true, 401 | "optional": true, 402 | "os": [ 403 | "android" 404 | ] 405 | }, 406 | "node_modules/@rollup/rollup-android-arm64": { 407 | "version": "4.18.0", 408 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", 409 | "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", 410 | "cpu": [ 411 | "arm64" 412 | ], 413 | "dev": true, 414 | "optional": true, 415 | "os": [ 416 | "android" 417 | ] 418 | }, 419 | "node_modules/@rollup/rollup-darwin-arm64": { 420 | "version": "4.18.0", 421 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", 422 | "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", 423 | "cpu": [ 424 | "arm64" 425 | ], 426 | "dev": true, 427 | "optional": true, 428 | "os": [ 429 | "darwin" 430 | ] 431 | }, 432 | "node_modules/@rollup/rollup-darwin-x64": { 433 | "version": "4.18.0", 434 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", 435 | "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", 436 | "cpu": [ 437 | "x64" 438 | ], 439 | "dev": true, 440 | "optional": true, 441 | "os": [ 442 | "darwin" 443 | ] 444 | }, 445 | "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 446 | "version": "4.18.0", 447 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", 448 | "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", 449 | "cpu": [ 450 | "arm" 451 | ], 452 | "dev": true, 453 | "optional": true, 454 | "os": [ 455 | "linux" 456 | ] 457 | }, 458 | "node_modules/@rollup/rollup-linux-arm-musleabihf": { 459 | "version": "4.18.0", 460 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", 461 | "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", 462 | "cpu": [ 463 | "arm" 464 | ], 465 | "dev": true, 466 | "optional": true, 467 | "os": [ 468 | "linux" 469 | ] 470 | }, 471 | "node_modules/@rollup/rollup-linux-arm64-gnu": { 472 | "version": "4.18.0", 473 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", 474 | "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", 475 | "cpu": [ 476 | "arm64" 477 | ], 478 | "dev": true, 479 | "optional": true, 480 | "os": [ 481 | "linux" 482 | ] 483 | }, 484 | "node_modules/@rollup/rollup-linux-arm64-musl": { 485 | "version": "4.18.0", 486 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", 487 | "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", 488 | "cpu": [ 489 | "arm64" 490 | ], 491 | "dev": true, 492 | "optional": true, 493 | "os": [ 494 | "linux" 495 | ] 496 | }, 497 | "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { 498 | "version": "4.18.0", 499 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", 500 | "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", 501 | "cpu": [ 502 | "ppc64" 503 | ], 504 | "dev": true, 505 | "optional": true, 506 | "os": [ 507 | "linux" 508 | ] 509 | }, 510 | "node_modules/@rollup/rollup-linux-riscv64-gnu": { 511 | "version": "4.18.0", 512 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", 513 | "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", 514 | "cpu": [ 515 | "riscv64" 516 | ], 517 | "dev": true, 518 | "optional": true, 519 | "os": [ 520 | "linux" 521 | ] 522 | }, 523 | "node_modules/@rollup/rollup-linux-s390x-gnu": { 524 | "version": "4.18.0", 525 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", 526 | "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", 527 | "cpu": [ 528 | "s390x" 529 | ], 530 | "dev": true, 531 | "optional": true, 532 | "os": [ 533 | "linux" 534 | ] 535 | }, 536 | "node_modules/@rollup/rollup-linux-x64-gnu": { 537 | "version": "4.18.0", 538 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", 539 | "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", 540 | "cpu": [ 541 | "x64" 542 | ], 543 | "dev": true, 544 | "optional": true, 545 | "os": [ 546 | "linux" 547 | ] 548 | }, 549 | "node_modules/@rollup/rollup-linux-x64-musl": { 550 | "version": "4.18.0", 551 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", 552 | "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", 553 | "cpu": [ 554 | "x64" 555 | ], 556 | "dev": true, 557 | "optional": true, 558 | "os": [ 559 | "linux" 560 | ] 561 | }, 562 | "node_modules/@rollup/rollup-win32-arm64-msvc": { 563 | "version": "4.18.0", 564 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", 565 | "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", 566 | "cpu": [ 567 | "arm64" 568 | ], 569 | "dev": true, 570 | "optional": true, 571 | "os": [ 572 | "win32" 573 | ] 574 | }, 575 | "node_modules/@rollup/rollup-win32-ia32-msvc": { 576 | "version": "4.18.0", 577 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", 578 | "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", 579 | "cpu": [ 580 | "ia32" 581 | ], 582 | "dev": true, 583 | "optional": true, 584 | "os": [ 585 | "win32" 586 | ] 587 | }, 588 | "node_modules/@rollup/rollup-win32-x64-msvc": { 589 | "version": "4.18.0", 590 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", 591 | "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", 592 | "cpu": [ 593 | "x64" 594 | ], 595 | "dev": true, 596 | "optional": true, 597 | "os": [ 598 | "win32" 599 | ] 600 | }, 601 | "node_modules/@types/estree": { 602 | "version": "1.0.5", 603 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", 604 | "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", 605 | "dev": true 606 | }, 607 | "node_modules/@types/postcss-modules-local-by-default": { 608 | "version": "4.0.2", 609 | "resolved": "https://registry.npmjs.org/@types/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.2.tgz", 610 | "integrity": "sha512-CtYCcD+L+trB3reJPny+bKWKMzPfxEyQpKIwit7kErnOexf5/faaGpkFy4I5AwbV4hp1sk7/aTg0tt0B67VkLQ==", 611 | "dev": true, 612 | "dependencies": { 613 | "postcss": "^8.0.0" 614 | } 615 | }, 616 | "node_modules/@types/postcss-modules-scope": { 617 | "version": "3.0.4", 618 | "resolved": "https://registry.npmjs.org/@types/postcss-modules-scope/-/postcss-modules-scope-3.0.4.tgz", 619 | "integrity": "sha512-//ygSisVq9kVI0sqx3UPLzWIMCmtSVrzdljtuaAEJtGoGnpjBikZ2sXO5MpH9SnWX9HRfXxHifDAXcQjupWnIQ==", 620 | "dev": true, 621 | "dependencies": { 622 | "postcss": "^8.0.0" 623 | } 624 | }, 625 | "node_modules/anymatch": { 626 | "version": "3.1.3", 627 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 628 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 629 | "dev": true, 630 | "dependencies": { 631 | "normalize-path": "^3.0.0", 632 | "picomatch": "^2.0.4" 633 | }, 634 | "engines": { 635 | "node": ">= 8" 636 | } 637 | }, 638 | "node_modules/balanced-match": { 639 | "version": "1.0.2", 640 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 641 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 642 | "dev": true 643 | }, 644 | "node_modules/binary-extensions": { 645 | "version": "2.3.0", 646 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", 647 | "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", 648 | "dev": true, 649 | "engines": { 650 | "node": ">=8" 651 | }, 652 | "funding": { 653 | "url": "https://github.com/sponsors/sindresorhus" 654 | } 655 | }, 656 | "node_modules/brace-expansion": { 657 | "version": "1.1.11", 658 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 659 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 660 | "dev": true, 661 | "dependencies": { 662 | "balanced-match": "^1.0.0", 663 | "concat-map": "0.0.1" 664 | } 665 | }, 666 | "node_modules/braces": { 667 | "version": "3.0.3", 668 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", 669 | "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 670 | "dev": true, 671 | "dependencies": { 672 | "fill-range": "^7.1.1" 673 | }, 674 | "engines": { 675 | "node": ">=8" 676 | } 677 | }, 678 | "node_modules/chokidar": { 679 | "version": "3.6.0", 680 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", 681 | "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", 682 | "dev": true, 683 | "dependencies": { 684 | "anymatch": "~3.1.2", 685 | "braces": "~3.0.2", 686 | "glob-parent": "~5.1.2", 687 | "is-binary-path": "~2.1.0", 688 | "is-glob": "~4.0.1", 689 | "normalize-path": "~3.0.0", 690 | "readdirp": "~3.6.0" 691 | }, 692 | "engines": { 693 | "node": ">= 8.10.0" 694 | }, 695 | "funding": { 696 | "url": "https://paulmillr.com/funding/" 697 | }, 698 | "optionalDependencies": { 699 | "fsevents": "~2.3.2" 700 | } 701 | }, 702 | "node_modules/concat-map": { 703 | "version": "0.0.1", 704 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 705 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 706 | "dev": true 707 | }, 708 | "node_modules/copy-anything": { 709 | "version": "2.0.6", 710 | "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", 711 | "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", 712 | "dev": true, 713 | "dependencies": { 714 | "is-what": "^3.14.1" 715 | }, 716 | "funding": { 717 | "url": "https://github.com/sponsors/mesqueeb" 718 | } 719 | }, 720 | "node_modules/cssesc": { 721 | "version": "3.0.0", 722 | "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", 723 | "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", 724 | "dev": true, 725 | "bin": { 726 | "cssesc": "bin/cssesc" 727 | }, 728 | "engines": { 729 | "node": ">=4" 730 | } 731 | }, 732 | "node_modules/debug": { 733 | "version": "4.3.5", 734 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", 735 | "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", 736 | "dev": true, 737 | "dependencies": { 738 | "ms": "2.1.2" 739 | }, 740 | "engines": { 741 | "node": ">=6.0" 742 | }, 743 | "peerDependenciesMeta": { 744 | "supports-color": { 745 | "optional": true 746 | } 747 | } 748 | }, 749 | "node_modules/dotenv": { 750 | "version": "16.4.5", 751 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", 752 | "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", 753 | "dev": true, 754 | "engines": { 755 | "node": ">=12" 756 | }, 757 | "funding": { 758 | "url": "https://dotenvx.com" 759 | } 760 | }, 761 | "node_modules/errno": { 762 | "version": "0.1.8", 763 | "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", 764 | "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", 765 | "dev": true, 766 | "optional": true, 767 | "dependencies": { 768 | "prr": "~1.0.1" 769 | }, 770 | "bin": { 771 | "errno": "cli.js" 772 | } 773 | }, 774 | "node_modules/esbuild": { 775 | "version": "0.21.5", 776 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", 777 | "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", 778 | "dev": true, 779 | "hasInstallScript": true, 780 | "bin": { 781 | "esbuild": "bin/esbuild" 782 | }, 783 | "engines": { 784 | "node": ">=12" 785 | }, 786 | "optionalDependencies": { 787 | "@esbuild/aix-ppc64": "0.21.5", 788 | "@esbuild/android-arm": "0.21.5", 789 | "@esbuild/android-arm64": "0.21.5", 790 | "@esbuild/android-x64": "0.21.5", 791 | "@esbuild/darwin-arm64": "0.21.5", 792 | "@esbuild/darwin-x64": "0.21.5", 793 | "@esbuild/freebsd-arm64": "0.21.5", 794 | "@esbuild/freebsd-x64": "0.21.5", 795 | "@esbuild/linux-arm": "0.21.5", 796 | "@esbuild/linux-arm64": "0.21.5", 797 | "@esbuild/linux-ia32": "0.21.5", 798 | "@esbuild/linux-loong64": "0.21.5", 799 | "@esbuild/linux-mips64el": "0.21.5", 800 | "@esbuild/linux-ppc64": "0.21.5", 801 | "@esbuild/linux-riscv64": "0.21.5", 802 | "@esbuild/linux-s390x": "0.21.5", 803 | "@esbuild/linux-x64": "0.21.5", 804 | "@esbuild/netbsd-x64": "0.21.5", 805 | "@esbuild/openbsd-x64": "0.21.5", 806 | "@esbuild/sunos-x64": "0.21.5", 807 | "@esbuild/win32-arm64": "0.21.5", 808 | "@esbuild/win32-ia32": "0.21.5", 809 | "@esbuild/win32-x64": "0.21.5" 810 | } 811 | }, 812 | "node_modules/fill-range": { 813 | "version": "7.1.1", 814 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", 815 | "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 816 | "dev": true, 817 | "dependencies": { 818 | "to-regex-range": "^5.0.1" 819 | }, 820 | "engines": { 821 | "node": ">=8" 822 | } 823 | }, 824 | "node_modules/fs.realpath": { 825 | "version": "1.0.0", 826 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 827 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", 828 | "dev": true 829 | }, 830 | "node_modules/fsevents": { 831 | "version": "2.3.3", 832 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 833 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 834 | "dev": true, 835 | "hasInstallScript": true, 836 | "optional": true, 837 | "os": [ 838 | "darwin" 839 | ], 840 | "engines": { 841 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 842 | } 843 | }, 844 | "node_modules/glob": { 845 | "version": "7.2.3", 846 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", 847 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", 848 | "deprecated": "Glob versions prior to v9 are no longer supported", 849 | "dev": true, 850 | "dependencies": { 851 | "fs.realpath": "^1.0.0", 852 | "inflight": "^1.0.4", 853 | "inherits": "2", 854 | "minimatch": "^3.1.1", 855 | "once": "^1.3.0", 856 | "path-is-absolute": "^1.0.0" 857 | }, 858 | "engines": { 859 | "node": "*" 860 | }, 861 | "funding": { 862 | "url": "https://github.com/sponsors/isaacs" 863 | } 864 | }, 865 | "node_modules/glob-parent": { 866 | "version": "5.1.2", 867 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 868 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 869 | "dev": true, 870 | "dependencies": { 871 | "is-glob": "^4.0.1" 872 | }, 873 | "engines": { 874 | "node": ">= 6" 875 | } 876 | }, 877 | "node_modules/graceful-fs": { 878 | "version": "4.2.11", 879 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", 880 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", 881 | "dev": true, 882 | "optional": true 883 | }, 884 | "node_modules/hyperapp": { 885 | "version": "2.0.22", 886 | "resolved": "https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.22.tgz", 887 | "integrity": "sha512-3uf9HjnjrhbfykowFNEObZewBEo4DXJIM+9FnGkiR9E4H2eh2f921SzMCMS69X5nN3A7KFfmZc9KCKh/7TQBFA==" 888 | }, 889 | "node_modules/iconv-lite": { 890 | "version": "0.6.3", 891 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 892 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 893 | "dev": true, 894 | "optional": true, 895 | "dependencies": { 896 | "safer-buffer": ">= 2.1.2 < 3.0.0" 897 | }, 898 | "engines": { 899 | "node": ">=0.10.0" 900 | } 901 | }, 902 | "node_modules/icss-utils": { 903 | "version": "5.1.0", 904 | "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", 905 | "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", 906 | "dev": true, 907 | "engines": { 908 | "node": "^10 || ^12 || >= 14" 909 | }, 910 | "peerDependencies": { 911 | "postcss": "^8.1.0" 912 | } 913 | }, 914 | "node_modules/image-size": { 915 | "version": "0.5.5", 916 | "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", 917 | "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", 918 | "dev": true, 919 | "optional": true, 920 | "bin": { 921 | "image-size": "bin/image-size.js" 922 | }, 923 | "engines": { 924 | "node": ">=0.10.0" 925 | } 926 | }, 927 | "node_modules/immutable": { 928 | "version": "4.3.6", 929 | "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz", 930 | "integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==", 931 | "dev": true 932 | }, 933 | "node_modules/inflight": { 934 | "version": "1.0.6", 935 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 936 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 937 | "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", 938 | "dev": true, 939 | "dependencies": { 940 | "once": "^1.3.0", 941 | "wrappy": "1" 942 | } 943 | }, 944 | "node_modules/inherits": { 945 | "version": "2.0.4", 946 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 947 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 948 | "dev": true 949 | }, 950 | "node_modules/is-binary-path": { 951 | "version": "2.1.0", 952 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 953 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 954 | "dev": true, 955 | "dependencies": { 956 | "binary-extensions": "^2.0.0" 957 | }, 958 | "engines": { 959 | "node": ">=8" 960 | } 961 | }, 962 | "node_modules/is-extglob": { 963 | "version": "2.1.1", 964 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 965 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 966 | "dev": true, 967 | "engines": { 968 | "node": ">=0.10.0" 969 | } 970 | }, 971 | "node_modules/is-glob": { 972 | "version": "4.0.3", 973 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 974 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 975 | "dev": true, 976 | "dependencies": { 977 | "is-extglob": "^2.1.1" 978 | }, 979 | "engines": { 980 | "node": ">=0.10.0" 981 | } 982 | }, 983 | "node_modules/is-number": { 984 | "version": "7.0.0", 985 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 986 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 987 | "dev": true, 988 | "engines": { 989 | "node": ">=0.12.0" 990 | } 991 | }, 992 | "node_modules/is-what": { 993 | "version": "3.14.1", 994 | "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", 995 | "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", 996 | "dev": true 997 | }, 998 | "node_modules/json5": { 999 | "version": "2.2.3", 1000 | "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", 1001 | "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", 1002 | "dev": true, 1003 | "bin": { 1004 | "json5": "lib/cli.js" 1005 | }, 1006 | "engines": { 1007 | "node": ">=6" 1008 | } 1009 | }, 1010 | "node_modules/less": { 1011 | "version": "4.2.0", 1012 | "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", 1013 | "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==", 1014 | "dev": true, 1015 | "dependencies": { 1016 | "copy-anything": "^2.0.1", 1017 | "parse-node-version": "^1.0.1", 1018 | "tslib": "^2.3.0" 1019 | }, 1020 | "bin": { 1021 | "lessc": "bin/lessc" 1022 | }, 1023 | "engines": { 1024 | "node": ">=6" 1025 | }, 1026 | "optionalDependencies": { 1027 | "errno": "^0.1.1", 1028 | "graceful-fs": "^4.1.2", 1029 | "image-size": "~0.5.0", 1030 | "make-dir": "^2.1.0", 1031 | "mime": "^1.4.1", 1032 | "needle": "^3.1.0", 1033 | "source-map": "~0.6.0" 1034 | } 1035 | }, 1036 | "node_modules/lilconfig": { 1037 | "version": "2.1.0", 1038 | "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", 1039 | "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", 1040 | "dev": true, 1041 | "engines": { 1042 | "node": ">=10" 1043 | } 1044 | }, 1045 | "node_modules/lodash.camelcase": { 1046 | "version": "4.3.0", 1047 | "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", 1048 | "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", 1049 | "dev": true 1050 | }, 1051 | "node_modules/make-dir": { 1052 | "version": "2.1.0", 1053 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", 1054 | "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", 1055 | "dev": true, 1056 | "optional": true, 1057 | "dependencies": { 1058 | "pify": "^4.0.1", 1059 | "semver": "^5.6.0" 1060 | }, 1061 | "engines": { 1062 | "node": ">=6" 1063 | } 1064 | }, 1065 | "node_modules/mime": { 1066 | "version": "1.6.0", 1067 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 1068 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 1069 | "dev": true, 1070 | "optional": true, 1071 | "bin": { 1072 | "mime": "cli.js" 1073 | }, 1074 | "engines": { 1075 | "node": ">=4" 1076 | } 1077 | }, 1078 | "node_modules/minimatch": { 1079 | "version": "3.1.2", 1080 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1081 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1082 | "dev": true, 1083 | "dependencies": { 1084 | "brace-expansion": "^1.1.7" 1085 | }, 1086 | "engines": { 1087 | "node": "*" 1088 | } 1089 | }, 1090 | "node_modules/minimist": { 1091 | "version": "1.2.8", 1092 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 1093 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 1094 | "dev": true, 1095 | "funding": { 1096 | "url": "https://github.com/sponsors/ljharb" 1097 | } 1098 | }, 1099 | "node_modules/ms": { 1100 | "version": "2.1.2", 1101 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1102 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1103 | "dev": true 1104 | }, 1105 | "node_modules/nanoid": { 1106 | "version": "3.3.7", 1107 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", 1108 | "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", 1109 | "dev": true, 1110 | "funding": [ 1111 | { 1112 | "type": "github", 1113 | "url": "https://github.com/sponsors/ai" 1114 | } 1115 | ], 1116 | "bin": { 1117 | "nanoid": "bin/nanoid.cjs" 1118 | }, 1119 | "engines": { 1120 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1121 | } 1122 | }, 1123 | "node_modules/needle": { 1124 | "version": "3.3.1", 1125 | "resolved": "https://registry.npmjs.org/needle/-/needle-3.3.1.tgz", 1126 | "integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==", 1127 | "dev": true, 1128 | "optional": true, 1129 | "dependencies": { 1130 | "iconv-lite": "^0.6.3", 1131 | "sax": "^1.2.4" 1132 | }, 1133 | "bin": { 1134 | "needle": "bin/needle" 1135 | }, 1136 | "engines": { 1137 | "node": ">= 4.4.x" 1138 | } 1139 | }, 1140 | "node_modules/normalize-path": { 1141 | "version": "3.0.0", 1142 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1143 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1144 | "dev": true, 1145 | "engines": { 1146 | "node": ">=0.10.0" 1147 | } 1148 | }, 1149 | "node_modules/once": { 1150 | "version": "1.4.0", 1151 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1152 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1153 | "dev": true, 1154 | "dependencies": { 1155 | "wrappy": "1" 1156 | } 1157 | }, 1158 | "node_modules/parse-node-version": { 1159 | "version": "1.0.1", 1160 | "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", 1161 | "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", 1162 | "dev": true, 1163 | "engines": { 1164 | "node": ">= 0.10" 1165 | } 1166 | }, 1167 | "node_modules/path-is-absolute": { 1168 | "version": "1.0.1", 1169 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1170 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 1171 | "dev": true, 1172 | "engines": { 1173 | "node": ">=0.10.0" 1174 | } 1175 | }, 1176 | "node_modules/picocolors": { 1177 | "version": "1.0.1", 1178 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", 1179 | "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", 1180 | "dev": true 1181 | }, 1182 | "node_modules/picomatch": { 1183 | "version": "2.3.1", 1184 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1185 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1186 | "dev": true, 1187 | "engines": { 1188 | "node": ">=8.6" 1189 | }, 1190 | "funding": { 1191 | "url": "https://github.com/sponsors/jonschlinkert" 1192 | } 1193 | }, 1194 | "node_modules/pify": { 1195 | "version": "4.0.1", 1196 | "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", 1197 | "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", 1198 | "dev": true, 1199 | "optional": true, 1200 | "engines": { 1201 | "node": ">=6" 1202 | } 1203 | }, 1204 | "node_modules/postcss": { 1205 | "version": "8.4.39", 1206 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", 1207 | "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", 1208 | "dev": true, 1209 | "funding": [ 1210 | { 1211 | "type": "opencollective", 1212 | "url": "https://opencollective.com/postcss/" 1213 | }, 1214 | { 1215 | "type": "tidelift", 1216 | "url": "https://tidelift.com/funding/github/npm/postcss" 1217 | }, 1218 | { 1219 | "type": "github", 1220 | "url": "https://github.com/sponsors/ai" 1221 | } 1222 | ], 1223 | "dependencies": { 1224 | "nanoid": "^3.3.7", 1225 | "picocolors": "^1.0.1", 1226 | "source-map-js": "^1.2.0" 1227 | }, 1228 | "engines": { 1229 | "node": "^10 || ^12 || >=14" 1230 | } 1231 | }, 1232 | "node_modules/postcss-load-config": { 1233 | "version": "3.1.4", 1234 | "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", 1235 | "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", 1236 | "dev": true, 1237 | "dependencies": { 1238 | "lilconfig": "^2.0.5", 1239 | "yaml": "^1.10.2" 1240 | }, 1241 | "engines": { 1242 | "node": ">= 10" 1243 | }, 1244 | "funding": { 1245 | "type": "opencollective", 1246 | "url": "https://opencollective.com/postcss/" 1247 | }, 1248 | "peerDependencies": { 1249 | "postcss": ">=8.0.9", 1250 | "ts-node": ">=9.0.0" 1251 | }, 1252 | "peerDependenciesMeta": { 1253 | "postcss": { 1254 | "optional": true 1255 | }, 1256 | "ts-node": { 1257 | "optional": true 1258 | } 1259 | } 1260 | }, 1261 | "node_modules/postcss-modules-extract-imports": { 1262 | "version": "3.1.0", 1263 | "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", 1264 | "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", 1265 | "dev": true, 1266 | "engines": { 1267 | "node": "^10 || ^12 || >= 14" 1268 | }, 1269 | "peerDependencies": { 1270 | "postcss": "^8.1.0" 1271 | } 1272 | }, 1273 | "node_modules/postcss-modules-local-by-default": { 1274 | "version": "4.0.5", 1275 | "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", 1276 | "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", 1277 | "dev": true, 1278 | "dependencies": { 1279 | "icss-utils": "^5.0.0", 1280 | "postcss-selector-parser": "^6.0.2", 1281 | "postcss-value-parser": "^4.1.0" 1282 | }, 1283 | "engines": { 1284 | "node": "^10 || ^12 || >= 14" 1285 | }, 1286 | "peerDependencies": { 1287 | "postcss": "^8.1.0" 1288 | } 1289 | }, 1290 | "node_modules/postcss-modules-scope": { 1291 | "version": "3.2.0", 1292 | "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", 1293 | "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", 1294 | "dev": true, 1295 | "dependencies": { 1296 | "postcss-selector-parser": "^6.0.4" 1297 | }, 1298 | "engines": { 1299 | "node": "^10 || ^12 || >= 14" 1300 | }, 1301 | "peerDependencies": { 1302 | "postcss": "^8.1.0" 1303 | } 1304 | }, 1305 | "node_modules/postcss-selector-parser": { 1306 | "version": "6.1.0", 1307 | "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz", 1308 | "integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==", 1309 | "dev": true, 1310 | "dependencies": { 1311 | "cssesc": "^3.0.0", 1312 | "util-deprecate": "^1.0.2" 1313 | }, 1314 | "engines": { 1315 | "node": ">=4" 1316 | } 1317 | }, 1318 | "node_modules/postcss-value-parser": { 1319 | "version": "4.2.0", 1320 | "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", 1321 | "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", 1322 | "dev": true 1323 | }, 1324 | "node_modules/prr": { 1325 | "version": "1.0.1", 1326 | "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", 1327 | "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", 1328 | "dev": true, 1329 | "optional": true 1330 | }, 1331 | "node_modules/readdirp": { 1332 | "version": "3.6.0", 1333 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 1334 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 1335 | "dev": true, 1336 | "dependencies": { 1337 | "picomatch": "^2.2.1" 1338 | }, 1339 | "engines": { 1340 | "node": ">=8.10.0" 1341 | } 1342 | }, 1343 | "node_modules/reserved-words": { 1344 | "version": "0.1.2", 1345 | "resolved": "https://registry.npmjs.org/reserved-words/-/reserved-words-0.1.2.tgz", 1346 | "integrity": "sha512-0S5SrIUJ9LfpbVl4Yzij6VipUdafHrOTzvmfazSw/jeZrZtQK303OPZW+obtkaw7jQlTQppy0UvZWm9872PbRw==", 1347 | "dev": true 1348 | }, 1349 | "node_modules/rollup": { 1350 | "version": "4.18.0", 1351 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", 1352 | "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", 1353 | "dev": true, 1354 | "dependencies": { 1355 | "@types/estree": "1.0.5" 1356 | }, 1357 | "bin": { 1358 | "rollup": "dist/bin/rollup" 1359 | }, 1360 | "engines": { 1361 | "node": ">=18.0.0", 1362 | "npm": ">=8.0.0" 1363 | }, 1364 | "optionalDependencies": { 1365 | "@rollup/rollup-android-arm-eabi": "4.18.0", 1366 | "@rollup/rollup-android-arm64": "4.18.0", 1367 | "@rollup/rollup-darwin-arm64": "4.18.0", 1368 | "@rollup/rollup-darwin-x64": "4.18.0", 1369 | "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", 1370 | "@rollup/rollup-linux-arm-musleabihf": "4.18.0", 1371 | "@rollup/rollup-linux-arm64-gnu": "4.18.0", 1372 | "@rollup/rollup-linux-arm64-musl": "4.18.0", 1373 | "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", 1374 | "@rollup/rollup-linux-riscv64-gnu": "4.18.0", 1375 | "@rollup/rollup-linux-s390x-gnu": "4.18.0", 1376 | "@rollup/rollup-linux-x64-gnu": "4.18.0", 1377 | "@rollup/rollup-linux-x64-musl": "4.18.0", 1378 | "@rollup/rollup-win32-arm64-msvc": "4.18.0", 1379 | "@rollup/rollup-win32-ia32-msvc": "4.18.0", 1380 | "@rollup/rollup-win32-x64-msvc": "4.18.0", 1381 | "fsevents": "~2.3.2" 1382 | } 1383 | }, 1384 | "node_modules/safer-buffer": { 1385 | "version": "2.1.2", 1386 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1387 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 1388 | "dev": true, 1389 | "optional": true 1390 | }, 1391 | "node_modules/sass": { 1392 | "version": "1.77.6", 1393 | "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.6.tgz", 1394 | "integrity": "sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q==", 1395 | "dev": true, 1396 | "dependencies": { 1397 | "chokidar": ">=3.0.0 <4.0.0", 1398 | "immutable": "^4.0.0", 1399 | "source-map-js": ">=0.6.2 <2.0.0" 1400 | }, 1401 | "bin": { 1402 | "sass": "sass.js" 1403 | }, 1404 | "engines": { 1405 | "node": ">=14.0.0" 1406 | } 1407 | }, 1408 | "node_modules/sax": { 1409 | "version": "1.4.1", 1410 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", 1411 | "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", 1412 | "dev": true, 1413 | "optional": true 1414 | }, 1415 | "node_modules/semver": { 1416 | "version": "5.7.2", 1417 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", 1418 | "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", 1419 | "dev": true, 1420 | "optional": true, 1421 | "bin": { 1422 | "semver": "bin/semver" 1423 | } 1424 | }, 1425 | "node_modules/source-map": { 1426 | "version": "0.6.1", 1427 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1428 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1429 | "dev": true, 1430 | "optional": true, 1431 | "engines": { 1432 | "node": ">=0.10.0" 1433 | } 1434 | }, 1435 | "node_modules/source-map-js": { 1436 | "version": "1.2.0", 1437 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", 1438 | "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", 1439 | "dev": true, 1440 | "engines": { 1441 | "node": ">=0.10.0" 1442 | } 1443 | }, 1444 | "node_modules/strip-bom": { 1445 | "version": "3.0.0", 1446 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", 1447 | "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", 1448 | "dev": true, 1449 | "engines": { 1450 | "node": ">=4" 1451 | } 1452 | }, 1453 | "node_modules/stylus": { 1454 | "version": "0.62.0", 1455 | "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.62.0.tgz", 1456 | "integrity": "sha512-v3YCf31atbwJQIMtPNX8hcQ+okD4NQaTuKGUWfII8eaqn+3otrbttGL1zSMZAAtiPsBztQnujVBugg/cXFUpyg==", 1457 | "dev": true, 1458 | "dependencies": { 1459 | "@adobe/css-tools": "~4.3.1", 1460 | "debug": "^4.3.2", 1461 | "glob": "^7.1.6", 1462 | "sax": "~1.3.0", 1463 | "source-map": "^0.7.3" 1464 | }, 1465 | "bin": { 1466 | "stylus": "bin/stylus" 1467 | }, 1468 | "engines": { 1469 | "node": "*" 1470 | }, 1471 | "funding": { 1472 | "url": "https://opencollective.com/stylus" 1473 | } 1474 | }, 1475 | "node_modules/stylus/node_modules/sax": { 1476 | "version": "1.3.0", 1477 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", 1478 | "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==", 1479 | "dev": true 1480 | }, 1481 | "node_modules/stylus/node_modules/source-map": { 1482 | "version": "0.7.4", 1483 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", 1484 | "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", 1485 | "dev": true, 1486 | "engines": { 1487 | "node": ">= 8" 1488 | } 1489 | }, 1490 | "node_modules/to-regex-range": { 1491 | "version": "5.0.1", 1492 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1493 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1494 | "dev": true, 1495 | "dependencies": { 1496 | "is-number": "^7.0.0" 1497 | }, 1498 | "engines": { 1499 | "node": ">=8.0" 1500 | } 1501 | }, 1502 | "node_modules/tsconfig-paths": { 1503 | "version": "4.2.0", 1504 | "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", 1505 | "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", 1506 | "dev": true, 1507 | "dependencies": { 1508 | "json5": "^2.2.2", 1509 | "minimist": "^1.2.6", 1510 | "strip-bom": "^3.0.0" 1511 | }, 1512 | "engines": { 1513 | "node": ">=6" 1514 | } 1515 | }, 1516 | "node_modules/tslib": { 1517 | "version": "2.6.3", 1518 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", 1519 | "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", 1520 | "dev": true 1521 | }, 1522 | "node_modules/typescript": { 1523 | "version": "5.5.3", 1524 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", 1525 | "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", 1526 | "dev": true, 1527 | "bin": { 1528 | "tsc": "bin/tsc", 1529 | "tsserver": "bin/tsserver" 1530 | }, 1531 | "engines": { 1532 | "node": ">=14.17" 1533 | } 1534 | }, 1535 | "node_modules/typescript-plugin-css-modules": { 1536 | "version": "5.1.0", 1537 | "resolved": "https://registry.npmjs.org/typescript-plugin-css-modules/-/typescript-plugin-css-modules-5.1.0.tgz", 1538 | "integrity": "sha512-6h+sLBa4l+XYSTn/31vZHd/1c3SvAbLpobY6FxDiUOHJQG1eD9Gh3eCs12+Eqc+TCOAdxcO+zAPvUq0jBfdciw==", 1539 | "dev": true, 1540 | "dependencies": { 1541 | "@types/postcss-modules-local-by-default": "^4.0.2", 1542 | "@types/postcss-modules-scope": "^3.0.4", 1543 | "dotenv": "^16.4.2", 1544 | "icss-utils": "^5.1.0", 1545 | "less": "^4.2.0", 1546 | "lodash.camelcase": "^4.3.0", 1547 | "postcss": "^8.4.35", 1548 | "postcss-load-config": "^3.1.4", 1549 | "postcss-modules-extract-imports": "^3.0.0", 1550 | "postcss-modules-local-by-default": "^4.0.4", 1551 | "postcss-modules-scope": "^3.1.1", 1552 | "reserved-words": "^0.1.2", 1553 | "sass": "^1.70.0", 1554 | "source-map-js": "^1.0.2", 1555 | "stylus": "^0.62.0", 1556 | "tsconfig-paths": "^4.2.0" 1557 | }, 1558 | "peerDependencies": { 1559 | "typescript": ">=4.0.0" 1560 | } 1561 | }, 1562 | "node_modules/util-deprecate": { 1563 | "version": "1.0.2", 1564 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1565 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", 1566 | "dev": true 1567 | }, 1568 | "node_modules/vite": { 1569 | "version": "5.3.3", 1570 | "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.3.tgz", 1571 | "integrity": "sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A==", 1572 | "dev": true, 1573 | "dependencies": { 1574 | "esbuild": "^0.21.3", 1575 | "postcss": "^8.4.39", 1576 | "rollup": "^4.13.0" 1577 | }, 1578 | "bin": { 1579 | "vite": "bin/vite.js" 1580 | }, 1581 | "engines": { 1582 | "node": "^18.0.0 || >=20.0.0" 1583 | }, 1584 | "funding": { 1585 | "url": "https://github.com/vitejs/vite?sponsor=1" 1586 | }, 1587 | "optionalDependencies": { 1588 | "fsevents": "~2.3.3" 1589 | }, 1590 | "peerDependencies": { 1591 | "@types/node": "^18.0.0 || >=20.0.0", 1592 | "less": "*", 1593 | "lightningcss": "^1.21.0", 1594 | "sass": "*", 1595 | "stylus": "*", 1596 | "sugarss": "*", 1597 | "terser": "^5.4.0" 1598 | }, 1599 | "peerDependenciesMeta": { 1600 | "@types/node": { 1601 | "optional": true 1602 | }, 1603 | "less": { 1604 | "optional": true 1605 | }, 1606 | "lightningcss": { 1607 | "optional": true 1608 | }, 1609 | "sass": { 1610 | "optional": true 1611 | }, 1612 | "stylus": { 1613 | "optional": true 1614 | }, 1615 | "sugarss": { 1616 | "optional": true 1617 | }, 1618 | "terser": { 1619 | "optional": true 1620 | } 1621 | } 1622 | }, 1623 | "node_modules/wrappy": { 1624 | "version": "1.0.2", 1625 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1626 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 1627 | "dev": true 1628 | }, 1629 | "node_modules/yaml": { 1630 | "version": "1.10.2", 1631 | "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", 1632 | "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", 1633 | "dev": true, 1634 | "engines": { 1635 | "node": ">= 6" 1636 | } 1637 | } 1638 | } 1639 | } 1640 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hyperapp-starter", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite dev --open --host", 8 | "build": "tsc && vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "hyperapp": "^2.0.22" 13 | }, 14 | "devDependencies": { 15 | "typescript": "^5.2.2", 16 | "typescript-plugin-css-modules": "^5.1.0", 17 | "vite": "^5.3.1" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loteoo/hyperapp-starter/384bbed11b1b58d027a5b03de90d1320543ab21e/public/favicon.png -------------------------------------------------------------------------------- /public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loteoo/hyperapp-starter/384bbed11b1b58d027a5b03de90d1320543ab21e/public/logo.png -------------------------------------------------------------------------------- /src/components/App/app.module.css: -------------------------------------------------------------------------------- 1 | .app { 2 | height: 100%; 3 | display: flex; 4 | flex-direction: column; 5 | align-items: stretch; 6 | & main { 7 | flex: 1; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/components/App/index.tsx: -------------------------------------------------------------------------------- 1 | import { State } from '/src/lib/state'; 2 | 3 | import Header from '/src/components/Header'; 4 | import Footer from '/src/components/Footer'; 5 | import Router from '/src/components/Router'; 6 | 7 | import styles from './app.module.css'; 8 | 9 | const App = (state: State) => { 10 | return ( 11 |
12 |
13 |
14 | 15 |
16 |
17 |
18 | ); 19 | }; 20 | 21 | export default App; 22 | -------------------------------------------------------------------------------- /src/components/Footer/footer.module.css: -------------------------------------------------------------------------------- 1 | .footer { 2 | padding: 1rem; 3 | } 4 | -------------------------------------------------------------------------------- /src/components/Footer/index.tsx: -------------------------------------------------------------------------------- 1 | import styles from './footer.module.css'; 2 | import utils from '/src/lib/utils.module.css'; 3 | 4 | const Footer = () => { 5 | return ( 6 | 19 | ); 20 | }; 21 | 22 | export default Footer; 23 | -------------------------------------------------------------------------------- /src/components/Header/header.module.css: -------------------------------------------------------------------------------- 1 | .header { 2 | padding: 1rem; 3 | } 4 | -------------------------------------------------------------------------------- /src/components/Header/index.tsx: -------------------------------------------------------------------------------- 1 | import styles from './header.module.css'; 2 | import utils from '/src/lib/utils.module.css'; 3 | 4 | const Header = () => { 5 | return ( 6 |
7 | 14 |
15 | ); 16 | }; 17 | 18 | export default Header; 19 | -------------------------------------------------------------------------------- /src/components/Router/index.tsx: -------------------------------------------------------------------------------- 1 | import { State } from '/src/lib/state'; 2 | import Home from '/src/pages/Home'; 3 | import About from '/src/pages/About'; 4 | import NotFound from '/src/pages/NotFound'; 5 | 6 | const Router = (state: State) => { 7 | if (state.location.path === '/') { 8 | return ; 9 | } 10 | if (state.location.path === '/about') { 11 | return ; 12 | } 13 | return ; 14 | }; 15 | 16 | export default Router; 17 | -------------------------------------------------------------------------------- /src/components/StateViewer/index.tsx: -------------------------------------------------------------------------------- 1 | import { State } from '/src/lib/state'; 2 | 3 | const StateViewer = ({ state }: { state: State }) => { 4 | return ( 5 |
6 | Show app state 7 |
 8 |         {`state: ${JSON.stringify(state, null, 2)}`}
 9 |       
10 |
11 | ); 12 | }; 13 | 14 | export default StateViewer; 15 | -------------------------------------------------------------------------------- /src/lib/global.css: -------------------------------------------------------------------------------- 1 | /* === Global styles === */ 2 | 3 | :root { 4 | --font-sans: -apple-system, 'Segoe UI', Roboto, sans-serif; 5 | --font-mono: ui-monospace, Menlo, Consolas, 'Roboto Mono', monospace; 6 | --font-serif: serif; 7 | --text-color: CanvasText; 8 | --background-color: Canvas; 9 | --border-color: light-dark(#ccc, #333); 10 | --alt-background-color: light-dark(ButtonFace, #282828); 11 | --theme-color: #2965f7; 12 | } 13 | 14 | *, 15 | *::before, 16 | *::after { 17 | box-sizing: border-box; 18 | } 19 | 20 | html { 21 | color-scheme: light dark; /* use system */ 22 | /* color-scheme: light; light mode */ 23 | /* color-scheme: dark; dark mode */ 24 | color: var(--text-color); 25 | background-color: var(--background-color); 26 | font-family: var(--font-sans); 27 | accent-color: var(--theme-color); 28 | font-size: clamp(14px, 1.5vw, 16px); 29 | line-height: 1.375; 30 | font-synthesis: none; 31 | text-rendering: optimizeLegibility; 32 | -webkit-font-smoothing: antialiased; 33 | -moz-osx-font-smoothing: grayscale; 34 | } 35 | 36 | ::selection { 37 | background: var(--theme-color); 38 | color: var(--background-color); 39 | } 40 | 41 | :focus-visible { 42 | outline-color: var(--theme-color); 43 | } 44 | ::marker { 45 | color: currentColor; 46 | } 47 | 48 | [id] { 49 | scroll-margin-top: 2ex; 50 | } 51 | 52 | @media (prefers-reduced-motion: reduce) { 53 | *, 54 | *::before, 55 | *::after { 56 | animation-duration: 0.01ms !important; 57 | animation-iteration-count: 1 !important; 58 | transition-duration: 0.01ms !important; 59 | scroll-behavior: auto !important; 60 | } 61 | } 62 | 63 | /* === Root layout === */ 64 | 65 | html { 66 | scroll-behavior: smooth; 67 | display: table; 68 | width: 100%; 69 | height: 100%; 70 | } 71 | 72 | body { 73 | display: table-cell; 74 | } 75 | 76 | #app { 77 | height: 100%; 78 | display: flex; 79 | flex-direction: column; 80 | align-items: stretch; 81 | } 82 | 83 | /* === Typography === */ 84 | 85 | a { 86 | color: var(--theme-color); 87 | text-decoration: none; 88 | &:hover { 89 | text-decoration: underline; 90 | } 91 | } 92 | 93 | code, 94 | kbd, 95 | samp, 96 | pre { 97 | font-family: var(--font-mono); 98 | } 99 | 100 | code { 101 | background-color: var(--alt-background-color); 102 | font-size: 85%; 103 | border-radius: 0.25em; 104 | padding: 0 0.125em; 105 | } 106 | 107 | /* === Forms === */ 108 | 109 | input, 110 | button, 111 | textarea, 112 | select { 113 | background-color: transparent; 114 | border: 1px solid var(--border-color); 115 | color: inherit; 116 | font: inherit; 117 | letter-spacing: inherit; 118 | padding: 0.25em 0.375em; 119 | border-radius: 0.25em; 120 | } 121 | 122 | button { 123 | cursor: pointer; 124 | &:disabled { 125 | cursor: default; 126 | } 127 | } 128 | 129 | textarea { 130 | resize: vertical; 131 | } 132 | 133 | :is(input, textarea)::placeholder { 134 | color: inherit; 135 | opacity: 0.5; 136 | } 137 | 138 | select { 139 | -webkit-appearance: none; 140 | appearance: none; 141 | background: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='4'%3E%3Cpath d='M4 0h6L7 4'/%3E%3C/svg%3E") 142 | no-repeat right center / 1em; 143 | padding-right: 1em; 144 | &[multiple] { 145 | background-image: none; 146 | } 147 | } 148 | 149 | /* === Misc elements === */ 150 | 151 | img, 152 | picture, 153 | video, 154 | canvas, 155 | svg { 156 | display: block; 157 | max-width: 100%; 158 | } 159 | 160 | hr { 161 | margin: 1rem 0; 162 | border: none; 163 | height: 1px; 164 | background-color: var(--border-color); 165 | } 166 | 167 | pre code { 168 | display: block; 169 | padding: 1em; 170 | } 171 | 172 | details { 173 | margin: 1rem 0; 174 | border: 1px solid var(--border-color); 175 | border-radius: 0.25rem; 176 | padding: 0.5rem 1rem; 177 | & summary { 178 | cursor: pointer; 179 | font-weight: bold; 180 | margin: -0.5rem -1rem; 181 | padding: 0.5rem 1rem; 182 | &:focus { 183 | outline: none; 184 | } 185 | } 186 | } 187 | 188 | blockquote { 189 | margin: 1em 0; 190 | padding: 0.5em 2em; 191 | border-left: 0.25rem solid var(--text-color); 192 | & > *:first-child { 193 | margin-top: 0; 194 | } 195 | & > *:last-child { 196 | margin-bottom: 0; 197 | } 198 | } 199 | 200 | table { 201 | border-collapse: collapse; 202 | & caption { 203 | padding: 0.375rem 0.75rem; 204 | } 205 | & th, 206 | & td { 207 | padding: 0.375rem 0.75rem; 208 | border: 1px solid var(--border-color); 209 | } 210 | & th { 211 | font-weight: 600; 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /src/lib/main.tsx: -------------------------------------------------------------------------------- 1 | import { app } from 'hyperapp'; 2 | 3 | import App from '/src/components/App'; 4 | 5 | import { init, State } from '/src/lib/state'; 6 | import { TrackLinkClicks, onPushState } from '/src/lib/router'; 7 | 8 | import './global.css'; 9 | 10 | const view = (state: State) => ( 11 |
12 | {App(state)} 13 |
14 | ); 15 | 16 | app({ init, view, node: document.getElementById('app')!, subscriptions: () => [onPushState] }); 17 | -------------------------------------------------------------------------------- /src/lib/router.ts: -------------------------------------------------------------------------------- 1 | import { Subscription } from 'hyperapp'; 2 | import { State } from './state'; 3 | 4 | export type InternalPath = `/${string}`; 5 | 6 | export interface Location { 7 | path: InternalPath; 8 | query: Record; 9 | hash: string; 10 | } 11 | 12 | // Navigation util 13 | export const navigate = (path: InternalPath) => { 14 | history.pushState(null, '', path); 15 | setTimeout(() => { 16 | dispatchEvent(new CustomEvent('pushstate')); 17 | }); 18 | }; 19 | 20 | // Get current location 21 | export const getLocation = (): Location => { 22 | const { pathname, search, hash } = window.location; 23 | const query: Record = {}; 24 | for (const [key, value] of new URLSearchParams(search)) { 25 | query[key] = value; 26 | } 27 | return { 28 | path: pathname as InternalPath, 29 | query, 30 | hash, 31 | }; 32 | }; 33 | 34 | // Link click Action 35 | export const TrackLinkClicks = (state: State, ev: MouseEvent) => { 36 | let clicked: HTMLElement | null = ev.target as HTMLElement; 37 | 38 | // Crawl up dom tree, look if click landed inside a tag 39 | const anchor = clicked.closest('a'); 40 | 41 | if (!anchor) { 42 | return state; 43 | } 44 | const href = anchor.getAttribute('href'); 45 | 46 | if (!href?.startsWith('/')) { 47 | return state; 48 | } 49 | 50 | ev.preventDefault(); 51 | ev.stopPropagation(); 52 | navigate(href as InternalPath); 53 | 54 | return state; 55 | }; 56 | 57 | // Route change Subscription 58 | export const onPushState: Subscription = [ 59 | (dispatch) => { 60 | const handleLocationChange = () => { 61 | dispatch((state) => ({ ...state, location: getLocation() })); 62 | }; 63 | addEventListener('pushstate', handleLocationChange); 64 | addEventListener('popstate', handleLocationChange); 65 | return () => { 66 | removeEventListener('pushstate', handleLocationChange); 67 | removeEventListener('popstate', handleLocationChange); 68 | }; 69 | }, 70 | null, 71 | ]; 72 | -------------------------------------------------------------------------------- /src/lib/state.ts: -------------------------------------------------------------------------------- 1 | import { getLocation, Location } from "/src/lib/router"; 2 | 3 | export interface State { 4 | location: Location; 5 | count: number; 6 | } 7 | 8 | export const init: State = { 9 | location: getLocation(), 10 | count: 0, 11 | }; 12 | -------------------------------------------------------------------------------- /src/lib/utils.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | width: 100%; 3 | max-width: min(32rem, 90vw); 4 | margin: 0 auto; 5 | } 6 | 7 | .group { 8 | display: flex; 9 | align-items: center; 10 | gap: 1rem; 11 | } 12 | 13 | .stack { 14 | display: flex; 15 | flex-direction: column; 16 | gap: 1rem; 17 | } 18 | 19 | /* Responsive Card grid */ 20 | .grid { 21 | display: grid; 22 | grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); 23 | grid-gap: 1rem; 24 | margin: 1rem 0; 25 | } 26 | -------------------------------------------------------------------------------- /src/pages/About/index.tsx: -------------------------------------------------------------------------------- 1 | import utils from '/src/lib/utils.module.css'; 2 | 3 | const AboutPage = () => { 4 | return ( 5 |
6 |

About

7 |

Hey there!

8 |
9 | ); 10 | }; 11 | 12 | export default AboutPage; 13 | -------------------------------------------------------------------------------- /src/pages/Home/index.tsx: -------------------------------------------------------------------------------- 1 | import StateViewer from '/src/components/StateViewer'; 2 | import { State } from '/src/lib/state'; 3 | import utils from '/src/lib/utils.module.css'; 4 | 5 | const Increment = (state: State) => ({ 6 | ...state, 7 | count: state.count + 1, 8 | }); 9 | 10 | const HomePage = (state: State) => { 11 | return ( 12 |
21 | ); 22 | }; 23 | 24 | export default HomePage; 25 | -------------------------------------------------------------------------------- /src/pages/NotFound/index.tsx: -------------------------------------------------------------------------------- 1 | import utils from '/src/lib/utils.module.css'; 2 | 3 | const NotFound = () => ( 4 |
5 |

404.

6 |

Page not found.

7 | Go back to home page 8 |
9 | ); 10 | 11 | export default NotFound; 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "moduleDetection": "force", 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "jsxImportSource": "/jsx", 18 | 19 | /* Linting */ 20 | "strict": true, 21 | "noUnusedLocals": true, 22 | "noUnusedParameters": true, 23 | "noFallthroughCasesInSwitch": true, 24 | 25 | "baseUrl": ".", 26 | "paths": { 27 | "/*": ["./*"] 28 | }, 29 | "plugins": [{ "name": "typescript-plugin-css-modules" }], 30 | }, 31 | "include": ["src", "env.d.ts"] 32 | } 33 | --------------------------------------------------------------------------------