├── .gitignore ├── README.md ├── next.config.js ├── package.json ├── packages └── trie │ ├── .babelrc │ ├── __tests__ │ └── trie.test.js │ ├── index.js │ └── util │ ├── __tests__ │ ├── toHighlightedTreeData.test.js │ └── toTreeData.test.js │ ├── toHighlightedTreeData.js │ └── toTreeData.js ├── pages └── index.js ├── static ├── custom.css ├── spectre-exp.min.css ├── spectre-icons.min.css └── spectre.min.css ├── ui ├── CodeBlock.js ├── HighlightedTrie.js ├── Link.js ├── Node.js ├── SiteHead.js ├── ToggleButton.js ├── TreeGraph.js ├── TrieUI.js ├── TrieWithButtons.js ├── TrieWithSearch.js └── sections │ ├── BasicFunctions.js │ ├── README.md │ └── introduction.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | ./site/.next/* 3 | .next 4 | node_modules 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Trie Data Structure 2 | 3 | This is the code for an interactive guide to the Trie data structure, written in [NextJS](https://github.com/zeit/next.js/), [React](https://facebook.github.io/react/), and [VX](https://vx-demo.now.sh/). 4 | 5 | It's currently under construction, but if you would like to check it out, you can run it with `npm run dev` in your terminal. 6 | 7 | ## Tests 8 | 9 | You can currently run tests with `npm test` but you also can run them by downloading [jest](https://facebook.github.io/jest/) and running them via `jest --watch`. 10 | 11 | ## Code structure 12 | 13 | This project is built with NextJS, which uses the file system as it's paths. All paths are in "pages", and the `index.js` file in there is what gets run when you go to `localhost:3000/`. You can read more about this structure on this [NextJS docs](https://github.com/zeit/next.js/). 14 | 15 | "Packages" contains the trie and potentially other data structures. It's probably misnamed. 16 | 17 | ## Inspiration 18 | 19 | - [Redblob Game's Introduction to A*](http://www.redblobgames.com/pathfinding/a-star/introduction.html) 20 | - Literally anything [Nicky Case](http://ncase.me/) does. 21 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | // This file is not going through babel transformation. 2 | // So, we write it in vanilla JS 3 | // (But you could use ES2015 features supported by your Node.js version) 4 | 5 | module.exports = { 6 | webpack: (config, { dev }) => { 7 | // Perform customizations to webpack config 8 | config.resolve.modules = [ 9 | "node_modules" 10 | ] 11 | 12 | // Important: return the modified config 13 | return config 14 | }, 15 | webpackDevMiddleware: (config) => { 16 | // Perform customizations to webpack dev middleware config 17 | 18 | // Important: return the modified config 19 | return config 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "site", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "dev": "next", 6 | "build": "next build", 7 | "start": "next start", 8 | "test": "jest" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@vx/hierarchy": "0.0.119", 14 | "@vx/shape": "0.0.119", 15 | "babel-preset-jest": "^20.0.3", 16 | "d3-hierarchy": "^1.1.5", 17 | "next": "^2.4.2", 18 | "react": "^15.6.1", 19 | "react-dom": "^15.6.1", 20 | "react-syntax-highlighter": "^5.6.2", 21 | "spectre.css": "^0.2.14" 22 | }, 23 | "devDependencies": { 24 | "babel-jest": "^20.0.3", 25 | "babel-preset-es2015": "^6.24.1", 26 | "babel-preset-react": "^6.24.1", 27 | "react-test-renderer": "^15.6.1" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/trie/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "jest"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/trie/__tests__/trie.test.js: -------------------------------------------------------------------------------- 1 | import Trie from "../index.js"; 2 | 3 | describe("Trie", () => { 4 | 5 | test("it can add a word", () => { 6 | const trie = new Trie(); 7 | trie.add("hey"); 8 | expect(trie.has("hey")).toBe(true); 9 | expect(trie.has("hello")).toBe(false); 10 | expect(trie.has("ey")).toBe(false); 11 | expect(trie.has("he")).toBe(true); 12 | }) 13 | 14 | test("it can count prefixes", () => { 15 | const trie = new Trie(); 16 | trie.add("hey"); 17 | trie.add("hi"); 18 | expect(trie.countPrefixes("h")).toBe(2); 19 | expect(trie.countPrefixes("he")).toBe(1); 20 | }) 21 | 22 | test("it can count words", () => { 23 | const trie = new Trie(); 24 | trie.add("hello"); 25 | trie.add("hello"); 26 | expect(trie.countWords("hello")).toBe(2); 27 | expect(trie.countWords("floops")).toBe(0); 28 | }) 29 | }) 30 | -------------------------------------------------------------------------------- /packages/trie/index.js: -------------------------------------------------------------------------------- 1 | const isEmptyString = (w) => (!w || w.length === 0); 2 | 3 | class Trie { 4 | constructor() { 5 | this.words = 0; 6 | this.prefixes = 0; 7 | this.edges = {}; 8 | } 9 | 10 | /** 11 | * Adds a word to the trie. 12 | */ 13 | add(word) { 14 | if (isEmptyString(word)) { 15 | this.words += 1; 16 | } else { 17 | this.prefixes += 1; 18 | 19 | // Check if we've got this letter yet 20 | const k = word[0]; 21 | if (!this.edges[k]) { 22 | this.edges[k] = new Trie(); 23 | } 24 | 25 | word = word.slice(1); // Cut off first letter 26 | this.edges[k].add(word); 27 | } 28 | } 29 | 30 | /** 31 | * Returns true if the word or partial word exists inside the trie. 32 | */ 33 | has(word) { 34 | if (isEmptyString(word)) return true; 35 | 36 | // If this letter doesn't exist, return false. 37 | const k = word[0]; 38 | if (!this.edges[k]) return false; 39 | 40 | // Otherwise, continue 41 | return this.edges[k].has(word.slice(1)); 42 | } 43 | 44 | /** 45 | * Returns the total number of words in the trie 46 | * that have this prefix. 47 | */ 48 | countPrefixes(prefix) { 49 | if (isEmptyString(prefix)) return this.prefixes; 50 | 51 | const k = prefix[0]; 52 | if (!this.edges[k]) return 0; 53 | else { 54 | prefix = prefix.slice(1); 55 | return this.edges[k].countPrefixes(prefix); 56 | } 57 | } 58 | 59 | /** 60 | * Returns the total number of words that exactly 61 | * match this string. 62 | */ 63 | countWords(word) { 64 | if (isEmptyString(word)) return this.words; 65 | 66 | const k = word[0]; 67 | if (!this.edges[k]) return 0; 68 | else { 69 | word = word.slice(1); 70 | return this.edges[k].countWords(word); 71 | } 72 | } 73 | } 74 | 75 | export default Trie; 76 | -------------------------------------------------------------------------------- /packages/trie/util/__tests__/toHighlightedTreeData.test.js: -------------------------------------------------------------------------------- 1 | import toHighlightedTreeData from "../toHighlightedTreeData.js"; 2 | import Trie from "../../index.js"; 3 | 4 | test("highlightedTreeData", () => { 5 | const trie = new Trie(); 6 | trie.add("hey"); 7 | trie.add("hello"); 8 | 9 | console.log(JSON.stringify(toHighlightedTreeData(trie, "h"), null, 2)); 10 | }) 11 | -------------------------------------------------------------------------------- /packages/trie/util/__tests__/toTreeData.test.js: -------------------------------------------------------------------------------- 1 | import toTreeData from "../toTreeData.js"; 2 | import Trie from "../../index.js"; 3 | 4 | describe("toTreeData", () => { 5 | test("exists", () => { 6 | const trie = new Trie(); 7 | trie.add("heat"); 8 | trie.add("hat"); 9 | console.log(JSON.stringify(toTreeData(trie), null, 2)) 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /packages/trie/util/toHighlightedTreeData.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import toTreeData from './toTreeData.js'; 3 | 4 | export default function mapTrie(data, searchWord) { 5 | data.highlighted = searchWord.includes(data.name) || data.name === ""; 6 | 7 | if (data.children) data.children.map(d => mapTrie(d, searchWord)); 8 | return data; 9 | } 10 | -------------------------------------------------------------------------------- /packages/trie/util/toTreeData.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | 3 | function fromTrieChildren(trie, previous = "") { 4 | return Object.keys(trie.edges).map(d => { 5 | const prev = previous + d; 6 | return { 7 | name: prev, 8 | children: fromTrieChildren(trie.edges[d], prev) 9 | } 10 | }); 11 | } 12 | 13 | export default function fromTrie(trie, previous = "") { 14 | const children = fromTrieChildren(trie); 15 | return [{ 16 | name: "", 17 | children: children 18 | }] 19 | } 20 | -------------------------------------------------------------------------------- /pages/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import SiteHead from "../ui/SiteHead.js"; 4 | import Introduction from "../ui/sections/Introduction.js"; 5 | import BasicFunctions from "../ui/sections/BasicFunctions.js"; 6 | 7 | class App extends React.Component { 8 | render() { 9 | return ( 10 |
21 | 22 | 23 | 24 |
25 | ); 26 | } 27 | } 28 | 29 | export default () => ; 30 | -------------------------------------------------------------------------------- /static/custom.css: -------------------------------------------------------------------------------- 1 | .code-wrapper code { 2 | width: 100%; 3 | color: initial; 4 | } 5 | -------------------------------------------------------------------------------- /static/spectre-exp.min.css: -------------------------------------------------------------------------------- 1 | /*! Spectre.css Experimentals | MIT License | github.com/picturepan2/spectre */.accordion .accordion-item input:checked~.accordion-body{max-height:100rem;transition:max-height 3s ease}.accordion .accordion-item .accordion-header{background:#f8f9fa;display:block;padding:1rem 1.6rem}.accordion .accordion-item .accordion-body{margin-bottom:.8rem;max-height:0;overflow:hidden;padding:.2rem .8rem;transition:max-height .3s ease}.calendar{border:.1rem solid #f0f1f4;border-radius:.2rem;display:block;min-width:28rem;text-align:center}.calendar .calendar-nav{-webkit-align-items:center;align-items:center;background:#f8f9fa;border-top-left-radius:.2rem;border-top-right-radius:.2rem;display:flex;display:-ms-flexbox;display:-webkit-flex;-ms-flex-align:center;font-size:1.6rem;padding:1rem}.calendar .calendar-body,.calendar .calendar-header{display:flex;display:-ms-flexbox;display:-webkit-flex;-ms-flex-pack:center;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-justify-content:center;justify-content:center;padding:1rem 0}.calendar .calendar-body .calendar-date,.calendar .calendar-header .calendar-date{-webkit-flex:0 0 14.28%;-ms-flex:0 0 14.28%;flex:0 0 14.28%;max-width:14.28%}.calendar .calendar-header{background:#f8f9fa;border-bottom:.1rem solid #f0f1f4;color:#acb3c2;font-size:1.2rem}.calendar .calendar-body{color:#727e96}.calendar .calendar-date{border:0;padding:.4rem}.calendar .calendar-date .date-item{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:0 0;border:.1rem solid transparent;border-radius:50%;color:#727e96;cursor:pointer;height:2.8rem;line-height:2rem;outline:0;padding:.3rem;position:relative;text-align:center;text-decoration:none;transition:all .2s ease;vertical-align:middle;white-space:nowrap;width:2.8rem}.calendar .calendar-date .date-item.date-today{border-color:#e4e6f6;color:#5764c6}.calendar .calendar-date .date-item:focus{box-shadow:0 0 0 .2rem rgba(87,100,198,.15)}.calendar .calendar-date .date-item:focus,.calendar .calendar-date .date-item:hover{background:#fbfbfe;border-color:#e4e6f6;color:#5764c6;text-decoration:none}.calendar .calendar-date .date-item.active,.calendar .calendar-date .date-item:active{background:#4c59c2;border-color:#3e4cb6;color:#fff}.calendar .calendar-date .date-item.badge::after{position:absolute;right:.3rem;top:.3rem;-webkit-transform:translate(50%,-50%);-ms-transform:translate(50%,-50%);transform:translate(50%,-50%)}.calendar .calendar-date .calendar-event:disabled,.calendar .calendar-date .date-item:disabled,.calendar .calendar-date.disabled .calendar-event,.calendar .calendar-date.disabled .date-item{cursor:default;opacity:.25;pointer-events:none}.calendar .calendar-range{position:relative}.calendar .calendar-range::before{background:#eff1fa;content:"";height:2.8rem;left:0;position:absolute;right:0;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.calendar .calendar-range.range-start::before{left:50%}.calendar .calendar-range.range-end::before{right:50%}.calendar .calendar-range .date-item{color:#5764c6}.calendar.calendar-lg .calendar-body{padding:0}.calendar.calendar-lg .calendar-body .calendar-date{border-bottom:.1rem solid #f0f1f4;border-right:.1rem solid #f0f1f4;display:flex;display:-ms-flexbox;display:-webkit-flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;height:11rem;padding:0}.calendar.calendar-lg .calendar-body .calendar-date:nth-child(7n){border-right:0}.calendar.calendar-lg .calendar-body .calendar-date:nth-last-child(-n+7){border-bottom:0}.calendar.calendar-lg .date-item{-webkit-align-self:flex-end;align-self:flex-end;-ms-flex-item-align:end;height:2.8rem;margin-right:.5rem;margin-top:.5rem}.calendar.calendar-lg .calendar-range::before{top:1.9rem}.calendar.calendar-lg .calendar-range.range-start::before{left:auto;width:1.9rem}.calendar.calendar-lg .calendar-range.range-end::before{right:1.9rem}.calendar.calendar-lg .calendar-events{-webkit-flex-grow:1;flex-grow:1;-ms-flex-positive:1;line-height:1;overflow-y:auto;padding:.5rem}.calendar.calendar-lg .calendar-event{background:#eff1fa;border-radius:.2rem;color:#5764c6;display:block;font-size:1.2rem;margin:.2rem auto;overflow:hidden;padding:.3rem .4rem;text-align:left;text-overflow:ellipsis;vertical-align:baseline;white-space:nowrap}.carousel{background:#f8f9fa;display:block;overflow:hidden;position:relative;width:100%}.carousel .carousel-container{height:100%;left:0;position:relative}.carousel .carousel-container::before{content:"";display:block;padding-bottom:56.25%}.carousel .carousel-container .carousel-item{-webkit-animation:carousel-slideout 1s ease-in-out 1;animation:carousel-slideout 1s ease-in-out 1;height:100%;left:0;margin:0;opacity:0;position:absolute;top:0;width:100%}.carousel .carousel-container .carousel-item:hover .item-next,.carousel .carousel-container .carousel-item:hover .item-prev{opacity:1}.carousel .carousel-container .item-next,.carousel .carousel-container .item-prev{background:rgba(231,233,237,.25);border-color:rgba(231,233,237,.5);color:#e7e9ed;opacity:0;position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);transition:all .4s ease;z-index:200}.carousel .carousel-container .item-prev{left:2rem}.carousel .carousel-container .item-next{right:2rem}.carousel .carousel-locator:nth-of-type(1):checked~.carousel-container .carousel-item:nth-of-type(1),.carousel .carousel-locator:nth-of-type(2):checked~.carousel-container .carousel-item:nth-of-type(2),.carousel .carousel-locator:nth-of-type(3):checked~.carousel-container .carousel-item:nth-of-type(3),.carousel .carousel-locator:nth-of-type(4):checked~.carousel-container .carousel-item:nth-of-type(4){-webkit-animation:carousel-slidein .75s ease-in-out 1;animation:carousel-slidein .75s ease-in-out 1;opacity:1;z-index:100}.carousel .carousel-locator:nth-of-type(1):checked~.carousel-nav .nav-item:nth-of-type(1),.carousel .carousel-locator:nth-of-type(2):checked~.carousel-nav .nav-item:nth-of-type(2),.carousel .carousel-locator:nth-of-type(3):checked~.carousel-nav .nav-item:nth-of-type(3),.carousel .carousel-locator:nth-of-type(4):checked~.carousel-nav .nav-item:nth-of-type(4){color:#e7e9ed}.carousel .carousel-nav{bottom:1rem;display:-webkit-flex;display:flex;display:-ms-flexbox;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;left:50%;position:absolute;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);width:20rem;z-index:200}.carousel .carousel-nav .nav-item{color:rgba(231,233,237,.5);display:block;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;height:4rem;margin:.4rem;max-width:5rem;position:relative}.carousel .carousel-nav .nav-item::before{background:currentColor;content:"";display:block;height:.3rem;position:absolute;top:2rem;width:100%}@-webkit-keyframes carousel-slidein{0%{-webkit-transform:translateX(100%);transform:translateX(100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes carousel-slidein{0%{-webkit-transform:translateX(100%);transform:translateX(100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@-webkit-keyframes carousel-slideout{0%{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}100%{opacity:1;-webkit-transform:translateX(-50%);transform:translateX(-50%)}}@keyframes carousel-slideout{0%{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}100%{opacity:1;-webkit-transform:translateX(-50%);transform:translateX(-50%)}}.comparison-slider{height:50vh;overflow:hidden;position:relative;width:100%}.comparison-slider .comparison-after,.comparison-slider .comparison-before{height:100%;left:0;margin:0;overflow:hidden;position:absolute;top:0}.comparison-slider .comparison-after img,.comparison-slider .comparison-before img{height:100%;object-fit:none;object-position:left top;position:absolute;width:100%;z-index:-1}.comparison-slider .comparison-before{width:100%}.comparison-slider .comparison-before .comparison-label{right:1.6rem}.comparison-slider .comparison-after{max-width:100%;min-width:0;z-index:1}.comparison-slider .comparison-after::before{background:0 0;content:"";cursor:default;height:100%;left:0;position:absolute;right:1.6rem;top:0;z-index:1}.comparison-slider .comparison-after::after{background:currentColor;border-radius:50%;box-shadow:0 -.5rem,0 .5rem;color:#fff;content:"";height:.3rem;position:absolute;right:.8rem;top:50%;-webkit-transform:translate(50%,-50%);-ms-transform:translate(50%,-50%);transform:translate(50%,-50%);width:.3rem;z-index:-1}.comparison-slider .comparison-after .comparison-label{left:1.6rem}.comparison-slider .comparison-resizer{-webkit-animation:first-run 1.5s 1 ease-in-out;animation:first-run 1.5s 1 ease-in-out;cursor:ew-resize;height:1.5rem;left:0;max-width:100%;min-width:1.6rem;opacity:0;outline:0;position:relative;resize:horizontal;top:50%;-webkit-transform:translateY(-50%) scaleY(30);-ms-transform:translateY(-50%) scaleY(30);transform:translateY(-50%) scaleY(30);width:0}.comparison-slider .comparison-label{background:rgba(69,77,93,.5);bottom:1.6rem;color:#fff;padding:.3rem .8rem;position:absolute;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@-webkit-keyframes first-run{0%{width:0}25%{width:4.8rem}50%{width:1.6rem}75%{width:2.4rem}100%{width:0}}@keyframes first-run{0%{width:0}25%{width:4.8rem}50%{width:1.6rem}75%{width:2.4rem}100%{width:0}}.filter .filter-nav{margin:1rem 0}.filter .filter-body{display:flex;display:-ms-flexbox;display:-webkit-flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.filter .filter-tag#tag-action:checked~.filter-nav .chip[for=tag-action],.filter .filter-tag#tag-all:checked~.filter-nav .chip[for=tag-all],.filter .filter-tag#tag-roleplaying:checked~.filter-nav .chip[for=tag-roleplaying],.filter .filter-tag#tag-shooter:checked~.filter-nav .chip[for=tag-shooter],.filter .filter-tag#tag-sports:checked~.filter-nav .chip[for=tag-sports]{background:#5764c6;color:#fff}.filter .filter-tag#tag-action:checked~.filter-body .column:not([data-tag~=tag-action]),.filter .filter-tag#tag-roleplaying:checked~.filter-body .column:not([data-tag~=tag-roleplaying]),.filter .filter-tag#tag-shooter:checked~.filter-body .column:not([data-tag~=tag-shooter]),.filter .filter-tag#tag-sports:checked~.filter-body .column:not([data-tag~=tag-sports]){display:none}.meter{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#f8f9fa;border:0;border-radius:.2rem;display:block;height:1.6rem;width:100%}.meter::-webkit-meter-inner-element{display:block}.meter::-webkit-meter-bar,.meter::-webkit-meter-even-less-good-value,.meter::-webkit-meter-optimum-value,.meter::-webkit-meter-suboptimum-value{border-radius:.2rem}.meter::-webkit-meter-bar{background:#f8f9fa}.meter::-webkit-meter-optimum-value{background:#32b643}.meter::-webkit-meter-suboptimum-value{background:#ffb700}.meter::-webkit-meter-even-less-good-value{background:#e85600}.meter:-moz-meter-optimum,.meter:-moz-meter-sub-optimum,.meter:-moz-meter-sub-sub-optimum,.meter::-moz-meter-bar{border-radius:.2rem}.meter:-moz-meter-optimum::-moz-meter-bar{background:#32b643}.meter:-moz-meter-sub-optimum::-moz-meter-bar{background:#ffb700}.meter:-moz-meter-sub-sub-optimum::-moz-meter-bar{background:#e85600}.parallax{display:block;height:auto;position:relative;width:auto}.parallax .parallax-content{box-shadow:0 2rem 4.2rem rgba(69,77,93,.3);height:auto;-webkit-transform:perspective(100rem);transform:perspective(100rem);-webkit-transform-style:preserve-3d;transform-style:preserve-3d;transition:all .4s ease;width:100%}.parallax .parallax-content::before{content:"";display:block;height:100%;left:0;position:absolute;top:0;width:100%}.parallax .parallax-front{-webkit-align-items:center;align-items:center;color:#fff;display:flex;display:-ms-flexbox;display:-webkit-flex;-ms-flex-align:center;-ms-flex-pack:center;height:100%;-webkit-justify-content:center;justify-content:center;left:0;position:absolute;text-align:center;text-shadow:0 0 3rem rgba(69,77,93,.95);top:0;-webkit-transform:translateZ(10rem) scale(.9);transform:translateZ(10rem) scale(.9);transition:all .4s ease;width:100%;z-index:1}.parallax .parallax-top-left{height:50%;left:0;position:absolute;top:0;width:50%;z-index:300}.parallax .parallax-top-left:hover~.parallax-content{-webkit-transform:perspective(100rem) rotateX(-3deg) rotateY(3deg);transform:perspective(100rem) rotateX(-3deg) rotateY(3deg)}.parallax .parallax-top-left:hover~.parallax-content::before{background:linear-gradient(135deg,rgba(255,255,255,.25) 0,rgba(255,255,255,0) 50%)}.parallax .parallax-top-left:hover~.parallax-content .parallax-front{-webkit-transform:translate3d(-.65rem,-.65rem,10rem) scale(.9);transform:translate3d(-.65rem,-.65rem,10rem) scale(.9)}.parallax .parallax-top-right{height:50%;position:absolute;right:0;top:0;width:50%;z-index:300}.parallax .parallax-top-right:hover~.parallax-content{-webkit-transform:perspective(100rem) rotateX(-3deg) rotateY(-3deg);transform:perspective(100rem) rotateX(-3deg) rotateY(-3deg)}.parallax .parallax-top-right:hover~.parallax-content::before{background:linear-gradient(-135deg,rgba(255,255,255,.25) 0,rgba(255,255,255,0) 50%)}.parallax .parallax-top-right:hover~.parallax-content .parallax-front{-webkit-transform:translate3d(.65rem,-.65rem,10rem) scale(.9);transform:translate3d(.65rem,-.65rem,10rem) scale(.9)}.parallax .parallax-bottom-left{bottom:0;height:50%;left:0;position:absolute;width:50%;z-index:300}.parallax .parallax-bottom-left:hover~.parallax-content{-webkit-transform:perspective(100rem) rotateX(3deg) rotateY(3deg);transform:perspective(100rem) rotateX(3deg) rotateY(3deg)}.parallax .parallax-bottom-left:hover~.parallax-content::before{background:linear-gradient(45deg,rgba(255,255,255,.25) 0,rgba(255,255,255,0) 50%)}.parallax .parallax-bottom-left:hover~.parallax-content .parallax-front{-webkit-transform:translate3d(-.65rem,.65rem,10rem) scale(.9);transform:translate3d(-.65rem,.65rem,10rem) scale(.9)}.parallax .parallax-bottom-right{bottom:0;height:50%;position:absolute;right:0;width:50%;z-index:300}.parallax .parallax-bottom-right:hover~.parallax-content{-webkit-transform:perspective(100rem) rotateX(3deg) rotateY(-3deg);transform:perspective(100rem) rotateX(3deg) rotateY(-3deg)}.parallax .parallax-bottom-right:hover~.parallax-content::before{background:linear-gradient(-45deg,rgba(255,255,255,.25) 0,rgba(255,255,255,0) 50%)}.parallax .parallax-bottom-right:hover~.parallax-content .parallax-front{-webkit-transform:translate3d(.65rem,.65rem,10rem) scale(.9);transform:translate3d(.65rem,.65rem,10rem) scale(.9)}.progress{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#f0f1f4;border:0;border-radius:.2rem;color:#5764c6;height:.4rem;position:relative;width:100%}.progress::-webkit-progress-bar{background:0 0;border-radius:.2rem}.progress::-webkit-progress-value{background:#5764c6;border-radius:.2rem}.progress::-moz-progress-bar{background:#5764c6;border-radius:.2rem}.progress:indeterminate{-webkit-animation:progress-indeterminate 1.5s linear infinite;animation:progress-indeterminate 1.5s linear infinite;background:#f0f1f4 linear-gradient(to right,#5764c6 30%,#f0f1f4 30%) top left/150% 150% no-repeat}.progress:indeterminate::-moz-progress-bar{background:0 0}@-webkit-keyframes progress-indeterminate{0%{background-position:200% 0}100%{background-position:-200% 0}}@keyframes progress-indeterminate{0%{background-position:200% 0}100%{background-position:-200% 0}}.slider{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:0 0;display:block;height:2.4rem;width:100%}.slider:focus{box-shadow:0 0 0 .2rem rgba(87,100,198,.15);outline:0}.slider::-webkit-slider-thumb{-webkit-appearance:none;background:#5764c6;border:0;border-radius:50%;height:1.2rem;margin-top:-.5rem;transition:transform .2s ease,-webkit-transform .2s ease;transition:transform .2s ease;transition:-webkit-transform .2s ease;width:1.2rem}.slider::-moz-range-thumb{background:#5764c6;border:0;border-radius:50%;height:1.2rem;transition:transform .2s ease,-webkit-transform .2s ease;transition:transform .2s ease;transition:-webkit-transform .2s ease;width:1.2rem}.slider::-ms-thumb{background:#5764c6;border:0;border-radius:50%;height:1.2rem;transition:transform .2s ease,-webkit-transform .2s ease;transition:transform .2s ease;transition:-webkit-transform .2s ease;width:1.2rem}.slider:active::-webkit-slider-thumb{-webkit-transform:scale(1.25);transform:scale(1.25)}.slider:active::-moz-range-thumb{transform:scale(1.25)}.slider:active::-ms-thumb{-ms-transform:scale(1.25);transform:scale(1.25)}.slider.disabled::-webkit-slider-thumb,.slider:disabled::-webkit-slider-thumb{background:#e7e9ed;-webkit-transform:scale(1);transform:scale(1)}.slider.disabled::-moz-range-thumb,.slider:disabled::-moz-range-thumb{background:#e7e9ed;transform:scale(1)}.slider.disabled::-ms-thumb,.slider:disabled::-ms-thumb{background:#e7e9ed;-ms-transform:scale(1);transform:scale(1)}.slider::-webkit-slider-runnable-track{background:#f0f1f4;border-radius:.2rem;height:.2rem;width:100%}.slider::-moz-range-track{background:#f0f1f4;border-radius:.2rem;height:.2rem;width:100%}.slider::-ms-track{background:#f0f1f4;border-radius:.2rem;height:.2rem;width:100%}.slider::-ms-fill-lower{background:#5764c6}.timeline .timeline-item{display:flex;display:-ms-flexbox;display:-webkit-flex;margin-bottom:2.4rem;position:relative}.timeline .timeline-item::before{background:#f0f1f4;content:"";height:100%;left:1.1rem;position:absolute;top:2.4rem;width:.2rem}.timeline .timeline-item .timeline-left{-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.timeline .timeline-item .timeline-content{-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;padding:.2rem 0 .2rem 1.5rem}.timeline .timeline-item .timeline-icon{border-radius:50%;color:#fff;display:block;height:2.4rem;text-align:center;width:2.4rem}.timeline .timeline-item .timeline-icon::before{border:.2rem solid #5764c6;border-radius:50%;content:"";display:block;height:.8rem;left:.8rem;position:absolute;top:.8rem;width:.8rem}.timeline .timeline-item .timeline-icon.icon-lg{background:#5764c6;font-size:1.6rem;line-height:2rem}.timeline .timeline-item .timeline-icon.icon-lg::before{content:none} -------------------------------------------------------------------------------- /static/spectre-icons.min.css: -------------------------------------------------------------------------------- 1 | /*! Spectre.css Icons | MIT License | github.com/picturepan2/spectre */.icon{box-sizing:border-box;display:inline-block;font-size:inherit;font-style:normal;height:1em;position:relative;text-indent:-999rem;vertical-align:middle;width:1em}.icon::after,.icon::before{display:block;left:50%;position:absolute;top:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.icon-arrow-down::before,.icon-arrow-left::before,.icon-arrow-right::before,.icon-arrow-up::before,.icon-back::before,.icon-downward::before,.icon-forward::before,.icon-upward::before{border:.2rem solid currentColor;border-bottom:0;border-right:0;content:"";height:.65em;-webkit-transform:translate(-25%,-50%) rotate(-45deg);-ms-transform:translate(-25%,-50%) rotate(-45deg);transform:translate(-25%,-50%) rotate(-45deg);width:.65em}.icon-arrow-down,.icon-downward{-webkit-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg)}.icon-arrow-right,.icon-forward{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.icon-arrow-up,.icon-upward{-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.icon-back::before,.icon-downward::before,.icon-forward::before,.icon-upward::before{-webkit-transform:translate(-50%,-50%) rotate(-45deg);-ms-transform:translate(-50%,-50%) rotate(-45deg);transform:translate(-50%,-50%) rotate(-45deg)}.icon-back::after,.icon-downward::after,.icon-forward::after,.icon-upward::after{background:currentColor;content:"";height:.2rem;left:55%;width:.8em}.icon-caret::before{border-left:.3em solid transparent;border-right:.3em solid transparent;border-top:.3em solid currentColor;content:"";height:0;-webkit-transform:translate(-50%,-25%);-ms-transform:translate(-50%,-25%);transform:translate(-50%,-25%);width:0}.icon-menu::before{background:currentColor;box-shadow:0 -.35em,0 .35em;content:"";height:.2rem;width:100%}.icon-apps::before{background:currentColor;box-shadow:-.35em -.35em,-.35em 0,-.35em .35em,0 -.35em,0 .35em,.35em -.35em,.35em 0,.35em .35em;content:"";height:.3rem;width:.3rem}.icon-resize-horiz::after,.icon-resize-horiz::before,.icon-resize-vert::after,.icon-resize-vert::before{border:.2rem solid currentColor;border-bottom:0;border-right:0;content:"";height:.45em;width:.45em}.icon-resize-horiz::before,.icon-resize-vert::before{-webkit-transform:translate(-50%,-90%) rotate(45deg);-ms-transform:translate(-50%,-90%) rotate(45deg);transform:translate(-50%,-90%) rotate(45deg)}.icon-resize-horiz::after,.icon-resize-vert::after{-webkit-transform:translate(-50%,-10%) rotate(225deg);-ms-transform:translate(-50%,-10%) rotate(225deg);transform:translate(-50%,-10%) rotate(225deg)}.icon-resize-horiz::before{-webkit-transform:translate(-90%,-50%) rotate(-45deg);-ms-transform:translate(-90%,-50%) rotate(-45deg);transform:translate(-90%,-50%) rotate(-45deg)}.icon-resize-horiz::after{-webkit-transform:translate(-10%,-50%) rotate(135deg);-ms-transform:translate(-10%,-50%) rotate(135deg);transform:translate(-10%,-50%) rotate(135deg)}.icon-more-horiz::before,.icon-more-vert::before{background:currentColor;border-radius:50%;box-shadow:-.4em 0,.4em 0;content:"";height:.3rem;width:.3rem}.icon-more-vert::before{box-shadow:0 -.4em,0 .4em}.icon-cross::before,.icon-minus::before,.icon-plus::before{background:currentColor;content:"";height:.2rem;width:100%}.icon-cross::after,.icon-plus::after{background:currentColor;content:"";height:100%;width:.2rem}.icon-cross::before{width:100%}.icon-cross::after{height:100%}.icon-cross::after,.icon-cross::before{-webkit-transform:translate(-50%,-50%) rotate(45deg);-ms-transform:translate(-50%,-50%) rotate(45deg);transform:translate(-50%,-50%) rotate(45deg)}.icon-check::before{border:.2rem solid currentColor;border-right:0;border-top:0;content:"";height:.5em;-webkit-transform:translate(-50%,-75%) rotate(-45deg);-ms-transform:translate(-50%,-75%) rotate(-45deg);transform:translate(-50%,-75%) rotate(-45deg);width:.9em}.icon-stop{border:.2rem solid currentColor;border-radius:50%}.icon-stop::before{background:currentColor;content:"";height:.2rem;-webkit-transform:translate(-50%,-50%) rotate(45deg);-ms-transform:translate(-50%,-50%) rotate(45deg);transform:translate(-50%,-50%) rotate(45deg);width:1em}.icon-shutdown{border:.2rem solid currentColor;border-radius:50%;border-top-color:transparent}.icon-shutdown::before{background:currentColor;content:"";height:.5em;top:.1em;width:.2rem}.icon-refresh::before{border:.2rem solid currentColor;border-radius:50%;border-right-color:transparent;content:"";height:1em;width:1em}.icon-refresh::after{border:.2em solid currentColor;border-left-color:transparent;border-top-color:transparent;content:"";height:0;left:80%;top:20%;width:0}.icon-search::before{border:.2rem solid currentColor;border-radius:50%;content:"";height:.75em;left:5%;top:5%;-webkit-transform:translate(0,0) rotate(45deg);-ms-transform:translate(0,0) rotate(45deg);transform:translate(0,0) rotate(45deg);width:.75em}.icon-search::after{background:currentColor;content:"";height:.2rem;left:80%;top:80%;-webkit-transform:translate(-50%,-50%) rotate(45deg);-ms-transform:translate(-50%,-50%) rotate(45deg);transform:translate(-50%,-50%) rotate(45deg);width:.4em}.icon-edit::before{border:.2rem solid currentColor;content:"";height:.4em;-webkit-transform:translate(-40%,-60%) rotate(-45deg);-ms-transform:translate(-40%,-60%) rotate(-45deg);transform:translate(-40%,-60%) rotate(-45deg);width:.85em}.icon-edit::after{border:.15em solid currentColor;border-right-color:transparent;border-top-color:transparent;content:"";height:0;left:5%;top:95%;-webkit-transform:translate(0,-100%);-ms-transform:translate(0,-100%);transform:translate(0,-100%);width:0}.icon-delete::before{border:.2rem solid currentColor;border-bottom-left-radius:.2rem;border-bottom-right-radius:.2rem;border-top:0;content:"";height:.75em;top:60%;width:.75em}.icon-delete::after{background:currentColor;box-shadow:-.25em .2em,.25em .2em;content:"";height:.2rem;top:.1rem;width:.5em}.icon-share{border:.2rem solid currentColor;border-radius:.2rem;border-right:0;border-top:0}.icon-share::before{border:.2rem solid currentColor;border-left:0;border-top:0;content:"";height:.4em;left:100%;top:.25em;-webkit-transform:translate(-125%,-50%) rotate(-45deg);-ms-transform:translate(-125%,-50%) rotate(-45deg);transform:translate(-125%,-50%) rotate(-45deg);width:.4em}.icon-share::after{border:.2rem solid currentColor;border-bottom:0;border-radius:75% 0;border-right:0;content:"";height:.5em;width:.6em}.icon-flag::before{background:currentColor;content:"";height:1em;left:15%;width:.2rem}.icon-flag::after{border:.2rem solid currentColor;border-bottom-right-radius:.2rem;border-left:0;border-top-right-radius:.2rem;content:"";height:.65em;left:60%;top:35%;width:.8em}.icon-bookmark::before{border:.2rem solid currentColor;border-bottom:0;border-top-left-radius:.2rem;border-top-right-radius:.2rem;content:"";height:.9em;width:.8em}.icon-bookmark::after{border:.2rem solid currentColor;border-bottom:0;border-left:0;border-radius:.2rem;content:"";height:.5em;-webkit-transform:translate(-50%,35%) rotate(-45deg) skew(15deg,15deg);-ms-transform:translate(-50%,35%) rotate(-45deg) skew(15deg,15deg);transform:translate(-50%,35%) rotate(-45deg) skew(15deg,15deg);width:.5em}.icon-download,.icon-upload{border-bottom:.2rem solid currentColor}.icon-download::before,.icon-upload::before{border:.2rem solid currentColor;border-bottom:0;border-right:0;content:"";height:.5em;-webkit-transform:translate(-50%,-60%) rotate(-135deg);-ms-transform:translate(-50%,-60%) rotate(-135deg);transform:translate(-50%,-60%) rotate(-135deg);width:.5em}.icon-download::after,.icon-upload::after{background:currentColor;content:"";height:.6em;top:40%;width:.2rem}.icon-upload::before{-webkit-transform:translate(-50%,-60%) rotate(45deg);-ms-transform:translate(-50%,-60%) rotate(45deg);transform:translate(-50%,-60%) rotate(45deg)}.icon-upload::after{top:50%}.icon-time{border:.2rem solid currentColor;border-radius:50%}.icon-time::before{background:currentColor;content:"";height:.4em;-webkit-transform:translate(-50%,-75%);-ms-transform:translate(-50%,-75%);transform:translate(-50%,-75%);width:.2rem}.icon-time::after{background:currentColor;content:"";height:.3em;-webkit-transform:translate(-50%,-75%) rotate(90deg);-ms-transform:translate(-50%,-75%) rotate(90deg);transform:translate(-50%,-75%) rotate(90deg);-webkit-transform-origin:50% 90%;-ms-transform-origin:50% 90%;transform-origin:50% 90%;width:.2rem}.icon-mail::before{border:.2rem solid currentColor;border-radius:.2rem;content:"";height:.8em;width:1em}.icon-mail::after{border:.2rem solid currentColor;border-right:0;border-top:0;content:"";height:.5em;-webkit-transform:translate(-50%,-90%) rotate(-45deg) skew(10deg,10deg);-ms-transform:translate(-50%,-90%) rotate(-45deg) skew(10deg,10deg);transform:translate(-50%,-90%) rotate(-45deg) skew(10deg,10deg);width:.5em}.icon-people::before{border:.2rem solid currentColor;border-radius:50%;content:"";height:.45em;top:25%;width:.45em}.icon-people::after{border:.2rem solid currentColor;border-radius:50% 50% 0 0;content:"";height:.4em;top:75%;width:.9em}.icon-message{border:.2rem solid currentColor;border-bottom:0;border-radius:.2rem;border-right:0}.icon-message::before{border:.2rem solid currentColor;border-bottom-right-radius:.2rem;border-left:0;border-top:0;content:"";height:.8em;left:65%;top:40%;width:.7em}.icon-message::after{background:currentColor;border-radius:.2rem;content:"";height:.3em;left:10%;top:100%;-webkit-transform:translate(0,-90%) rotate(45deg);-ms-transform:translate(0,-90%) rotate(45deg);transform:translate(0,-90%) rotate(45deg);width:.2rem}.icon-photo{border:.2rem solid currentColor;border-radius:.2rem}.icon-photo::before{border:.2rem solid currentColor;border-radius:50%;content:"";height:.25em;left:35%;top:35%;width:.25em}.icon-photo::after{border:.2rem solid currentColor;border-bottom:0;border-left:0;content:"";height:.5em;left:60%;-webkit-transform:translate(-50%,25%) rotate(-45deg);-ms-transform:translate(-50%,25%) rotate(-45deg);transform:translate(-50%,25%) rotate(-45deg);width:.5em}.icon-link::after,.icon-link::before{border:.2rem solid currentColor;border-radius:5em 0 0 5em;border-right:0;content:"";height:.5em;width:.75em}.icon-link::before{-webkit-transform:translate(-70%,-45%) rotate(-45deg);-ms-transform:translate(-70%,-45%) rotate(-45deg);transform:translate(-70%,-45%) rotate(-45deg)}.icon-link::after{-webkit-transform:translate(-30%,-55%) rotate(135deg);-ms-transform:translate(-30%,-55%) rotate(135deg);transform:translate(-30%,-55%) rotate(135deg)}.icon-location::before{border:.2rem solid currentColor;border-radius:50% 50% 50% 0;content:"";height:.8em;-webkit-transform:translate(-50%,-60%) rotate(-45deg);-ms-transform:translate(-50%,-60%) rotate(-45deg);transform:translate(-50%,-60%) rotate(-45deg);width:.8em}.icon-location::after{border:.2rem solid currentColor;border-radius:50%;content:"";height:.2em;-webkit-transform:translate(-50%,-80%);-ms-transform:translate(-50%,-80%);transform:translate(-50%,-80%);width:.2em}.icon-emoji{border:.2rem solid currentColor;border-radius:50%}.icon-emoji::before{border-radius:50%;box-shadow:-.17em -.15em,.17em -.15em;content:"";height:.1em;width:.1em}.icon-emoji::after{border:.2rem solid currentColor;border-bottom-color:transparent;border-radius:50%;border-right-color:transparent;content:"";height:.5em;-webkit-transform:translate(-50%,-40%) rotate(-135deg);-ms-transform:translate(-50%,-40%) rotate(-135deg);transform:translate(-50%,-40%) rotate(-135deg);width:.5em}.btn .icon,.menu .icon,.toast .icon{vertical-align:-10%} -------------------------------------------------------------------------------- /static/spectre.min.css: -------------------------------------------------------------------------------- 1 | /*! Spectre.css | MIT License | github.com/picturepan2/spectre */html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}hr{box-sizing:content-box;height:0;overflow:visible}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}b,strong{font-weight:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}fieldset{border:0;margin:0;padding:0}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}template{display:none}[hidden]{display:none}*,::after,::before{box-sizing:inherit}html{box-sizing:border-box;font-size:10px;line-height:1.42857143;-webkit-tap-highlight-color:transparent}body{background:#fff;color:#50596c;font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;font-size:1.4rem;overflow-x:hidden;text-rendering:optimizeLegibility}a{color:#5764c6;outline:0;text-decoration:none}a:focus{box-shadow:0 0 0 .2rem rgba(87,100,198,.15)}a.active,a:active,a:focus,a:hover{color:#3b49af;text-decoration:underline}h1,h2,h3,h4,h5,h6{color:inherit;font-weight:300;line-height:1.2;margin-bottom:1.5rem;margin-top:0}h1{font-size:5rem}h2{font-size:4rem}h3{font-size:3rem}h4{font-size:2.4rem}h5{font-size:2rem}h6{font-size:1.6rem}p{line-height:2.4rem;margin:0 0 1rem}a,ins,u{-webkit-text-decoration-skip:ink edges;text-decoration-skip:ink edges}blockquote{border-left:.2rem solid #f0f1f4;margin-left:0;padding:1rem 2rem}blockquote p:last-child{margin-bottom:0}blockquote cite{color:#acb3c2}ol,ul{margin:2rem 0 2rem 2rem;padding:0}ol ol,ol ul,ul ol,ul ul{margin:1.5rem 0 1.5rem 2rem}ol li,ul li{margin-top:1rem}ul{list-style:disc inside}ul ul{list-style-type:circle}ol{list-style:decimal inside}ol ol{list-style-type:lower-alpha}dl dt{font-weight:700}dl dd{margin:.5rem 0 1.5rem 0}mark{background:#ffe9b3;border-radius:.2rem;color:#50596c;display:inline-block;line-height:1;padding:.3rem .4rem;vertical-align:baseline}kbd{background:#454d5d;border-radius:.2rem;color:#fff;display:inline-block;line-height:1;padding:.3rem .4rem;vertical-align:baseline}abbr[title]{border-bottom:.1rem dotted;cursor:help;text-decoration:none}.cjk,:lang(ja),:lang(ko),:lang(zh){font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","Hiragino Kaku Gothic Pro",Meiryo,"Malgun Gothic","Helvetica Neue",sans-serif}.cjk ins,.cjk u,:lang(ja) ins,:lang(ja) u,:lang(zh) ins,:lang(zh) u{border-bottom:.1rem solid;text-decoration:none}.cjk del+del,.cjk del+s,.cjk ins+ins,.cjk ins+u,.cjk s+del,.cjk s+s,.cjk u+ins,.cjk u+u,:lang(ja) del+del,:lang(ja) del+s,:lang(ja) ins+ins,:lang(ja) ins+u,:lang(ja) s+del,:lang(ja) s+s,:lang(ja) u+ins,:lang(ja) u+u,:lang(zh) del+del,:lang(zh) del+s,:lang(zh) ins+ins,:lang(zh) ins+u,:lang(zh) s+del,:lang(zh) s+s,:lang(zh) u+ins,:lang(zh) u+u{margin-left:.125em}.table{border-collapse:collapse;border-spacing:0;text-align:left;width:100%}.table.table-striped tbody tr:nth-of-type(odd){background:#f8f9fa}.table.table-hover tbody tr:hover{background:#f0f1f4}.table tbody tr.active,.table.table-striped tbody tr.active{background:#f0f1f4}.table td{border-bottom:.1rem solid #f0f1f4;padding:1.5rem 1rem}.table th{border-bottom:.1rem solid #727e96;padding:1.5rem 1rem}.btn{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#fff;border:.1rem solid #5764c6;border-radius:.2rem;color:#5764c6;cursor:pointer;display:inline-block;font-size:1.4rem;height:3.2rem;line-height:2rem;outline:0;padding:.5rem .8rem;text-align:center;text-decoration:none;transition:all .2s ease;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle;white-space:nowrap}.btn:focus{background:#fbfbfe;box-shadow:0 0 0 .2rem rgba(87,100,198,.15);text-decoration:none}.btn:hover{background:#5764c6;border-color:#4c59c2;color:#fff;text-decoration:none}.btn.active,.btn:active{background:#4c59c2;border-color:#3e4cb6;color:#fff;text-decoration:none}.btn.disabled,.btn:disabled,.btn[disabled]{cursor:default;opacity:.5;pointer-events:none}.btn.btn-primary{background:#5764c6;border-color:#4c59c2;color:#fff}.btn.btn-primary:focus,.btn.btn-primary:hover{background:#4452c0;border-color:#3e4cb6;color:#fff}.btn.btn-primary.active,.btn.btn-primary:active{background:#3f4eba;border-color:#3b49af;color:#fff}.btn.btn-primary.loading::after{border-bottom-color:#fff;border-left-color:#fff}.btn.btn-link{background:0 0;border-color:transparent;color:#5764c6}.btn.btn-link.active,.btn.btn-link:active,.btn.btn-link:focus,.btn.btn-link:hover{color:#3b49af}.btn.btn-sm{font-size:1.2rem;height:2.4rem;padding:.1rem .8rem}.btn.btn-lg{font-size:1.6rem;height:4rem;padding:.9rem .8rem}.btn.btn-block{display:block;width:100%}.btn.btn-action{padding-left:0;padding-right:0;width:3.2rem}.btn.btn-action.btn-sm{width:2.4rem}.btn.btn-action.btn-lg{width:4rem}.btn.btn-clear{background:0 0;border:0;color:currentColor;height:1.6rem;line-height:1.6rem;margin-left:.4rem;margin-right:-.2rem;opacity:.45;padding:0 .2rem;text-decoration:none;width:1.6rem}.btn.btn-clear:hover{opacity:.85}.btn.btn-clear::before{content:"\2715"}.btn-group{display:inline-flex;display:-ms-inline-flexbox;display:-webkit-inline-flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.btn-group .btn{-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.btn-group .btn:first-child:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group .btn:not(:first-child):not(:last-child){border-radius:0;margin-left:-.1rem}.btn-group .btn:last-child:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0;margin-left:-.1rem}.btn-group .btn.active,.btn-group .btn:active,.btn-group .btn:focus,.btn-group .btn:hover{z-index:1}.btn-group.btn-group-block{display:flex;display:-ms-flexbox;display:-webkit-flex}.btn-group.btn-group-block .btn{-webkit-flex:1 0 0;-ms-flex:1 0 0;flex:1 0 0}.form-group:not(:last-child){margin-bottom:1rem}.form-label{display:block;padding:.6rem 0}.form-label.label-sm{padding:.2rem 0}.form-label.label-lg{padding:1rem 0}.form-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#fff;background-image:none;border:.1rem solid #c4c9d3;border-radius:.2rem;color:#50596c;display:block;font-size:1.4rem;height:3.2rem;line-height:2rem;max-width:100%;outline:0;padding:.5rem .8rem;position:relative;transition:all .2s ease;width:100%}.form-input:focus{border-color:#5764c6;box-shadow:0 0 0 .2rem rgba(87,100,198,.15)}.form-input::-webkit-input-placeholder{color:#acb3c2}.form-input::-moz-placeholder{color:#acb3c2}.form-input:-ms-input-placeholder{color:#acb3c2}.form-input::placeholder{color:#acb3c2}.form-input.input-sm{font-size:1.2rem;height:2.4rem;padding:.1rem .8rem}.form-input.input-lg{font-size:1.6rem;height:4rem;padding:.9rem .8rem}.form-input.input-inline{display:inline-block;vertical-align:middle;width:auto}textarea.form-input{height:auto}.form-input[type=file]{height:auto}.form-input-hint{color:#acb3c2;margin-top:.4rem}.has-success .form-input-hint,.is-success+.form-input-hint{color:#32b643}.has-error .form-input-hint,.is-error+.form-input-hint{color:#e85600}.form-select{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:.1rem solid #c4c9d3;border-radius:.2rem;color:inherit;font-size:1.4rem;line-height:2rem;outline:0;padding:.5rem .8rem;vertical-align:middle;width:100%}.form-select[multiple] option{padding:.2rem .4rem}.form-select:not([multiple]){background:#fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23667189' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right .75rem center/.8rem 1rem;height:3.2rem;padding-right:2.4rem}.form-select:focus{border-color:#5764c6;box-shadow:0 0 0 .2rem rgba(87,100,198,.15)}.form-select::-ms-expand{display:none}.form-select.select-sm{font-size:1.2rem;height:2.4rem;padding:.1rem 2rem .1rem .6rem}.form-select.select-lg{font-size:1.6rem;height:4rem;padding:.9rem 2.4rem .9rem .8rem}.form-input.is-success,.form-select.is-success,.has-success .form-input,.has-success .form-select{border-color:#32b643}.form-input.is-success:focus,.form-select.is-success:focus,.has-success .form-input:focus,.has-success .form-select:focus{box-shadow:0 0 0 .2rem rgba(50,182,67,.15)}.form-input.is-error,.form-select.is-error,.has-error .form-input,.has-error .form-select{border-color:#e85600}.form-input.is-error:focus,.form-select.is-error:focus,.has-error .form-input:focus,.has-error .form-select:focus{box-shadow:0 0 0 .2rem rgba(232,86,0,.15)}.form-input:not(:placeholder-shown):invalid{border-color:#e85600}.form-input:not(:placeholder-shown):invalid:focus{box-shadow:0 0 0 .2rem rgba(232,86,0,.15)}.form-input:not(:placeholder-shown):invalid+.form-input-hint{color:#e85600}.has-icon-left,.has-icon-right{position:relative}.has-icon-left .form-icon,.has-icon-right .form-icon{margin:0 .8rem;min-width:1.4rem;position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.has-icon-left .form-icon{left:0}.has-icon-left .form-input{padding-left:3rem}.has-icon-right .form-icon{right:0}.has-icon-right .form-input{padding-right:3rem}.form-checkbox,.form-radio,.form-switch{display:inline-block;line-height:2rem;position:relative}.form-checkbox input,.form-radio input,.form-switch input{clip:rect(0,0,0,0);height:.1rem;margin:-.1rem;overflow:hidden;position:absolute;width:.1rem}.form-checkbox input:focus+.form-icon,.form-radio input:focus+.form-icon,.form-switch input:focus+.form-icon{border-color:#5764c6;box-shadow:0 0 0 .2rem rgba(87,100,198,.15)}.form-checkbox input:checked+.form-icon,.form-radio input:checked+.form-icon,.form-switch input:checked+.form-icon{background:#5764c6;border-color:#5764c6}.form-checkbox .form-icon,.form-radio .form-icon,.form-switch .form-icon{border:.1rem solid #c4c9d3;cursor:pointer;display:inline-block;position:absolute;transition:all .2s ease}.form-checkbox,.form-radio{padding:.2rem 2rem}.form-checkbox .form-icon,.form-radio .form-icon{background:#fff;height:1.4rem;left:0;top:.5rem;width:1.4rem}.form-checkbox input:active+.form-icon,.form-radio input:active+.form-icon{background:#f0f1f4}.form-checkbox .form-icon{border-radius:.2rem}.form-checkbox input:checked+.form-icon::before{background-clip:padding-box;border:.2rem solid #fff;border-left-width:0;border-top-width:0;content:"";height:1rem;left:50%;margin-left:-.3rem;margin-top:-.6rem;position:absolute;top:50%;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);width:.6rem}.form-checkbox input:indeterminate+.form-icon{background:#5764c6;border-color:#5764c6}.form-checkbox input:indeterminate+.form-icon::before{background:#fff;content:"";height:.2rem;left:50%;margin-left:-.5rem;margin-top:-.1rem;position:absolute;top:50%;width:1rem}.form-radio .form-icon{border-radius:.7rem}.form-radio input:checked+.form-icon::before{background:#fff;border-radius:.2rem;content:"";height:.4rem;left:50%;margin-left:-.2rem;margin-top:-.2rem;position:absolute;top:50%;width:.4rem}.form-switch{padding:.2rem 2rem .2rem 3.6rem}.form-switch .form-icon{background:#e7e9ed;background-clip:padding-box;border-radius:.9rem;height:1.8rem;left:0;top:.3rem;width:3rem}.form-switch .form-icon::before{background:#fff;border-radius:.8rem;content:"";display:block;height:1.6rem;left:0;position:absolute;top:0;transition:all .2s ease;width:1.6rem}.form-switch input:checked+.form-icon::before{left:1.2rem}.form-switch input:active+.form-icon::before{background:#f8f9fa}.input-group{display:flex;display:-ms-flexbox;display:-webkit-flex}.input-group .input-group-addon{background:#f8f9fa;border:.1rem solid #c4c9d3;border-radius:.2rem;line-height:2rem;padding:.5rem .8rem}.input-group .input-group-addon.addon-sm{font-size:1.2rem;padding:.1rem .8rem}.input-group .input-group-addon.addon-lg{font-size:1.6rem;padding:.9rem .8rem}.input-group .input-group-addon,.input-group .input-group-btn{-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.input-group .form-input:first-child:not(:last-child),.input-group .form-select:first-child:not(:last-child),.input-group .input-group-addon:first-child:not(:last-child),.input-group .input-group-btn:first-child:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.input-group .form-input:not(:first-child):not(:last-child),.input-group .form-select:not(:first-child):not(:last-child),.input-group .input-group-addon:not(:first-child):not(:last-child),.input-group .input-group-btn:not(:first-child):not(:last-child){border-radius:0;margin-left:-.1rem}.input-group .form-input:last-child:not(:first-child),.input-group .form-select:last-child:not(:first-child),.input-group .input-group-addon:last-child:not(:first-child),.input-group .input-group-btn:last-child:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0;margin-left:-.1rem}.input-group .form-input:focus,.input-group .form-select:focus,.input-group .input-group-addon:focus,.input-group .input-group-btn:focus{z-index:1}.input-group .form-select{width:auto}.input-group.input-inline{display:inline-flex;display:-ms-inline-flexbox;display:-webkit-inline-flex}.form-input.disabled,.form-input:disabled,.form-select.disabled,.form-select:disabled{background-color:#f0f1f4;cursor:not-allowed;opacity:.5}.form-input[readonly]{background-color:#f8f9fa}input.disabled+.form-icon,input:disabled+.form-icon{background:#f0f1f4;cursor:not-allowed;opacity:.5}.form-switch input.disabled+.form-icon::before,.form-switch input:disabled+.form-icon::before{background:#fff}.form-horizontal{padding:1rem}.form-horizontal .form-group{display:flex;display:-ms-flexbox;display:-webkit-flex}.form-horizontal .form-checkbox,.form-horizontal .form-radio,.form-horizontal .form-switch{margin:.4rem 0}.label{background:#f8f9fa;border-radius:.2rem;color:#5b657a;display:inline-block;line-height:1;padding:.3rem .4rem;vertical-align:baseline}.label.label-primary{background:#5764c6;color:#fff}.label.label-success{background:#32b643;color:#fff}.label.label-warning{background:#ffb700;color:#fff}.label.label-error{background:#e85600;color:#fff}code{background:#fdf4f4;border-radius:.2rem;color:#e06870;display:inline-block;line-height:1;padding:.3rem .4rem;vertical-align:baseline}.code{border-radius:.2rem;color:#50596c;line-height:2rem;position:relative}.code::before{color:#acb3c2;content:attr(data-lang);font-size:1.2rem;position:absolute;right:1rem;top:.2rem}.code code{background:#f8f9fa;color:inherit;display:block;line-height:inherit;overflow-x:auto;padding:2rem;width:100%}.img-responsive{display:block;height:auto;max-width:100%}.img-fit-cover{object-fit:cover}.img-fit-contain{object-fit:contain}.video-responsive{display:block;overflow:hidden;padding:0;position:relative;width:100%}.video-responsive::before{content:"";display:block;padding-bottom:56.25%}.video-responsive embed,.video-responsive iframe,.video-responsive object{bottom:0;height:100%;left:0;position:absolute;right:0;top:0;width:100%}.video-responsive video{height:auto;max-width:100%;width:100%}.video-responsive-4-3::before{padding-bottom:75%}.video-responsive-1-1::before{padding-bottom:100%}.figure{margin:0 0 1rem 0}.figure .figure-caption{color:#727e96;margin-top:1rem}.container{margin-left:auto;margin-right:auto;padding-left:1rem;padding-right:1rem;width:100%}.container.grid-1280{max-width:130rem}.container.grid-960{max-width:98rem}.container.grid-480{max-width:50rem}.columns{display:flex;display:-ms-flexbox;display:-webkit-flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-left:-1rem;margin-right:-1rem}.columns.col-gapless{margin-left:0;margin-right:0}.columns.col-gapless .column{padding-left:0;padding-right:0}.columns.col-oneline{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow-x:auto}.column{-webkit-flex:1;-ms-flex:1;flex:1;max-width:100%;padding:1rem}.column.col-1,.column.col-10,.column.col-11,.column.col-12,.column.col-2,.column.col-3,.column.col-4,.column.col-5,.column.col-6,.column.col-7,.column.col-8,.column.col-9{-webkit-flex:none;-ms-flex:none;flex:none}.col-12{width:100%}.col-11{width:91.66666667%}.col-10{width:83.33333333%}.col-9{width:75%}.col-8{width:66.66666667%}.col-7{width:58.33333333%}.col-6{width:50%}.col-5{width:41.66666667%}.col-4{width:33.33333333%}.col-3{width:25%}.col-2{width:16.66666667%}.col-1{width:8.33333333%}@media screen and (max-width:1280px){.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9{-webkit-flex:none;-ms-flex:none;flex:none}.col-xl-12{width:100%}.col-xl-11{width:91.66666667%}.col-xl-10{width:83.33333333%}.col-xl-9{width:75%}.col-xl-8{width:66.66666667%}.col-xl-7{width:58.33333333%}.col-xl-6{width:50%}.col-xl-5{width:41.66666667%}.col-xl-4{width:33.33333333%}.col-xl-3{width:25%}.col-xl-2{width:16.66666667%}.col-xl-1{width:8.33333333%}}@media screen and (max-width:960px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{-webkit-flex:none;-ms-flex:none;flex:none}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}}@media screen and (max-width:840px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{-webkit-flex:none;-ms-flex:none;flex:none}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}}@media screen and (max-width:600px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{-webkit-flex:none;-ms-flex:none;flex:none}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}}@media screen and (max-width:480px){.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{-webkit-flex:none;-ms-flex:none;flex:none}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}}.show-lg,.show-md,.show-sm,.show-xl,.show-xs{display:none!important}@media screen and (max-width:480px){.hide-xs{display:none!important}.show-xs{display:block!important}}@media screen and (max-width:600px){.hide-sm{display:none!important}.show-sm{display:block!important}}@media screen and (max-width:840px){.hide-md{display:none!important}.show-md{display:block!important}}@media screen and (max-width:960px){.hide-lg{display:none!important}.show-lg{display:block!important}}@media screen and (max-width:1280px){.hide-xl{display:none!important}.show-xl{display:block!important}}.navbar{-webkit-align-items:stretch;align-items:stretch;display:flex;display:-ms-flexbox;display:-webkit-flex;-ms-flex-align:stretch;-ms-flex-pack:justify;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-justify-content:space-between;justify-content:space-between}.navbar .navbar-section{-webkit-align-items:center;align-items:center;display:flex;display:-ms-flexbox;display:-webkit-flex;-webkit-flex:1 0 0;-ms-flex:1 0 0;flex:1 0 0;-ms-flex-align:center}.navbar .navbar-section:last-child{-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.navbar .navbar-center{-webkit-align-items:center;align-items:center;display:flex;display:-ms-flexbox;display:-webkit-flex;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-align:center}.navbar .navbar-brand{font-size:1.6rem;font-weight:500;text-decoration:none}.panel{border:.1rem solid #f0f1f4;border-radius:.2rem;display:flex;display:-ms-flexbox;display:-webkit-flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.panel .panel-footer,.panel .panel-header{-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;padding:1.5rem}.panel .panel-nav{-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.panel .panel-body{-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;overflow-y:auto;padding:0 1.5rem}.panel .panel-title{font-size:2rem}.panel .panel-subtitle{color:#bbc1cd}.empty{background:#f8f9fa;border-radius:.2rem;color:#727e96;padding:4rem;text-align:center}.empty .empty-subtitle,.empty .empty-title{margin:1rem auto}.empty .empty-subtitle{color:#bbc1cd}.empty .empty-action{margin-top:1.5rem}.form-autocomplete{position:relative}.form-autocomplete .form-autocomplete-input{-webkit-align-content:flex-start;align-content:flex-start;display:flex;display:-ms-flexbox;display:-webkit-flex;-ms-flex-line-pack:start;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;height:auto;min-height:3.2rem;padding:.1rem 0 0 .1rem}.form-autocomplete .form-autocomplete-input.is-focused{border-color:#5764c6;box-shadow:0 0 0 .2rem rgba(87,100,198,.15)}.form-autocomplete .form-autocomplete-input .form-input{border-color:transparent;box-shadow:none;display:inline-block;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;height:2.8rem;padding:.3rem .8rem;width:auto}.form-autocomplete mark{font-size:1;padding:.1em 0}.form-autocomplete .menu{left:0;position:absolute;top:100%;width:100%}.avatar{background:#5764c6;border-radius:50%;color:rgba(255,255,255,.85);display:inline-block;font-size:1.4rem;font-weight:300;height:3.2rem;line-height:1;margin:0;position:relative;vertical-align:middle;width:3.2rem}.avatar.avatar-xs{font-size:.8rem;height:1.6rem;width:1.6rem}.avatar.avatar-sm{font-size:1rem;height:2.4rem;width:2.4rem}.avatar.avatar-lg{font-size:2rem;height:4.8rem;width:4.8rem}.avatar.avatar-xl{font-size:2.6rem;height:6.4rem;width:6.4rem}.avatar img{border-radius:50%;height:100%;position:relative;width:100%;z-index:100}.avatar .avatar-icon{background:#fff;bottom:14.64%;height:50%;padding:.2rem;position:absolute;right:14.64%;-webkit-transform:translate(50%,50%);-ms-transform:translate(50%,50%);transform:translate(50%,50%);width:50%}.avatar[data-initial]::before{color:currentColor;content:attr(data-initial);left:50%;position:absolute;top:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);z-index:1}.badge{position:relative;white-space:nowrap}.badge:not([data-badge])::after,.badge[data-badge]::after{background:#5764c6;background-clip:padding-box;border-radius:1rem;box-shadow:0 0 0 .2rem #fff;color:#fff;content:attr(data-badge);display:inline-block;-webkit-transform:translate(-.2rem,-1rem);-ms-transform:translate(-.2rem,-1rem);transform:translate(-.2rem,-1rem)}.badge[data-badge]::after{font-size:1.2rem;height:1.8rem;line-height:1;min-width:1.8rem;padding:.3rem .5rem;text-align:center;white-space:nowrap}.badge:not([data-badge])::after,.badge[data-badge=""]::after{height:.6rem;min-width:.6rem;padding:0;width:.6rem}.badge.btn::after{position:absolute;right:0;top:0;-webkit-transform:translate(50%,-50%);-ms-transform:translate(50%,-50%);transform:translate(50%,-50%)}.badge.avatar::after{position:absolute;right:14.64%;top:14.64%;-webkit-transform:translate(50%,-50%);-ms-transform:translate(50%,-50%);transform:translate(50%,-50%);z-index:100}.badge.avatar-xs::after{content:"";height:.8rem;min-width:.8rem;padding:0;width:.8rem}.bar{background:#f0f1f4;border-radius:.2rem;display:flex;display:-ms-flexbox;display:-webkit-flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:1.6rem;width:100%}.bar.bar-sm{height:.4rem}.bar .bar-item{background:#5764c6;color:#fff;display:block;-ms-flex-negative:0;-webkit-flex-shrink:0;flex-shrink:0;font-size:1.2rem;height:100%;line-height:1;padding:.2rem 0;position:relative;text-align:center;width:0}.bar .bar-item:first-child{border-bottom-left-radius:.2rem;border-top-left-radius:.2rem}.bar .bar-item:last-child{border-bottom-right-radius:.2rem;border-top-right-radius:.2rem;-ms-flex-negative:1;-webkit-flex-shrink:1;flex-shrink:1}.bar-slider{height:.2rem;margin:1rem 0;position:relative}.bar-slider .bar-item{left:0;padding:0;position:absolute}.bar-slider .bar-item:not(:last-child):first-child{background:#f0f1f4;z-index:1}.bar-slider .bar-slider-btn{background:#5764c6;border:0;border-radius:50%;height:1.2rem;padding:0;position:absolute;right:0;top:50%;-webkit-transform:translate(50%,-50%);-ms-transform:translate(50%,-50%);transform:translate(50%,-50%);width:1.2rem}.bar-slider .bar-slider-btn:active{box-shadow:0 0 0 .2rem #5764c6}.card{background:#fff;border:.1rem solid #f0f1f4;border-radius:.2rem;display:block}.card .card-body,.card .card-footer,.card .card-header{padding:1.5rem;padding-bottom:0}.card .card-body:last-child,.card .card-footer:last-child,.card .card-header:last-child{padding-bottom:1.5rem}.card .card-image{padding-top:1.5rem}.card .card-image:first-child{padding-top:0}.card .card-image:first-child img{border-top-left-radius:.2rem;border-top-right-radius:.2rem}.card .card-image:last-child img{border-bottom-left-radius:.2rem;border-bottom-right-radius:.2rem}.card .card-title{font-size:2rem}.card .card-subtitle{color:#bbc1cd;font-size:1.2rem}.chip{-webkit-align-items:center;align-items:center;background:#f0f1f4;border-radius:.2rem;color:#727e96;display:-ms-inline-flexbox;display:inline-flex;display:-webkit-inline-flex;-ms-flex-align:center;height:2.8rem;margin:0 .1rem .1rem 0;max-width:100%;padding:.1rem .8rem;text-decoration:none;vertical-align:middle}.chip.active{background:#5764c6;color:#fff}.chip .avatar{margin-left:-.4rem;margin-right:.4rem}.dropdown{display:inline-block;position:relative}.dropdown .menu{-webkit-animation:slide-down .2s ease 1;animation:slide-down .2s ease 1;display:none;left:0;position:absolute;top:100%}.dropdown.dropdown-right .menu{left:auto;right:0}.dropdown .dropdown-toggle:focus+.menu,.dropdown .menu:hover,.dropdown.active .menu{display:block}.dropdown .btn-group .dropdown-toggle:nth-last-child(2){border-bottom-right-radius:.2rem;border-top-right-radius:.2rem}.menu{background:#fff;border-radius:.2rem;box-shadow:0 .1rem .4rem rgba(69,77,93,.3);list-style:none;margin:0;min-width:18rem;padding:1rem;-webkit-transform:translateY(.5rem);-ms-transform:translateY(.5rem);transform:translateY(.5rem);z-index:100}.menu .menu-item{margin-top:0;padding:0 .8rem;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.menu .menu-item>a{border-radius:.2rem;color:inherit;display:block;margin:0 -.8rem;padding:.6rem .8rem;text-decoration:none}.menu .menu-item>a:focus,.menu .menu-item>a:hover{color:#5764c6}.menu .menu-item>a.active,.menu .menu-item>a:active{background:#fbfbfe;color:#5764c6}.menu .menu-badge{float:right;padding:.6rem 0}.menu .menu-badge .btn{margin-top:-.2rem}.modal{-webkit-align-items:center;align-items:center;bottom:0;display:none;-ms-flex-align:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;left:0;opacity:0;overflow:hidden;padding:1rem;position:fixed;right:0;top:0}.modal.active,.modal:target{display:flex;display:-ms-flexbox;display:-webkit-flex;opacity:1;z-index:400}.modal.active .modal-overlay,.modal:target .modal-overlay{background:rgba(69,77,93,.5);bottom:0;cursor:default;display:block;left:0;position:absolute;right:0;top:0}.modal.active .modal-container,.modal:target .modal-container{-webkit-animation:slide-down .2s ease 1;animation:slide-down .2s ease 1;max-width:64rem;z-index:1}.modal.modal-sm .modal-container{max-width:32rem}.modal-container{background:#fff;border-radius:.2rem;box-shadow:0 .4rem 1rem rgba(69,77,93,.3);display:block;padding:0;text-align:left}.modal-container .modal-header{padding:1.5rem}.modal-container .modal-header .modal-title{font-size:1.6rem;margin:0}.modal-container .modal-body{max-height:50vh;overflow-y:auto;padding:1.5rem;position:relative}.modal-container .modal-footer{padding:1.5rem;text-align:right}.breadcrumb,.nav,.pagination,.tab{list-style:none;margin:.5rem 0}.breadcrumb{padding:1.2rem}.breadcrumb .breadcrumb-item{display:inline-block;margin:0}.breadcrumb .breadcrumb-item:last-child{color:#acb3c2}.breadcrumb .breadcrumb-item:not(:first-child)::before{color:#e7e9ed;content:"/";padding:0 .4rem}.tab{-webkit-align-items:center;align-items:center;display:flex;display:-ms-flexbox;display:-webkit-flex;-ms-flex-align:center;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.tab .tab-item{margin-top:0}.tab .tab-item.tab-action{-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;text-align:right}.tab .tab-item a{border-bottom:.2rem solid transparent;color:inherit;display:block;margin-top:0;padding:.6rem 1.2rem .4rem 1.2rem;text-decoration:none}.tab .tab-item a:focus,.tab .tab-item a:hover{color:#5764c6}.tab .tab-item a.active,.tab .tab-item.active a{border-bottom-color:#5764c6;color:#5764c6}.tab.tab-block .tab-item{-webkit-flex:1 0 0;-ms-flex:1 0 0;flex:1 0 0;text-align:center}.tab.tab-block .tab-item .badge[data-badge]::after{position:absolute;right:-.4rem;top:-.4rem;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.tab:not(.tab-block) .badge{padding-right:.2rem}.pagination{display:flex;display:-ms-flexbox;display:-webkit-flex}.pagination .page-item{margin:1rem .1rem}.pagination .page-item span{display:inline-block;padding:.6rem .4rem}.pagination .page-item a{border-radius:.2rem;color:#727e96;display:inline-block;padding:.6rem .8rem;text-decoration:none}.pagination .page-item a:focus,.pagination .page-item a:hover{color:#5764c6}.pagination .page-item a.disabled,.pagination .page-item a[disabled]{cursor:default;opacity:.5;pointer-events:none}.pagination .page-item.active a{background:#5764c6;color:#fff}.pagination .page-item.page-next,.pagination .page-item.page-prev{-webkit-flex:1 0 50%;-ms-flex:1 0 50%;flex:1 0 50%}.pagination .page-item.page-next{text-align:right}.pagination .page-item .page-item-title{margin:0}.pagination .page-item .page-item-subtitle{margin:0;opacity:.5}.nav{display:flex;display:-ms-flexbox;display:-webkit-flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.nav .nav-item a{color:#727e96;padding:.6rem .8rem;text-decoration:none}.nav .nav-item a:focus,.nav .nav-item a:hover{color:#5764c6}.nav .nav-item.active>a{font-weight:700}.nav .nav-item.active>a:focus,.nav .nav-item.active>a:hover{color:#5764c6}.nav .nav{margin-bottom:1rem;margin-left:2rem}.nav .nav a{color:#acb3c2}.popover{display:inline-block;position:relative}.popover .popover-container{content:attr(data-tooltip);left:50%;opacity:0;padding:1rem;position:absolute;top:0;-webkit-transform:translate(-50%,-50%) scale(0);-ms-transform:translate(-50%,-50%) scale(0);transform:translate(-50%,-50%) scale(0);transition:transform .2s ease,-webkit-transform .2s ease;transition:transform .2s ease;transition:-webkit-transform .2s ease;width:32rem;z-index:400}.popover .popover-container:hover,.popover :focus+.popover-container,.popover:hover .popover-container{display:block;opacity:1;-webkit-transform:translate(-50%,-100%) scale(1);-ms-transform:translate(-50%,-100%) scale(1);transform:translate(-50%,-100%) scale(1)}.popover.popover-right .popover-container{left:100%;top:50%}.popover.popover-right .popover-container:hover,.popover.popover-right :focus+.popover-container,.popover.popover-right:hover .popover-container{-webkit-transform:translate(0,-50%) scale(1);-ms-transform:translate(0,-50%) scale(1);transform:translate(0,-50%) scale(1)}.popover.popover-bottom .popover-container{left:50%;top:100%}.popover.popover-bottom .popover-container:hover,.popover.popover-bottom :focus+.popover-container,.popover.popover-bottom:hover .popover-container{-webkit-transform:translate(-50%,0) scale(1);-ms-transform:translate(-50%,0) scale(1);transform:translate(-50%,0) scale(1)}.popover.popover-left .popover-container{left:0;top:50%}.popover.popover-left .popover-container:hover,.popover.popover-left :focus+.popover-container,.popover.popover-left:hover .popover-container{-webkit-transform:translate(-100%,-50%) scale(1);-ms-transform:translate(-100%,-50%) scale(1);transform:translate(-100%,-50%) scale(1)}.popover .card{border:0;box-shadow:0 .4rem 1rem rgba(69,77,93,.3)}.step{display:flex;display:-ms-flexbox;display:-webkit-flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;list-style:none;margin:.5rem 0;width:100%}.step .step-item{-webkit-flex:1 1 0;-ms-flex:1 1 0;flex:1 1 0;margin-top:0;min-height:2rem;position:relative;text-align:center}.step .step-item:not(:first-child)::before{background:#5764c6;content:"";height:.2rem;left:-50%;position:absolute;top:.9rem;width:100%}.step .step-item a{color:#acb3c2;display:inline-block;padding:2rem 1rem 0;text-decoration:none}.step .step-item a::before{background:#5764c6;border:.2rem solid #fff;border-radius:50%;content:"";display:block;height:1.2rem;left:50%;position:absolute;top:.4rem;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);width:1.2rem;z-index:1}.step .step-item.active a::before{background:#fff;border:.2rem solid #5764c6}.step .step-item.active~.step-item::before{background:#f0f1f4}.step .step-item.active~.step-item a::before{background:#e7e9ed}.tile{-webkit-align-content:space-between;align-content:space-between;-webkit-align-items:flex-start;align-items:flex-start;display:flex;display:-ms-flexbox;display:-webkit-flex;-ms-flex-align:start;-ms-flex-line-pack:justify}.tile .tile-action,.tile .tile-icon{-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.tile .tile-content{-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.tile .tile-content:not(:first-child){padding-left:1rem}.tile .tile-content:not(:last-child){padding-right:1rem}.tile .tile-title{line-height:2rem}.tile .tile-subtitle{color:#bbc1cd;line-height:2rem}.tile.tile-centered{-webkit-align-items:center;align-items:center;-ms-flex-align:center}.tile.tile-centered .tile-content{overflow:hidden}.tile.tile-centered .tile-subtitle,.tile.tile-centered .tile-title{margin-bottom:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.toast{background:rgba(69,77,93,.9);border:.1rem solid #454d5d;border-color:#454d5d;border-radius:.2rem;color:#fff;display:block;padding:1rem;width:100%}.toast.toast-primary{background:rgba(87,100,198,.9);border-color:#5764c6}.toast.toast-success{background:rgba(50,182,67,.9);border-color:#32b643}.toast.toast-warning{background:rgba(255,183,0,.9);border-color:#ffb700}.toast.toast-error{background:rgba(232,86,0,.9);border-color:#e85600}.toast a{color:#fff;text-decoration:underline}.toast a.active,.toast a:active,.toast a:focus,.toast a:hover{opacity:.75}.tooltip{position:relative}.tooltip::after{background:rgba(69,77,93,.9);border-radius:.2rem;bottom:100%;color:#fff;content:attr(data-tooltip);display:block;font-size:1.2rem;left:50%;max-width:32rem;opacity:0;overflow:hidden;padding:.4rem .8rem;pointer-events:none;position:absolute;text-overflow:ellipsis;-webkit-transform:translate(-50%,1rem);-ms-transform:translate(-50%,1rem);transform:translate(-50%,1rem);transition:all .2s ease;white-space:nowrap;z-index:200}.tooltip:focus::after,.tooltip:hover::after{opacity:1;-webkit-transform:translate(-50%,-.5rem);-ms-transform:translate(-50%,-.5rem);transform:translate(-50%,-.5rem)}.tooltip.disabled,.tooltip[disabled]{pointer-events:auto}.tooltip.tooltip-right::after{bottom:50%;left:100%;-webkit-transform:translate(-1rem,50%);-ms-transform:translate(-1rem,50%);transform:translate(-1rem,50%)}.tooltip.tooltip-right:focus::after,.tooltip.tooltip-right:hover::after{-webkit-transform:translate(.5rem,50%);-ms-transform:translate(.5rem,50%);transform:translate(.5rem,50%)}.tooltip.tooltip-bottom::after{bottom:auto;top:100%;-webkit-transform:translate(-50%,-1rem);-ms-transform:translate(-50%,-1rem);transform:translate(-50%,-1rem)}.tooltip.tooltip-bottom:focus::after,.tooltip.tooltip-bottom:hover::after{-webkit-transform:translate(-50%,.5rem);-ms-transform:translate(-50%,.5rem);transform:translate(-50%,.5rem)}.tooltip.tooltip-left::after{bottom:50%;left:auto;right:100%;-webkit-transform:translate(1rem,50%);-ms-transform:translate(1rem,50%);transform:translate(1rem,50%)}.tooltip.tooltip-left:focus::after,.tooltip.tooltip-left:hover::after{-webkit-transform:translate(-.5rem,50%);-ms-transform:translate(-.5rem,50%);transform:translate(-.5rem,50%)}@-webkit-keyframes loading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes loading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes slide-down{0%{opacity:0;-webkit-transform:translateY(-3rem);transform:translateY(-3rem)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes slide-down{0%{opacity:0;-webkit-transform:translateY(-3rem);transform:translateY(-3rem)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}.divider,.divider-vert{display:block;position:relative}.divider-vert[data-content]::after,.divider[data-content]::after{background:#fff;color:#e7e9ed;content:attr(data-content);display:inline-block;font-size:1.2rem;padding:0 .8rem;-webkit-transform:translateY(-1.1rem);-ms-transform:translateY(-1.1rem);transform:translateY(-1.1rem)}.divider{border-top:.1rem solid #f0f1f4;height:.1rem;margin:1rem 0}.divider-vert{display:block;padding:1rem}.divider-vert::before{border-left:.1rem solid #f0f1f4;bottom:1rem;content:"";display:block;left:50%;position:absolute;top:1rem;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.divider-vert[data-content]::after{left:50%;padding:.4rem 0;position:absolute;top:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.loading{color:transparent!important;min-height:1.6rem;pointer-events:none;position:relative}.loading::after{-webkit-animation:loading .5s infinite linear;animation:loading .5s infinite linear;border:.2rem solid #5764c6;border-radius:.8rem;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1.6rem;left:50%;margin-left:-.8rem;margin-top:-.8rem;position:absolute;top:50%;width:1.6rem;z-index:1}.clearfix::after,.container::after{clear:both;content:"";display:table}.float-left{float:left!important}.float-right{float:right!important}.rel{position:relative}.abs{position:absolute}.fixed{position:fixed}.centered{display:block;float:none;margin-left:auto;margin-right:auto}.mt-10{margin-top:1rem}.mr-10{margin-right:1rem}.mb-10{margin-bottom:1rem}.ml-10{margin-left:1rem}.mt-5{margin-top:.5rem}.mr-5{margin-right:.5rem}.mb-5{margin-bottom:.5rem}.ml-5{margin-left:.5rem}.pt-10{padding-top:1rem}.pr-10{padding-right:1rem}.pb-10{padding-bottom:1rem}.pl-10{padding-left:1rem}.pt-5{padding-top:.5rem}.pr-5{padding-right:.5rem}.pb-5{padding-bottom:.5rem}.pl-5{padding-left:.5rem}.block{display:block}.inline{display:inline}.inline-block{display:inline-block}.flex{display:flex;display:-ms-flexbox;display:-webkit-flex}.inline-flex{display:inline-flex;display:-ms-inline-flexbox;display:-webkit-inline-flex}.hide{display:none!important}.visible{visibility:visible}.invisible{visibility:hidden}.text-hide{background:0 0;border:0;color:transparent;font-size:0;line-height:0;text-shadow:none}.text-assistive{border:0;clip:rect(0,0,0,0);height:.1rem;margin:-.1rem;overflow:hidden;padding:0;position:absolute;width:.1rem}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-normal{font-weight:400}.text-bold{font-weight:700}.text-italic{font-style:italic}.text-large{font-size:1.2em}.text-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-clip{overflow:hidden;text-overflow:clip;white-space:nowrap}.text-break{-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto;word-break:break-word;word-wrap:break-word}.hand{cursor:pointer}.shadow-0{box-shadow:0 0 .2rem rgba(69,77,93,.3)}.shadow-1{box-shadow:0 .1rem .4rem rgba(69,77,93,.3)}.shadow-2{box-shadow:0 .2rem .6rem rgba(69,77,93,.3)}.shadow-3{box-shadow:0 .3rem .8rem rgba(69,77,93,.3)}.shadow-4{box-shadow:0 .4rem 1rem rgba(69,77,93,.3)}.rounded{border-radius:.2rem}.circle{border-radius:50%} -------------------------------------------------------------------------------- /ui/CodeBlock.js: -------------------------------------------------------------------------------- 1 | import SyntaxHighlighter from 'react-syntax-highlighter'; 2 | 3 | export default ({ 4 | children 5 | }) => ( 6 |
7 | 8 | {children} 9 | 10 |
11 | ) 12 | -------------------------------------------------------------------------------- /ui/HighlightedTrie.js: -------------------------------------------------------------------------------- 1 | import TrieUI from './TrieUI.js'; 2 | import React from 'react'; 3 | import toHighlightedTreeData from "../packages/trie/util/toHighlightedTreeData.js"; 4 | 5 | export default ({ 6 | data, 7 | width, 8 | height, 9 | searchWord, 10 | }) => { 11 | return ( 12 | 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /ui/Link.js: -------------------------------------------------------------------------------- 1 | import { LinkHorizontal } from "@vx/shape"; 2 | 3 | export default function Link({ link }) { 4 | const color = "#ddd"; 5 | return ( 6 | 7 | ); 8 | }; 9 | -------------------------------------------------------------------------------- /ui/Node.js: -------------------------------------------------------------------------------- 1 | /** 2 | * I hear you like Node.js, so I put a Node.js in your Node.js. 3 | */ 4 | import { Group } from "@vx/group"; 5 | 6 | const primaryColor = "#5764c6"; 7 | const highlightColor = "#e06870"; 8 | 9 | export default function Node({ node, events }) { 10 | const width = 55; 11 | const height = 23; 12 | const cornerRadius = 5; 13 | const textColor = "white"; 14 | const color = (node.data.highlighted) 15 | ? highlightColor 16 | : primaryColor; 17 | 18 | return ( 19 | 20 | 31 | 39 | {node.data.name} 40 | 41 | 42 | ); 43 | } 44 | -------------------------------------------------------------------------------- /ui/SiteHead.js: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | export default ({ titleText }) => 3 | 4 | {titleText} 5 | 6 | 11 | 12 | 13 | ; 14 | -------------------------------------------------------------------------------- /ui/ToggleButton.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This React Component acts as a regular button, except 3 | * it can be toggled on/off by adding the "on" property. 4 | * 5 | * Example usage: 6 | * ``` 7 | * Cats // This is on 8 | * Dogs // This is off 9 | * ``` 10 | */ 11 | export default ({ 12 | on, 13 | children, 14 | ...restProps 15 | }) => { 16 | 17 | // If "on", activate the button! 18 | const toggle = (on) ? "active" : ""; 19 | const classes = `btn ${toggle}`; 20 | 21 | return ( 22 | 27 | ) 28 | } 29 | -------------------------------------------------------------------------------- /ui/TreeGraph.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Group } from "@vx/group"; 3 | import { Tree } from "@vx/hierarchy"; 4 | import { LinkHorizontal } from "@vx/shape"; 5 | import { hierarchy } from "d3-hierarchy"; 6 | import Node from './Node.js'; 7 | import Link from './Link.js'; 8 | 9 | class TreeGraph extends React.Component { 10 | constructor(props) { 11 | super(props); 12 | 13 | this.margin = props.margin; 14 | this.size = [ 15 | props.height - this.margin.top - this.margin.bottom, 16 | props.width - this.margin.left - this.margin.right 17 | ]; 18 | } 19 | 20 | render() { 21 | return ( 22 | 29 | 37 | 38 | ); 39 | } 40 | } 41 | 42 | export default TreeGraph; 43 | -------------------------------------------------------------------------------- /ui/TrieUI.js: -------------------------------------------------------------------------------- 1 | import TreeGraph from "./TreeGraph.js"; 2 | 3 | const margin = { 4 | top: 40, 5 | left: 50, 6 | right: 50, 7 | bottom: 40 8 | }; 9 | 10 | export default ({ 11 | data, 12 | width, 13 | height 14 | }) => ( 15 |
22 | 28 |
29 | ) 30 | -------------------------------------------------------------------------------- /ui/TrieWithButtons.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import TreeGraph from "./TreeGraph.js"; 3 | import Trie from "../packages/trie/index.js"; 4 | import toTreeData from "../packages/trie/util/toTreeData.js"; 5 | import toHighlightedTreeData from "../packages/trie/util/toHighlightedTreeData.js"; 6 | import ToggleButton from './ToggleButton.js'; 7 | import TrieUI from './TrieUI.js'; 8 | 9 | let trie = new Trie(); 10 | const margin = { 11 | top: 40, 12 | left: 50, 13 | right: 50, 14 | bottom: 40 15 | }; 16 | 17 | /** 18 | * Private Functions 19 | */ 20 | 21 | function createTrie(words) { 22 | const trie = new Trie(); // Reset trie 23 | words.forEach(w => trie.add(w)); 24 | return trie; 25 | } 26 | 27 | function getData(trie) { 28 | return toTreeData(trie)[0]; 29 | } 30 | 31 | /** 32 | * A trie with buttons to activate specific words. 33 | */ 34 | class TrieWithButtons extends React.Component { 35 | constructor(props) { 36 | super(props); 37 | 38 | const data = getData(trie, new Boolean(props.isHighlighted)); 39 | 40 | this.state = { 41 | data: data, 42 | activeWords: [] 43 | }; 44 | 45 | this.toggleWord = this.toggleWord.bind(this); 46 | this.setWords = this.setWords.bind(this); 47 | this.turnWordOff = this.turnWordOff.bind(this); 48 | this.turnWordOn = this.turnWordOn.bind(this); 49 | } 50 | 51 | /** 52 | * Given some active words, create a new trie with them 53 | * and set the state to match 54 | */ 55 | setWords(activeWords) { 56 | const trie = createTrie(activeWords); 57 | this.setState({ 58 | data: getData(trie), 59 | activeWords, 60 | }) 61 | } 62 | 63 | /** 64 | * Turns a word off in the Trie 65 | */ 66 | turnWordOff(activeWords, word) { 67 | // Remove word from list. 68 | const newActiveWords = activeWords.filter(item => item !== word); 69 | this.setWords(newActiveWords); 70 | } 71 | 72 | /** 73 | * Turns a word on in the Trie 74 | */ 75 | turnWordOn(activeWords, word) { 76 | activeWords.push(word); 77 | this.setWords(activeWords); 78 | } 79 | 80 | /** 81 | * Toggle a word, given an event. Generally called by an "onClick" method. 82 | */ 83 | toggleWord(event) { 84 | const word = event.target.value; 85 | const activeWords = this.state.activeWords.slice(); // Make a copy 86 | const wordAlreadyExists = activeWords.includes(word); 87 | 88 | if (wordAlreadyExists) { 89 | this.turnWordOff(activeWords, word); 90 | } else { 91 | this.turnWordOn(activeWords, word); 92 | } 93 | } 94 | 95 | render() { 96 | const buttons = this.props.words.map(w => { 97 | const isOn = this.state.activeWords.includes(w); 98 | return ( 99 | 100 | {w} 101 | 102 | ); 103 | }); 104 | 105 | return ( 106 |
111 | 115 | 116 |
117 | {buttons} 118 |
119 | 120 |
121 | ); 122 | } 123 | } 124 | 125 | export default TrieWithButtons; 126 | -------------------------------------------------------------------------------- /ui/TrieWithSearch.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import TreeGraph from "./TreeGraph.js"; 3 | import Trie from "../packages/trie/index.js"; 4 | import toTreeData from "../packages/trie/util/toTreeData.js"; 5 | import toHighlightedTreeData from "../packages/trie/util/toHighlightedTreeData.js"; 6 | import HighlightedTrie from './HighlightedTrie.js'; 7 | 8 | const trie = new Trie(); 9 | 10 | class TrieWithSearch extends React.Component { 11 | 12 | constructor(props) { 13 | super(props); 14 | 15 | props.words.forEach(w => trie.add(w)); 16 | this.state = { 17 | data: toTreeData(trie)[0], 18 | searchWord: "" 19 | } 20 | 21 | this.onChange = this.onChange.bind(this); 22 | } 23 | 24 | onChange(event) { 25 | this.setState({ 26 | searchWord : event.target.value 27 | }) 28 | } 29 | 30 | render() { 31 | const hasError = !trie.has(this.state.searchWord) 32 | 33 | return ( 34 |
39 | 44 | 45 |
46 | 52 | 53 |
54 | 55 |
56 | ); 57 | } 58 | } 59 | 60 | export default TrieWithSearch; 61 | -------------------------------------------------------------------------------- /ui/sections/BasicFunctions.js: -------------------------------------------------------------------------------- 1 | import TrieWithButtons from '../TrieWithButtons.js'; 2 | import TrieWithSearch from '../TrieWithSearch.js'; 3 | import CodeBlock from '../CodeBlock.js'; 4 | 5 | /** 6 | * Describes the basic functions of a trie. 7 | */ 8 | export default () => ( 9 |
10 | 11 |

Basic Functions of a Trie

12 |

Insert()

13 |

14 | The insert method of a Trie works by taking string and progressively taking each letter. The first node is generally empty, but for the purposes of explaination, we've labeled it as "root" in the demo below. 15 |

16 | 17 |
Pseudocode
18 | 19 | 20 | {` 21 | def insert(word): 22 | 23 | # Step 1: Grab the first letter of the word. 24 | firstLetter = word[0] 25 | 26 | # Step 2: Check if this letter already exists in 27 | # our children at this node. 28 | if not this.children[firstLetter]: 29 | this.children[firstLetter] = new Trie() 30 | 31 | # Step 3: Pop off the first letter, then recurse. 32 | word = word.removeFirstLetter() 33 | this.children[firstLetter].add(word) 34 | `} 35 | 36 | 37 |
Demo
38 | 39 | 44 | 45 |

Find()

46 |

47 | The find method of a Trie works in the same way that most other tree structures work. Take the first letter of the word you're looking for and see if that exists as a child node. If it doesn't, you can stop, as that word does not exist in the Trie. Otherwise, find the node with that letter and search it's children for the next lettter. If you've run out of letters, then you've your item. 48 |

49 | 50 |
Pseudocode
51 | 52 | 53 | {` 54 | def find(word): 55 | 56 | # Step 1: Do a check to see we've found the node 57 | if isEmptyString(word) return true; 58 | 59 | # Step 2: Check to see if we've hit a letter that's not 60 | # in the children of the current node 61 | const firstLetter = word[0]; 62 | if not this.children[firstLetter]: 63 | return false; 64 | else: 65 | 66 | # Step 3: Pop off the first letter and continue searching 67 | word = word.removeFirstLetter() 68 | return this.children[firstLetter].has(word) 69 | `} 70 | 71 | 72 | 77 | 78 |
79 | ) 80 | -------------------------------------------------------------------------------- /ui/sections/README.md: -------------------------------------------------------------------------------- 1 | # Sections 2 | 3 | This is the place where you can add the actually text of the article. 4 | -------------------------------------------------------------------------------- /ui/sections/introduction.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Introduction section 3 | */ 4 | export default () => ( 5 |
6 | 7 |

The Trie Data Structure

8 |

An Interactive Explanation

9 | 10 |

11 | A Trie (pronounced "try") is a tree data structure that is used to store Strings. It's generally used to search and store by prefix, which is why it is also known as a "prefix tree." 12 |

13 | 14 |

15 | Tries can often come up in software engineering interviews, however they aren't generally taught in a typical Data Structures course. Like all data structures, they're often better understood by interacting with them. 16 |

17 | 18 |

19 | This guide will feature written explanation, code samples, and interactive working Tries. You can find the code for the guide itself on Github, along with it's implementation of a Trie in Javascript. 20 |

21 | 22 |

23 | This guide was made by @FlaqueEau to help out members of the Gonzaga University Makers and Developers club and the greater dev community. If you find something wrong or want to add more, we'd love to merge your pull request! 24 |

25 |
26 | ) 27 | --------------------------------------------------------------------------------