├── .babelrc ├── .editorconfig ├── .gitattributes ├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── scripts └── sizes.js ├── src ├── CodeUtils.ts ├── Customize.tsx ├── PackagesData.tsx ├── images │ ├── download.svg │ ├── external-link.svg │ └── logo.svg ├── index.d.ts ├── index.html ├── index.tsx ├── packages.json ├── sizes.json └── styles │ ├── bootstrap-variables.scss │ ├── bootstrap.scss │ ├── index.scss │ └── scrollbar.scss ├── tsconfig.json ├── tslint.json └── typings └── preact-highlight └── index.d.ts /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "env", { 5 | "targets": { 6 | "chrome": "58", 7 | "ie": "11" 8 | } 9 | } 10 | ] 11 | ] 12 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs. 2 | # More information at http://EditorConfig.org 3 | root = true 4 | 5 | [*] 6 | end_of_line = lf 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | indent_style = space 10 | indent_size = 4 11 | 12 | [*.json] 13 | indent_size = 2 14 | 15 | [{.editorconfig,.babelrc,.scssrc}] 16 | indent_size = 2 17 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | .ts text eol=lf 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .DS_Store 4 | .cache -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PixiJS Customize 2 | 3 | The project is a web-based tool that enables users to custom builds of PixiJS by including the packages that you need and excluding packages you don't. The tool provides a workflow for users adding PixiJS to the browser directly or using a JavaScript bundler (like Rollup, Webpack or Parcel). 4 | 5 | ## Usage 6 | 7 | https://userland.pixijs.io/customize 8 | 9 | ## Authors 10 | 11 | * Matt Karl ([@bigtimebuddy](https://github.com/bigtimebuddy)) 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "customize", 3 | "version": "1.3.0", 4 | "private": true, 5 | "description": "Customize the list of packages to use for PixiJS, generates a list of dependencies and a JavaScript source file to include in your project.", 6 | "main": "index.js", 7 | "scripts": { 8 | "clean": "rimraf dist/*", 9 | "types": "tsc -noEmit", 10 | "lint": "tslint --project tsconfig.json -c tslint.json \"src/**/*.{ts,tsx}\" -e **/*.d.ts --format stylish", 11 | "start": "run-p watch launch", 12 | "launch": "http-server dist -o", 13 | "watch": "parcel watch src/index.html -d dist --public-url \".\"", 14 | "build:dev": "parcel build src/index.html -d dist --no-minify --public-url \".\"", 15 | "build:prod": "parcel build src/index.html -d dist --no-source-maps --no-cache --public-url \".\"", 16 | "prebuild": "run-s clean lint types", 17 | "build": "npm run build:prod", 18 | "predeploy": "npm run build", 19 | "deploy": "gh-pages -d dist", 20 | "postversion": "npm run deploy && git push && git push --tags", 21 | "sizes": "node scripts/sizes > src/sizes.json" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "git+https://github.com/pixijs/customize.git" 26 | }, 27 | "keywords": [], 28 | "author": "", 29 | "license": "ISC", 30 | "bugs": { 31 | "url": "https://github.com/pixijs/customize/issues" 32 | }, 33 | "pre-commit": [ 34 | "types", 35 | "lint" 36 | ], 37 | "homepage": "https://github.com/pixijs/customize#readme", 38 | "devDependencies": { 39 | "autoprefixer": "^9.5.1", 40 | "babel-core": "^6.26.3", 41 | "babel-preset-env": "^1.7.0", 42 | "bind-decorator": "^1.0.11", 43 | "bootstrap": "^4.3.1", 44 | "gh-pages": "^2.0.1", 45 | "http-server": "^0.11.1", 46 | "node-sass": "^4.11.0", 47 | "npm-run-all": "^4.1.5", 48 | "parcel-bundler": "^1.12.3", 49 | "pre-commit": "^1.2.2", 50 | "preact": "^8.4.2", 51 | "preact-highlight": "^1.1.3", 52 | "rimraf": "^2.6.3", 53 | "tslint": "^5.15.0", 54 | "typescript": "^3.4.3" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /scripts/sizes.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | let rootFolder; 5 | if (process.env.PIXIJS) { 6 | // Use environment variable for getting path to pixi.js 7 | rootFolder = path.resolve(process.env.PIXIJS); 8 | } 9 | else { 10 | // Default check folder alongsize 11 | rootFolder = path.join(__dirname, '..', '..', 'pixi.js'); 12 | } 13 | process.cwd(rootFolder); 14 | module.paths.splice(0, 0, path.join(rootFolder, 'node_modules')); 15 | 16 | const batchPackages = require('@lerna/batch-packages'); 17 | const filterPackages = require('@lerna/filter-packages'); 18 | const { getPackages } = require('@lerna/project'); 19 | const chalk = require('chalk'); 20 | 21 | async function getSortedPackages() { 22 | const packages = await getPackages(rootFolder); 23 | const filtered = filterPackages(packages, "@pixi/*", null, false); 24 | return batchPackages(filtered) 25 | .reduce((arr, batch) => arr.concat(batch), []); 26 | } 27 | 28 | (async function() { 29 | const packages = await getSortedPackages(); 30 | const sizes = {}; 31 | packages.forEach(pkg => { 32 | const {name, location} = pkg; 33 | const {bundle} = pkg.toJSON(); 34 | const output = path.join(location, bundle.replace(/\.js$/, '.min.js')); 35 | if (!fs.existsSync(output)) { 36 | console.log(chalk.red('ERROR: Run "npm run build:prod" first.')); 37 | process.exit(); 38 | } 39 | const {size} = fs.statSync(output); 40 | sizes[name] = size; 41 | }); 42 | console.log(JSON.stringify(sizes, null, 4)); 43 | })(); 44 | 45 | -------------------------------------------------------------------------------- /src/CodeUtils.ts: -------------------------------------------------------------------------------- 1 | import {Package, packagesData, packagesMap} from './PackagesData'; 2 | 3 | export interface HTMLResult { 4 | code:string; 5 | initCode:string; 6 | resources:string[]; 7 | pluginsHtml:string; 8 | plugins:string[]; 9 | } 10 | 11 | /** 12 | * Get header code 13 | */ 14 | function getCode({ name, namespace, code, importOnly }:Package) { 15 | if (importOnly) { 16 | return [`import '${name}'`]; 17 | } 18 | else if (code) { 19 | return code.map(line => line 20 | .replace('${name}', name) 21 | .replace('${namespace}', namespace)); 22 | } 23 | return namespace ? [ 24 | `import * as ${namespace} from '${name}'`, 25 | `export { ${namespace} }` 26 | ] : 27 | [`export * from '${name}'`]; 28 | } 29 | 30 | /** 31 | * Generate code for renderer plugins 32 | */ 33 | function rendererPlugin(rendererName:string, {name, rendererPlugin, canvasPlugin, namespace}:Package) { 34 | const target = rendererPlugin || canvasPlugin; 35 | const [apiName, className] = target; 36 | if (namespace) { 37 | return [ 38 | `${rendererName}.registerPlugin('${apiName}', ${namespace}.${className})` 39 | ]; 40 | } 41 | // avoid duplicate class imports for CanvasRenderer plugins 42 | else if (rendererName === 'CanvasRenderer' && rendererPlugin && rendererPlugin[1] === className) { 43 | return [ 44 | `${rendererName}.registerPlugin('${apiName}', ${className})` 45 | ]; 46 | } 47 | else { 48 | return [ 49 | `import { ${className} } from '${name}'`, 50 | `${rendererName}.registerPlugin('${apiName}', ${className})` 51 | ]; 52 | } 53 | } 54 | 55 | /** 56 | * Generate code for renderer plugins 57 | */ 58 | function rendererHTMLPlugin(rendererName:string, {name, rendererPlugin, canvasPlugin, namespace}:Package) { 59 | const target = rendererPlugin || canvasPlugin; 60 | const [apiName, className] = target; 61 | namespace = namespace ? `${namespace}.` : ''; 62 | return `PIXI.${rendererName}.registerPlugin('${apiName}', PIXI.${namespace}${className});`; 63 | } 64 | 65 | /** 66 | * Generate the ES6 code 67 | */ 68 | export function createBundleCode(packages:string[]) { 69 | const lines:string[] = []; 70 | 71 | const loaderPlugins = packagesData.packages 72 | .filter(pkg => packages.includes(pkg.name) && !!pkg.loaderPlugins); 73 | const appPlugins = packagesData.packages 74 | .filter(pkg => packages.includes(pkg.name) && !!pkg.appPlugin); 75 | const filters = packagesData.packages 76 | .filter(pkg => packages.includes(pkg.name) && !!pkg.filter); 77 | const canvasPlugins = packagesData.packages 78 | .filter(pkg => packages.includes(pkg.name) && !!pkg.canvasPlugin); 79 | 80 | packagesData.order 81 | .filter(name => packages.includes(name) && !packagesMap[name].filter) 82 | .map(name => packagesMap[name]) 83 | .forEach(pkg => lines.push.apply(lines, getCode(pkg))); 84 | 85 | lines.push('', '// Renderer plugins'); 86 | lines.push('import { Renderer } from \'@pixi/core\''); 87 | 88 | packagesData.packages 89 | .filter(pkg => packages.includes(pkg.name) && !!pkg.rendererPlugin) 90 | .forEach(pkg => lines.push.apply(lines, rendererPlugin('Renderer', pkg))); 91 | 92 | if (packages.includes('@pixi/canvas-renderer') && canvasPlugins.length) { 93 | lines.push('', '// CanvasRenderer plugins'); 94 | lines.push('import { CanvasRenderer } from \'@pixi/canvas-renderer\''); 95 | canvasPlugins.forEach(pkg => lines.push.apply(lines, rendererPlugin('CanvasRenderer', pkg))); 96 | } 97 | 98 | if (packages.includes('@pixi/app') && appPlugins.length) { 99 | lines.push('', '// Application plugins'); 100 | lines.push('import { Application } from \'@pixi/app\''); 101 | appPlugins.forEach(pkg => lines.push( 102 | `import { ${pkg.appPlugin} } from '${pkg.name}'`, 103 | `Application.registerPlugin(${pkg.appPlugin})` 104 | )); 105 | } 106 | 107 | if (packages.includes('@pixi/loaders') && loaderPlugins.length) { 108 | lines.push('', '// Loader plugins'); 109 | lines.push('import { Loader } from \'@pixi/loaders\''); 110 | loaderPlugins.forEach(pkg => lines.push( 111 | `import { ${pkg.loaderPlugins.join(', ')} } from '${pkg.name}'`, 112 | ...pkg.loaderPlugins.map(n => `Loader.registerPlugin(${n})`) 113 | )); 114 | } 115 | 116 | if (filters.length) { 117 | lines.push('', '// Filters'); 118 | const filterNames:string[] = []; 119 | filters.forEach(pkg => { 120 | const imports = pkg.filter.join(', '); 121 | filterNames.push(imports); 122 | lines.push(`import { ${imports} } from '${pkg.name}'`); 123 | }); 124 | lines.push(`export const filters = {\n ${filterNames.join(',\n ')}\n}`); 125 | } 126 | 127 | return lines 128 | .map(line => line && !line.startsWith('//') ? `${line};` : line) 129 | .join('\n'); 130 | } 131 | 132 | /** 133 | * Generate the HTML code 134 | */ 135 | export function createHTMLCode(selectedPackages:string[], unminifed:boolean, version:string):HTMLResult { 136 | const packages:string[] = []; 137 | 138 | // Create a list of packages that includes the selection 139 | // plus any dependencies, in bundler code we don't care 140 | // about this, but here 141 | selectedPackages.forEach(name => { 142 | packages.push(name); 143 | const {dependencies} = packagesMap[name]; 144 | if (dependencies) { 145 | dependencies 146 | .filter(n => !packages.includes(n)) 147 | .forEach(n => packages.push(n)); 148 | } 149 | }); 150 | 151 | const result:HTMLResult = { 152 | resources: [], 153 | plugins: [], 154 | initCode: null, 155 | pluginsHtml: null, 156 | code: '', 157 | }; 158 | 159 | result.resources = packagesData.order 160 | .filter(name => packages.includes(name)) 161 | .map(name => { 162 | const [ns, n] = name.split('/'); 163 | return `https://pixijs.download/${version}/packages/${n}${unminifed ? '' : '.min'}.js`; 164 | }); 165 | 166 | const loaderPlugins = packagesData.packages 167 | .filter(pkg => packages.includes(pkg.name) && !!pkg.loaderPlugins); 168 | const appPlugins = packagesData.packages 169 | .filter(pkg => packages.includes(pkg.name) && !!pkg.appPlugin); 170 | const filters = packagesData.packages 171 | .filter(pkg => packages.includes(pkg.name) && !!pkg.filter); 172 | const canvasPlugins = packagesData.packages 173 | .filter(pkg => packages.includes(pkg.name) && !!pkg.canvasPlugin); 174 | 175 | 176 | packagesData.packages 177 | .filter(pkg => packages.includes(pkg.name) && !!pkg.rendererPlugin) 178 | .forEach(pkg => result.plugins.push(rendererHTMLPlugin('Renderer', pkg))); 179 | 180 | if (packages.includes('@pixi/canvas-renderer') && canvasPlugins.length) { 181 | canvasPlugins.forEach(pkg => result.plugins.push(rendererHTMLPlugin('CanvasRenderer', pkg))); 182 | } 183 | 184 | if (packages.includes('@pixi/app') && appPlugins.length) { 185 | appPlugins.forEach(pkg => result.plugins.push(`PIXI.Application.registerPlugin(PIXI.${pkg.appPlugin});`)); 186 | } 187 | 188 | if (packages.includes('@pixi/loaders') && loaderPlugins.length) { 189 | loaderPlugins.forEach(pkg => result.plugins.push(...pkg.loaderPlugins.map(n => `PIXI.Loader.registerPlugin(PIXI.${n});`))); 190 | } 191 | 192 | result.pluginsHtml = ``; 193 | result.code += result.resources.map(url => ``).join('\n'); 194 | result.code += '\n' + result.pluginsHtml; 195 | result.initCode = packages.includes('@pixi/app') ? 196 | 'var app = new PIXI.Application();\ndocument.body.appendChild(app.view);': 197 | 'var renderer = PIXI.autoDetectRenderer();\ndocument.body.appendChild(renderer.view);'; 198 | 199 | return result; 200 | } 201 | -------------------------------------------------------------------------------- /src/Customize.tsx: -------------------------------------------------------------------------------- 1 | import { h, Component } from 'preact'; 2 | import logoUrl from './images/logo.svg'; 3 | import downloadUrl from './images/download.svg'; 4 | import externalLinkUrl from './images/external-link.svg'; 5 | import bind from 'bind-decorator'; 6 | import { HighLight } from 'preact-highlight'; 7 | import { createBundleCode, createHTMLCode, HTMLResult } from './CodeUtils'; 8 | import { packagesData, packagesMap, defaultPackages, Package, PackageGroup } from './PackagesData'; 9 | 10 | interface State { 11 | packages:string[]; 12 | useYarn:boolean; 13 | useBundler:boolean; 14 | bundleCode?:string; 15 | htmlResult?:HTMLResult; 16 | unminified:boolean; 17 | version:string; 18 | size:number; 19 | totalSize:number; 20 | } 21 | 22 | const PACKAGES = 'selectedPackages'; 23 | const BUNDLER = 'useBundler'; 24 | const YARN = 'useYarn'; 25 | const UNMINIFIED = 'unminified'; 26 | const VERSION = 'version'; 27 | 28 | const TITLE = 'PixiJS Customize'; 29 | const DESCRIPTION = 'Auto-generated by https://pixijs.io/customize'; 30 | 31 | /** 32 | * Main application 33 | */ 34 | export class Customize extends Component { 35 | constructor() { 36 | super(); 37 | 38 | const state:State = { 39 | packages: defaultPackages, 40 | size: 0, 41 | totalSize: 0, 42 | useYarn: !!localStorage.getItem(YARN), 43 | useBundler: !!localStorage.getItem(BUNDLER), 44 | unminified: !!localStorage.getItem(UNMINIFIED), 45 | version: localStorage.getItem(VERSION) || 'release', 46 | }; 47 | 48 | // Check for saved packages 49 | const savedPackages = localStorage.getItem(PACKAGES); 50 | if (savedPackages) { 51 | state.packages = JSON.parse(savedPackages); 52 | } 53 | for (const name in packagesMap) { 54 | state.totalSize += packagesMap[name].size; 55 | } 56 | state.size = this.getSize(state.packages); 57 | state.bundleCode = createBundleCode(state.packages); 58 | state.htmlResult = createHTMLCode(state.packages, state.unminified, state.version); 59 | this.state = state; 60 | } 61 | 62 | /** 63 | * Toggle package selection 64 | */ 65 | @bind 66 | private onTogglePackage(event:Event) { 67 | const {packages} = this.state; 68 | const {checked, dataset: {name}} = event.currentTarget as HTMLInputElement; 69 | if (checked) { 70 | packages.push(name); 71 | } 72 | else { 73 | packages.splice(packages.indexOf(name), 1); 74 | } 75 | this.refreshPackages(packages); 76 | } 77 | 78 | /** 79 | * Toggling ununminified checkbox 80 | */ 81 | @bind 82 | private onMinified(event:Event) { 83 | const {checked} = event.currentTarget as HTMLInputElement; 84 | if (checked) { 85 | localStorage.setItem(UNMINIFIED, '1'); 86 | } 87 | else { 88 | localStorage.removeItem(UNMINIFIED); 89 | } 90 | const { version, packages } = this.state; 91 | this.setState({ 92 | unminified: checked, 93 | htmlResult: createHTMLCode(packages, checked, version) 94 | }); 95 | } 96 | 97 | /** 98 | * Toggling ununminified checkbox 99 | */ 100 | @bind 101 | private onRelease(event:Event) { 102 | const {value} = event.currentTarget as HTMLInputElement; 103 | const version = value; 104 | localStorage.setItem(VERSION, version); 105 | const { packages, unminified } = this.state; 106 | this.setState({ 107 | version, 108 | htmlResult: createHTMLCode(packages, unminified, version) 109 | }); 110 | } 111 | 112 | private onToggleGroup(group:PackageGroup, event:Event) { 113 | const {checked} = event.currentTarget as HTMLInputElement; 114 | const {packages} = this.state; 115 | if (checked) { 116 | group.packages 117 | .filter(name => !packagesMap[name].required) 118 | .filter(name => !packages.includes(name)) 119 | .forEach(name => packages.push(name)); 120 | } 121 | else { 122 | group.packages 123 | .filter(name => !packagesMap[name].required) 124 | .filter(name => packages.includes(name)) 125 | .forEach(name => packages.splice(packages.indexOf(name), 1)); 126 | } 127 | this.refreshPackages(packages); 128 | } 129 | 130 | /** 131 | * Regenerate the bundle source code 132 | */ 133 | private refreshPackages(packages:string[]) { 134 | localStorage.setItem(PACKAGES, JSON.stringify(packages)); 135 | this.setState({ 136 | packages, 137 | size: this.getSize(packages), 138 | bundleCode: createBundleCode(packages), 139 | htmlResult: createHTMLCode(packages, this.state.unminified, this.state.version) 140 | }); 141 | } 142 | 143 | /** 144 | * Get the totally file size used 145 | */ 146 | private getSize(packages:string[]): number { 147 | return packages.map(name => packagesMap[name].size).reduce((prev, curr) => prev + curr); 148 | } 149 | 150 | /** 151 | * Handle the use of yarn 152 | */ 153 | private onYarn(useYarn:boolean) { 154 | if (useYarn) { 155 | localStorage.setItem(YARN, '1'); 156 | } 157 | else { 158 | localStorage.removeItem(YARN); 159 | } 160 | this.setState({ useYarn }); 161 | } 162 | 163 | /** 164 | * Handle browser type 165 | */ 166 | private onBundler(useBundler:boolean) { 167 | if (useBundler) { 168 | localStorage.setItem(BUNDLER, '1'); 169 | } 170 | else { 171 | localStorage.removeItem(BUNDLER); 172 | } 173 | this.setState({ useBundler }); 174 | } 175 | 176 | private groupSelected(group:PackageGroup): boolean { 177 | for (const name of group.packages) { 178 | if (!this.state.packages.includes(name)) { 179 | return false; 180 | } 181 | } 182 | return true; 183 | } 184 | 185 | /** 186 | * Reset to the default packages 187 | */ 188 | @bind 189 | private onReset() { 190 | const {packages} = this.state; 191 | packages.length = 0; 192 | for (const name of defaultPackages) { 193 | packages.push(name); 194 | } 195 | this.refreshPackages(packages); 196 | } 197 | 198 | render(props:any, { packages, useYarn, useBundler, bundleCode, htmlResult, version, unminified, size, totalSize }:State) { 199 | const percent = (size/totalSize*100); 200 | return (
201 |
202 |
203 |

Customize

204 |
205 | 207 | 209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
Estimated Filesize:
217 |
{Math.round(size / 1024)} KB
218 |
219 |
220 |
221 | {Math.round(percent)}% 222 |
223 |
224 |
225 | { packagesData.groups.map((group, i) => { 226 | return
227 |

228 | 233 | 234 |

235 |
    236 | { group.packages.map(name => packagesMap[name]).map(pkg => { 237 | return
  • 238 |
    239 | 245 | 246 |
    247 |
  • ; 248 | })} 249 |
250 |
; 251 | }) } 252 | 253 |
254 | { useBundler &&
255 |

Bundle Code

256 |

When using Webpack, 257 | Rollup or 258 | Parcel you can embed 259 | the follow code in your project and then 260 | simply import * as PIXI from './pixi.js'.

261 |

Since unused Renderer, Application and Loader plugins prevent 262 | proper tree-shaking using bundlers, it can be useful to bundle 263 | your own version of PixiJS with only the parts your project needs 264 | producing the smallest possible filesize.

265 | 266 | 267 | 271 | 272 |
} 273 | { useBundler &&
274 |

Install

275 |
276 | 277 | 278 |
279 | 280 | { useYarn ? 'yarn add' : 'npm install'} { packages.join(' ') } 281 | 282 |
} 283 | { !useBundler &&
284 |

285 |
286 |
287 | 292 | 293 |
294 | 298 |
299 | Browser Code 300 |

301 | 302 |
303 | 304 | 308 | 309 | {/*https://docs.jsfiddle.net/api/display-a-fiddle-from-post*/} 310 |
311 | 312 | 313 | 314 | 315 | 316 | 317 | 321 |
322 | {/*https://blog.codepen.io/documentation/api/prefill/*/} 323 |
324 | 331 | 335 |
336 |
337 |
} 338 |
339 |
); 340 | } 341 | } 342 | 343 | class Code extends Component { 344 | render(props:any) { 345 | return {props.children}; 346 | } 347 | } 348 | -------------------------------------------------------------------------------- /src/PackagesData.tsx: -------------------------------------------------------------------------------- 1 | import untypedPackagesData from './packages.json'; 2 | import untypedSizesData from './sizes.json'; 3 | 4 | export interface Package { 5 | name:string; 6 | code?:string[]; 7 | dependencies?:string[]; 8 | required?:boolean; 9 | rendererPlugin?:[string, string]; 10 | canvasPlugin?:[string, string]; 11 | appPlugin?:string; 12 | loaderPlugins?:string[]; 13 | namespace?:string; 14 | filter?:string[]; 15 | importOnly?:boolean; 16 | size:number; 17 | } 18 | export interface PackageGroup { 19 | packages:string[]; 20 | title:string; 21 | } 22 | 23 | export interface PackagesData { 24 | packages:Package[]; 25 | order:string[]; 26 | groups:PackageGroup[]; 27 | } 28 | 29 | const packagesData = untypedPackagesData as PackagesData; 30 | const packagesMap:{[name:string]:Package} = {}; 31 | 32 | // Create the map of packages by name to make for easier look-up 33 | packagesData.packages.forEach(pkg => { 34 | packagesMap[pkg.name] = pkg; 35 | pkg.size = untypedSizesData[pkg.name]; 36 | }); 37 | 38 | const defaultPackages = packagesData.packages 39 | .filter(pkg => pkg.required) 40 | .map(pkg => pkg.name); 41 | 42 | export { packagesData, packagesMap, defaultPackages }; 43 | -------------------------------------------------------------------------------- /src/images/download.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/images/external-link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/images/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.png' { 2 | const value: string; 3 | export = value; 4 | } 5 | 6 | declare module '*.svg' { 7 | const value: string; 8 | export = value; 9 | } 10 | 11 | declare module '*.json' { 12 | const value: any; 13 | export = value; 14 | } -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import './styles/index.scss'; 4 | import { Customize } from './Customize'; 5 | import { render, h } from 'preact'; 6 | 7 | render( 8 | (), 9 | document.body, 10 | document.body.lastElementChild 11 | ); 12 | -------------------------------------------------------------------------------- /src/packages.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | { 4 | "name": "@pixi/accessibility", 5 | "rendererPlugin": ["accessibility", "AccessibilityManager"], 6 | "canvasPlugin": ["accessibility", "AccessibilityManager"] 7 | }, 8 | { 9 | "name": "@pixi/app", 10 | "dependencies": ["@pixi/display"] 11 | }, 12 | { 13 | "name": "@pixi/basis", 14 | "dependencies": ["@pixi/compressed-textures"], 15 | "loaderPlugins": ["BasisLoader"] 16 | }, 17 | { 18 | "name": "@pixi/compressed-textures", 19 | "loaderPlugins": [ 20 | "CompressedTextureLoader", 21 | "DDSLoader", 22 | "KTXLoader" 23 | ] 24 | }, 25 | { 26 | "name": "@pixi/constants", 27 | "required": true 28 | }, 29 | { 30 | "name": "@pixi/core", 31 | "required": true, 32 | "rendererPlugin": ["batch", "BatchRenderer"] 33 | }, 34 | { 35 | "name": "@pixi/display" 36 | }, 37 | { 38 | "name": "@pixi/extract", 39 | "rendererPlugin": ["extract", "Extract"] 40 | }, 41 | { 42 | "name": "@pixi/events", 43 | "dependencies": ["@pixi/display"] 44 | }, 45 | { 46 | "name": "@pixi/graphics", 47 | "dependencies": [ 48 | "@pixi/sprite", 49 | "@pixi/display" 50 | ] 51 | }, 52 | { 53 | "name": "@pixi/graphics-extras", 54 | "importOnly": true, 55 | "dependencies": ["@pixi/graphics"] 56 | }, 57 | { 58 | "name": "@pixi/interaction", 59 | "rendererPlugin": ["interaction", "InteractionManager"], 60 | "canvasPlugin": ["interaction", "InteractionManager"], 61 | "dependencies": ["@pixi/display"] 62 | }, 63 | { 64 | "name": "@pixi/loaders", 65 | "appPlugin": "AppLoaderPlugin" 66 | }, 67 | { 68 | "name": "@pixi/math", 69 | "required": true 70 | }, 71 | { 72 | "name": "@pixi/math-extras", 73 | "importOnly": true 74 | }, 75 | { 76 | "name": "@pixi/mesh", 77 | "dependencies": ["@pixi/display"] 78 | }, 79 | { 80 | "name": "@pixi/mesh-extras", 81 | "dependencies": ["@pixi/mesh"] 82 | }, 83 | { 84 | "name": "@pixi/mixin-cache-as-bitmap", 85 | "importOnly": true, 86 | "dependencies": [ 87 | "@pixi/sprite", 88 | "@pixi/display" 89 | ] 90 | }, 91 | { 92 | "name": "@pixi/mixin-get-child-by-name", 93 | "importOnly": true, 94 | "dependencies": ["@pixi/display"] 95 | }, 96 | { 97 | "name": "@pixi/mixin-get-global-position", 98 | "importOnly": true, 99 | "dependencies": ["@pixi/display"] 100 | }, 101 | { 102 | "name": "@pixi/particle-container", 103 | "rendererPlugin": ["particle", "ParticleRenderer"], 104 | "dependencies": ["@pixi/display"] 105 | }, 106 | { 107 | "name": "@pixi/polyfill", 108 | "importOnly": true 109 | }, 110 | { 111 | "name": "@pixi/prepare", 112 | "rendererPlugin": ["prepare", "Prepare"], 113 | "dependencies": [ 114 | "@pixi/graphics", 115 | "@pixi/text", 116 | "@pixi/display" 117 | ] 118 | }, 119 | { 120 | "name": "@pixi/runner", 121 | "required": true 122 | }, 123 | { 124 | "name": "@pixi/settings", 125 | "required": true 126 | }, 127 | { 128 | "name": "@pixi/sprite", 129 | "dependencies": ["@pixi/display"] 130 | }, 131 | { 132 | "name": "@pixi/sprite-animated", 133 | "dependencies": ["@pixi/sprite"] 134 | }, 135 | { 136 | "name": "@pixi/sprite-tiling", 137 | "rendererPlugin": ["tilingSprite", "TilingSpriteRenderer"], 138 | "dependencies": ["@pixi/sprite", "@pixi/display"] 139 | }, 140 | { 141 | "name": "@pixi/spritesheet", 142 | "loaderPlugins": ["SpritesheetLoader"] 143 | }, 144 | { 145 | "name": "@pixi/text", 146 | "dependencies": ["@pixi/sprite"] 147 | }, 148 | { 149 | "name": "@pixi/text-bitmap", 150 | "loaderPlugins": ["BitmapFontLoader"], 151 | "dependencies": [ 152 | "@pixi/display", 153 | "@pixi/text", 154 | "@pixi/mesh" 155 | ] 156 | }, 157 | { 158 | "name": "@pixi/ticker", 159 | "required": true, 160 | "appPlugin": "TickerPlugin" 161 | }, 162 | { 163 | "name": "@pixi/unsafe-eval", 164 | "code": [ 165 | "import * as PIXI from '@pixi/core'", 166 | "import { install } from '${name}'", 167 | "install(PIXI)" 168 | ] 169 | }, 170 | { 171 | "name": "@pixi/utils", 172 | "namespace": "utils", 173 | "required": true 174 | }, 175 | { 176 | "name": "@pixi/filter-alpha", 177 | "filter": ["AlphaFilter"] 178 | }, 179 | { 180 | "name": "@pixi/filter-blur", 181 | "filter": ["BlurFilter", "BlurFilterPass"] 182 | }, 183 | { 184 | "name": "@pixi/filter-color-matrix", 185 | "filter": ["ColorMatrixFilter"] 186 | }, 187 | { 188 | "name": "@pixi/filter-displacement", 189 | "filter": ["DisplacementFilter"] 190 | }, 191 | { 192 | "name": "@pixi/filter-fxaa", 193 | "filter": ["FXAAFilter"] 194 | }, 195 | { 196 | "name": "@pixi/filter-noise", 197 | "filter": ["NoiseFilter"] 198 | }, 199 | { 200 | "name": "@pixi/canvas-display", 201 | "importOnly": true, 202 | "dependencies": ["@pixi/display"] 203 | }, 204 | { 205 | "name": "@pixi/canvas-extract", 206 | "canvasPlugin": ["extract", "CanvasExtract"], 207 | "dependencies": [ 208 | "@pixi/canvas-renderer", 209 | "@pixi/extract", 210 | "@pixi/display" 211 | ] 212 | }, 213 | { 214 | "name": "@pixi/canvas-graphics", 215 | "canvasPlugin": ["graphics", "CanvasGraphicsRenderer"], 216 | "dependencies": [ 217 | "@pixi/canvas-renderer", 218 | "@pixi/canvas-display" 219 | ] 220 | }, 221 | { 222 | "name": "@pixi/canvas-mesh", 223 | "canvasPlugin": ["mesh", "CanvasMeshRenderer"], 224 | "dependencies": [ 225 | "@pixi/canvas-renderer", 226 | "@pixi/canvas-display", 227 | "@pixi/mesh", 228 | "@pixi/mesh-extras" 229 | ] 230 | }, 231 | { 232 | "name": "@pixi/canvas-particle-container", 233 | "importOnly": true, 234 | "dependencies": ["@pixi/particle-container"] 235 | }, 236 | { 237 | "name": "@pixi/canvas-prepare", 238 | "canvasPlugin": ["prepare", "CanvasPrepare"], 239 | "dependencies": [ 240 | "@pixi/canvas-renderer", 241 | "@pixi/prepare" 242 | ] 243 | }, 244 | { 245 | "name": "@pixi/canvas-renderer" 246 | }, 247 | { 248 | "name": "@pixi/canvas-sprite", 249 | "canvasPlugin": ["sprite", "CanvasSpriteRenderer"], 250 | "dependencies": [ 251 | "@pixi/canvas-renderer", 252 | "@pixi/canvas-display", 253 | "@pixi/sprite" 254 | ] 255 | }, 256 | { 257 | "name": "@pixi/canvas-sprite-tiling", 258 | "importOnly": true, 259 | "dependencies": [ 260 | "@pixi/canvas-renderer", 261 | "@pixi/sprite-tiling", 262 | "@pixi/sprite" 263 | ] 264 | }, 265 | { 266 | "name": "@pixi/canvas-text", 267 | "importOnly": true, 268 | "dependencies": [ 269 | "@pixi/canvas-sprite", 270 | "@pixi/text", 271 | "@pixi/sprite" 272 | ] 273 | } 274 | ], 275 | "order": [ 276 | "@pixi/polyfill", 277 | "@pixi/constants", 278 | "@pixi/math", 279 | "@pixi/math-extras", 280 | "@pixi/runner", 281 | "@pixi/settings", 282 | "@pixi/ticker", 283 | "@pixi/utils", 284 | "@pixi/display", 285 | "@pixi/core", 286 | "@pixi/events", 287 | "@pixi/unsafe-eval", 288 | "@pixi/mixin-get-child-by-name", 289 | "@pixi/mixin-get-global-position", 290 | "@pixi/canvas-display", 291 | "@pixi/extract", 292 | "@pixi/loaders", 293 | "@pixi/compressed-textures", 294 | "@pixi/basis", 295 | "@pixi/mesh", 296 | "@pixi/particle-container", 297 | "@pixi/sprite", 298 | "@pixi/canvas-renderer", 299 | "@pixi/canvas-extract", 300 | "@pixi/filter-alpha", 301 | "@pixi/filter-blur", 302 | "@pixi/filter-color-matrix", 303 | "@pixi/filter-displacement", 304 | "@pixi/filter-fxaa", 305 | "@pixi/filter-noise", 306 | "@pixi/accessibility", 307 | "@pixi/app", 308 | "@pixi/graphics", 309 | "@pixi/graphics-extras", 310 | "@pixi/mesh-extras", 311 | "@pixi/mixin-cache-as-bitmap", 312 | "@pixi/sprite-animated", 313 | "@pixi/sprite-tiling", 314 | "@pixi/spritesheet", 315 | "@pixi/canvas-particle-container", 316 | "@pixi/canvas-sprite", 317 | "@pixi/text-bitmap", 318 | "@pixi/text", 319 | "@pixi/canvas-graphics", 320 | "@pixi/canvas-mesh", 321 | "@pixi/canvas-sprite-tiling", 322 | "@pixi/canvas-text", 323 | "@pixi/interaction", 324 | "@pixi/prepare", 325 | "@pixi/canvas-prepare" 326 | ], 327 | "groups": [ 328 | { 329 | "title": "Core", 330 | "packages": [ 331 | "@pixi/accessibility", 332 | "@pixi/app", 333 | "@pixi/basis", 334 | "@pixi/compressed-textures", 335 | "@pixi/constants", 336 | "@pixi/core", 337 | "@pixi/display", 338 | "@pixi/events", 339 | "@pixi/extract", 340 | "@pixi/graphics", 341 | "@pixi/graphics-extras", 342 | "@pixi/interaction", 343 | "@pixi/loaders", 344 | "@pixi/math", 345 | "@pixi/math-extras", 346 | "@pixi/mesh", 347 | "@pixi/mesh-extras", 348 | "@pixi/mixin-cache-as-bitmap", 349 | "@pixi/mixin-get-child-by-name", 350 | "@pixi/mixin-get-global-position", 351 | "@pixi/particle-container", 352 | "@pixi/polyfill", 353 | "@pixi/prepare", 354 | "@pixi/runner", 355 | "@pixi/settings", 356 | "@pixi/sprite", 357 | "@pixi/sprite-animated", 358 | "@pixi/sprite-tiling", 359 | "@pixi/spritesheet", 360 | "@pixi/text", 361 | "@pixi/text-bitmap", 362 | "@pixi/ticker", 363 | "@pixi/unsafe-eval", 364 | "@pixi/utils" 365 | ] 366 | }, 367 | { 368 | "title": "Filters", 369 | "packages": [ 370 | "@pixi/filter-alpha", 371 | "@pixi/filter-blur", 372 | "@pixi/filter-color-matrix", 373 | "@pixi/filter-displacement", 374 | "@pixi/filter-fxaa", 375 | "@pixi/filter-noise" 376 | ] 377 | }, 378 | { 379 | "title": "Canvas", 380 | "packages": [ 381 | "@pixi/canvas-display", 382 | "@pixi/canvas-extract", 383 | "@pixi/canvas-graphics", 384 | "@pixi/canvas-mesh", 385 | "@pixi/canvas-particle-container", 386 | "@pixi/canvas-prepare", 387 | "@pixi/canvas-renderer", 388 | "@pixi/canvas-sprite", 389 | "@pixi/canvas-sprite-tiling", 390 | "@pixi/canvas-text" 391 | ] 392 | } 393 | ] 394 | } 395 | -------------------------------------------------------------------------------- /src/sizes.json: -------------------------------------------------------------------------------- 1 | { 2 | "@pixi/accessibility": 7188, 3 | "@pixi/basis": 11419, 4 | "@pixi/compressed-textures": 22346, 5 | "@pixi/constants": 5006, 6 | "@pixi/core": 136556, 7 | "@pixi/display": 16678, 8 | "@pixi/events": 26652, 9 | "@pixi/extract": 2169, 10 | "@pixi/graphics-extras": 2619, 11 | "@pixi/graphics": 28885, 12 | "@pixi/loaders": 23044, 13 | "@pixi/math-extras": 2967, 14 | "@pixi/math": 13325, 15 | "@pixi/mesh": 7770, 16 | "@pixi/mixin-cache-as-bitmap": 6771, 17 | "@pixi/mixin-get-child-by-name": 662, 18 | "@pixi/mixin-get-global-position": 548, 19 | "@pixi/particle-container": 9649, 20 | "@pixi/polyfill": 5863, 21 | "@pixi/prepare": 4669, 22 | "@pixi/runner": 1661, 23 | "@pixi/settings": 3003, 24 | "@pixi/sprite-animated": 4721, 25 | "@pixi/sprite-tiling": 5990, 26 | "@pixi/sprite": 6090, 27 | "@pixi/spritesheet": 4282, 28 | "@pixi/ticker": 5508, 29 | "@pixi/unsafe-eval": 3848, 30 | "@pixi/utils": 31389, 31 | "@pixi/canvas-display": 690, 32 | "@pixi/canvas-extract": 1578, 33 | "@pixi/canvas-graphics": 7795, 34 | "@pixi/canvas-particle-container": 1368, 35 | "@pixi/canvas-prepare": 1351, 36 | "@pixi/canvas-sprite-tiling": 1678, 37 | "@pixi/canvas-sprite": 2178, 38 | "@pixi/canvas-text": 508, 39 | "@pixi/filter-alpha": 1230, 40 | "@pixi/filter-blur": 5992, 41 | "@pixi/filter-color-matrix": 7527, 42 | "@pixi/filter-displacement": 2923, 43 | "@pixi/filter-fxaa": 6386, 44 | "@pixi/filter-noise": 2008, 45 | "@pixi/mesh-extras": 8233, 46 | "@pixi/text-bitmap": 17586, 47 | "@pixi/canvas-mesh": 5187, 48 | "@pixi/canvas-renderer": 12418, 49 | "@pixi/app": 2119, 50 | "@pixi/interaction": 21491, 51 | "@pixi/text": 18785 52 | } 53 | -------------------------------------------------------------------------------- /src/styles/bootstrap-variables.scss: -------------------------------------------------------------------------------- 1 | $enable-rounded: false; // remove the default rounded corners 2 | $enable-gradients: false; // adds gradients to buttons 3 | $enable-shadows: false; // adds inner shadows to buttons 4 | $body-bg: #272d37; 5 | $body-color: #919bac; 6 | $primary: #ed206e; 7 | $secondary: #5f6a7d; 8 | // $danger: #e50913; 9 | // $dark: #313234; 10 | // $text-muted: #4c4c4d; 11 | // $hr-border-color: #262628; 12 | // $hr-border-width: 1px; 13 | // $close-color: #fff; 14 | // $close-text-shadow: none; 15 | // $custom-select-font-size-sm: 0.875rem; 16 | // $custom-select-focus-box-shadow: none; 17 | // $border-radius:0.5rem; 18 | // $custom-range-track-bg: lighten($input-bg, 10%); 19 | // $custom-range-track-height: 0.4rem; 20 | // $custom-range-thumb-border-radius: 1rem; 21 | // $pink: #e83e58; 22 | 23 | $link-color: #fff; 24 | $link-hover-color: $primary; 25 | $link-hover-decoration: none; -------------------------------------------------------------------------------- /src/styles/bootstrap.scss: -------------------------------------------------------------------------------- 1 | @import 'node_modules/bootstrap/scss/_functions'; 2 | @import 'node_modules/bootstrap/scss/_variables'; 3 | @import 'node_modules/bootstrap/scss/_mixins'; 4 | @import 'node_modules/bootstrap/scss/_root'; 5 | @import 'node_modules/bootstrap/scss/_reboot'; 6 | @import 'node_modules/bootstrap/scss/_type'; 7 | // @import 'node_modules/bootstrap/scss/_images'; 8 | @import 'node_modules/bootstrap/scss/_code'; 9 | @import 'node_modules/bootstrap/scss/_grid'; 10 | // @import 'node_modules/bootstrap/scss/_tables'; 11 | @import 'node_modules/bootstrap/scss/_forms'; 12 | @import 'node_modules/bootstrap/scss/_buttons'; 13 | // @import 'node_modules/bootstrap/scss/_transitions'; 14 | // @import 'node_modules/bootstrap/scss/_dropdown'; 15 | @import 'node_modules/bootstrap/scss/_button-group'; 16 | @import 'node_modules/bootstrap/scss/_input-group'; 17 | @import 'node_modules/bootstrap/scss/_custom-forms'; 18 | @import 'node_modules/bootstrap/scss/_nav'; 19 | // @import 'node_modules/bootstrap/scss/_navbar'; 20 | @import 'node_modules/bootstrap/scss/_card'; 21 | // @import 'node_modules/bootstrap/scss/_breadcrumb'; 22 | // @import 'node_modules/bootstrap/scss/_pagination'; 23 | // @import 'node_modules/bootstrap/scss/_badge'; 24 | // @import 'node_modules/bootstrap/scss/_jumbotron'; 25 | // @import 'node_modules/bootstrap/scss/_alert'; 26 | @import 'node_modules/bootstrap/scss/_progress'; 27 | // @import 'node_modules/bootstrap/scss/_media'; 28 | @import 'node_modules/bootstrap/scss/_list-group'; 29 | // @import 'node_modules/bootstrap/scss/_close'; 30 | @import 'node_modules/bootstrap/scss/_modal'; 31 | @import 'node_modules/bootstrap/scss/_tooltip'; 32 | // @import 'node_modules/bootstrap/scss/_popover'; 33 | // @import 'node_modules/bootstrap/scss/_carousel'; 34 | @import 'node_modules/bootstrap/scss/_utilities'; 35 | // @import 'node_modules/bootstrap/scss/_print'; 36 | -------------------------------------------------------------------------------- /src/styles/index.scss: -------------------------------------------------------------------------------- 1 | @import './bootstrap-variables'; 2 | @import './bootstrap'; 3 | @import './scrollbar'; 4 | 5 | $sm: map-get($grid-breakpoints, "sm"); 6 | $md: map-get($grid-breakpoints, "md"); 7 | 8 | html, body { 9 | font-family: 'Roboto', sans-serif; 10 | font-weight: 300; 11 | cursor:default; 12 | overflow: hidden; 13 | position: fixed; 14 | top:0; 15 | left:0; 16 | @extend .w-100; 17 | @extend .h-100; 18 | @media(max-width: $sm) { 19 | position: static; 20 | overflow: auto; 21 | -webkit-overflow-scrolling: touch; 22 | } 23 | } 24 | 25 | h1, h2, h3, h4, h5 { 26 | @extend .text-white; 27 | @extend .mb-2; 28 | 29 | } 30 | 31 | h2 { 32 | font-size: 140%; 33 | } 34 | 35 | ::selection { 36 | background:lighten(#465162, 40%); 37 | color:$white; 38 | } 39 | 40 | .customize-group + .customize-group { 41 | @extend .pt-3; 42 | } 43 | 44 | .customize-list-group { 45 | @extend .list-group; 46 | @extend .list-group-flush; 47 | user-select: none; 48 | } 49 | .customize-list-group-item { 50 | @extend .list-group-item; 51 | @extend .py-0; 52 | @extend .px-1; 53 | cursor:pointer; 54 | border-color:lighten($body-bg, 10%); 55 | &:hover { 56 | background: lighten($body-bg, 10%); 57 | } 58 | &, &.disabled { 59 | background: $body-bg; 60 | } 61 | & * { 62 | cursor:pointer; 63 | } 64 | .custom-control { 65 | @extend .py-1; 66 | } 67 | .custom-control-label { 68 | @extend .d-block; 69 | } 70 | &.disabled .custom-control-label { 71 | &:before { 72 | background: darken($primary, 25%); 73 | border-color: darken($primary, 25%); 74 | } 75 | &:after { 76 | opacity:0.4; 77 | } 78 | } 79 | } 80 | 81 | .customize-code { 82 | @extend .d-block; 83 | @extend .p-2; 84 | background: #38404e; 85 | border:1px solid #465162; 86 | &, & * { 87 | color:#919bac; 88 | } 89 | & + h2 { 90 | @extend .pt-4; 91 | } 92 | cursor: text; 93 | line-height:1.6; 94 | pre { 95 | @extend .m-0; 96 | white-space: pre-wrap; 97 | } 98 | .hljs { 99 | background: transparent !important; 100 | padding: 0 !important; 101 | } 102 | } 103 | 104 | .section-scroller { 105 | scrollbar-color: #647086 transparent; 106 | -moz-appearance: none !important; 107 | @extend .h-100; 108 | overflow: auto; 109 | -webkit-overflow-scrolling: touch; 110 | @media(max-width: $sm) { 111 | height: auto; 112 | overflow: inherit; 113 | -webkit-overflow-scrolling: auto; 114 | } 115 | } 116 | 117 | $header: 66px; 118 | 119 | .app-container { 120 | @extend .position-relative; 121 | @extend .mx-auto; 122 | max-width:1200px; 123 | height:100%; 124 | overflow: hidden; 125 | @media(max-width: $sm) { 126 | overflow: auto; 127 | height: auto; 128 | } 129 | .app-header { 130 | @extend .pt-2; 131 | @extend .w-100; 132 | position: absolute; 133 | height: $header; 134 | .logo { 135 | width:85px; 136 | vertical-align: baseline; 137 | } 138 | @media(max-width: $sm) { 139 | position: static; 140 | height: auto; 141 | h1 { 142 | font-size: 200%; 143 | text-align: center; 144 | padding: 1rem 0; 145 | } 146 | .logo { 147 | width: 75px; 148 | } 149 | } 150 | .app-tabs { 151 | top:0; 152 | right:0; 153 | position: absolute; 154 | @extend .btn-group; 155 | @extend .my-2; 156 | @extend .mr-3; 157 | @media(max-width: $sm) { 158 | position: static; 159 | width: 100%; 160 | margin-right: 0 !important; 161 | margin-bottom: 1rem !important; 162 | margin-top: 0 !important; 163 | .btn { 164 | padding-top: 0.5rem; 165 | padding-bottom: 0.5rem; 166 | } 167 | } 168 | } 169 | } 170 | .app-main { 171 | display: flex; 172 | position: absolute; 173 | top: $header; 174 | bottom: 1rem; 175 | @extend .w-100; 176 | @media(max-width: $sm) { 177 | position: static; 178 | height: auto; 179 | display: block; 180 | padding-bottom:1rem; 181 | } 182 | .app-col { 183 | @extend .section-scroller; 184 | } 185 | @media(max-width: $sm) { 186 | .app-col + .app-col { 187 | padding-top: 1rem; 188 | } 189 | } 190 | 191 | .app-col-bundler, 192 | .app-col-browser { 193 | @extend .d-flex; 194 | @extend .flex-column; 195 | @extend .h-100; 196 | overflow: hidden; 197 | @media(max-width: $sm) { 198 | height: auto; 199 | overflow: inherit; 200 | padding: 1rem 1rem 0; 201 | } 202 | .customize-code { 203 | @extend .flex-grow-1; 204 | @extend .section-scroller; 205 | } 206 | } 207 | .app-col-list { 208 | @extend .col-sm-4; 209 | @extend .col-md-3; 210 | position: relative; 211 | .app-size { 212 | z-index: 100; 213 | position: sticky; 214 | background: $body-bg; 215 | width: 100%; 216 | position: -webkit-sticky; 217 | top: 0; 218 | @extend .pb-1; 219 | @extend .mb-2; 220 | .progress { 221 | @extend .mt-2; 222 | } 223 | } 224 | } 225 | .app-col-bundler { 226 | @extend .col-sm-4; 227 | @extend .col-md-6; 228 | } 229 | .app-col-aside { 230 | @extend .col-sm-4; 231 | @extend .col-md-3; 232 | } 233 | .app-col-browser { 234 | @extend .col-sm-8; 235 | @extend .col-md-9; 236 | } 237 | } 238 | } 239 | 240 | .btn .icon { 241 | @extend .mr-md-2; 242 | width: 20px; 243 | height: 20px; 244 | @media(max-width: $md) { 245 | width: 16px; 246 | height: 16px; 247 | display:block; 248 | margin:0 auto 0.25rem; 249 | } 250 | } 251 | 252 | .note { 253 | @extend .small; 254 | line-height:1.5; 255 | } 256 | -------------------------------------------------------------------------------- /src/styles/scrollbar.scss: -------------------------------------------------------------------------------- 1 | ::-webkit-scrollbar { 2 | width: 8px; 3 | background-color: transparent; 4 | padding:2px; 5 | } 6 | 7 | ::-webkit-scrollbar-thumb { 8 | background-color: #647086; 9 | border-radius: 4px; 10 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "module": "None", 5 | "moduleResolution": "node", 6 | "allowSyntheticDefaultImports": true, 7 | "experimentalDecorators": true, 8 | "lib": [ 9 | "ES2016", 10 | "DOM" 11 | ], 12 | "removeComments": true, 13 | "noImplicitAny": true, 14 | "jsx": "react", 15 | "jsxFactory": "h", 16 | "typeRoots": [ 17 | "node_modules/@types", 18 | "typings" 19 | ], 20 | "sourceMap": true 21 | }, 22 | "parcelTsPluginOptions": { 23 | "transpileOnly": false 24 | }, 25 | "include": [ 26 | "src/**/*.ts", 27 | "src/**/*.tsx" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends":"tslint:recommended", 3 | "rules": { 4 | "semicolon": [true, "always"], 5 | "linebreak-style": [true, "LF"], 6 | "quotemark": [true, "single", "jsx-double"], 7 | "curly": true, 8 | "one-line": [true, "check-open-brace"], 9 | "indent": [true, "spaces", 4], 10 | "triple-equals": true, 11 | "no-reference": false, 12 | "no-var-keyword": true, 13 | "no-bitwise": false, 14 | "no-console": { "severity": "warning" }, 15 | "no-debugger": { "severity": "warning" }, 16 | "no-trailing-whitespace": { "severity": "warning" }, 17 | "variable-name": [true, "check-name", "allow-leading-underscore", "allow-pascal-case"], 18 | "array-type": [true, "array"], 19 | "trailing-comma": false, 20 | "object-literal-sort-keys": false, 21 | "interface-name": false, 22 | "only-arrow-functions": false, 23 | "max-classes-per-file": false, 24 | "forin": false, 25 | "one-variable-per-declaration": false, 26 | "max-line-length": false, 27 | "ordered-imports": false, 28 | "typedef-whitespace": false, 29 | "whitespace": false, 30 | "arrow-parens": false, 31 | "member-ordering": false, 32 | "no-shadowed-variable": false, 33 | "no-consecutive-blank-lines": false, 34 | "member-access": false, 35 | "no-shadowed-variable": false, 36 | "radix": false, 37 | "prefer-for-of": false, 38 | "no-string-throw": false 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /typings/preact-highlight/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'preact-highlight' { 2 | import { Component, ComponentChild } from 'preact'; 3 | export interface HighLightProps { 4 | code:string; 5 | theme?:string; 6 | className?:string; 7 | language?:string; 8 | } 9 | export class HighLight extends Component { 10 | render(props?:HighLightProps, state?:any): ComponentChild; 11 | } 12 | } 13 | --------------------------------------------------------------------------------