Repository: hankchizljaw/boilerform Branch: master Commit: 01896b49b929 Files: 81 Total size: 118.3 KB Directory structure: gitextract_xrdk3epu/ ├── .babelrc ├── .eslintrc ├── .github/ │ ├── ISSUE_TEMPLATE.md │ └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE.txt ├── assets/ │ ├── js/ │ │ ├── boilerform.js │ │ └── modules/ │ │ └── validation.js │ └── scss/ │ ├── _config.scss │ ├── _functions.scss │ ├── _helpers.scss │ ├── _reset.scss │ ├── boilerform.scss │ ├── components/ │ │ ├── _c-button.scss │ │ ├── _c-check-field.scss │ │ ├── _c-input-field.scss │ │ ├── _c-label.scss │ │ └── _c-select-field.scss │ ├── layouts/ │ │ └── _l-form.scss │ └── mixins/ │ └── _namespace.scss ├── astrum-config.json ├── dist/ │ ├── css/ │ │ └── boilerform.css │ ├── js/ │ │ └── boilerform.js │ └── markup/ │ ├── button/ │ │ └── default/ │ │ └── markup.html │ ├── check-field/ │ │ ├── checkbox/ │ │ │ └── markup.html │ │ ├── error-state/ │ │ │ └── markup.html │ │ └── radio/ │ │ └── markup.html │ ├── input-field/ │ │ ├── email/ │ │ │ └── markup.html │ │ ├── error-state/ │ │ │ └── markup.html │ │ ├── number/ │ │ │ └── markup.html │ │ ├── search/ │ │ │ └── markup.html │ │ ├── tel/ │ │ │ └── markup.html │ │ ├── text/ │ │ │ └── markup.html │ │ └── text-area/ │ │ └── markup.html │ ├── label/ │ │ └── default/ │ │ └── markup.html │ └── select-field/ │ ├── error-state/ │ │ └── markup.html │ └── select-menu/ │ └── markup.html ├── generator/ │ └── dist.js ├── package.json ├── pattern-library/ │ ├── LICENSE.txt │ ├── app/ │ │ ├── css/ │ │ │ └── styles.css │ │ └── js/ │ │ └── main.js │ ├── assets/ │ │ └── js/ │ │ └── patterns.js │ ├── components/ │ │ ├── button/ │ │ │ ├── default/ │ │ │ │ ├── description.md │ │ │ │ └── markup.html │ │ │ └── description.md │ │ ├── check-field/ │ │ │ ├── checkbox/ │ │ │ │ ├── description.md │ │ │ │ └── markup.html │ │ │ ├── description.md │ │ │ ├── error-state/ │ │ │ │ ├── description.md │ │ │ │ └── markup.html │ │ │ └── radio/ │ │ │ ├── description.md │ │ │ └── markup.html │ │ ├── input-field/ │ │ │ ├── description.md │ │ │ ├── email/ │ │ │ │ ├── description.md │ │ │ │ └── markup.html │ │ │ ├── error-state/ │ │ │ │ ├── description.md │ │ │ │ └── markup.html │ │ │ ├── number/ │ │ │ │ ├── description.md │ │ │ │ └── markup.html │ │ │ ├── search/ │ │ │ │ ├── description.md │ │ │ │ └── markup.html │ │ │ ├── tel/ │ │ │ │ ├── description.md │ │ │ │ └── markup.html │ │ │ ├── text/ │ │ │ │ ├── description.md │ │ │ │ └── markup.html │ │ │ └── text-area/ │ │ │ ├── description.md │ │ │ └── markup.html │ │ ├── label/ │ │ │ ├── default/ │ │ │ │ ├── description.md │ │ │ │ └── markup.html │ │ │ └── description.md │ │ └── select-field/ │ │ ├── description.md │ │ ├── error-state/ │ │ │ ├── description.md │ │ │ └── markup.html │ │ └── select-menu/ │ │ ├── description.md │ │ └── markup.html │ ├── data.json │ └── index.html ├── readme.md └── webpack.config.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .babelrc ================================================ { "presets": ["env"], "plugins": ["babel-plugin-add-module-exports"] } ================================================ FILE: .eslintrc ================================================ { "parser": "babel-eslint", "env": { "browser": true, "commonjs": true, "es6": true, "node": true }, "rules": { "no-const-assign": "warn", "no-this-before-super": "warn", "no-unreachable": "warn", "no-unused-vars": "warn", "constructor-super": "warn", "valid-typeof": "warn", "quotes": [2, "single", { "allowTemplateLiterals": true }] } } ================================================ FILE: .github/ISSUE_TEMPLATE.md ================================================ ## Expected Behavior ## Actual Behavior ## Steps to Reproduce the Problem 1. 1. 1. ## Specifications - Version: - Platform: - Browser: - Environment/Url: ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ Fixes Issue # (Delete if not applicable) ## Proposed Changes - - - ## Add a GIF that demonstrates how this Pull Request makes you feel (optional) ![alt text](Path to image) ================================================ FILE: .gitignore ================================================ # Common node_modules .DS_Store .sass-cache *.log *.scssc npm-debug.* .env # Compiled assets pattern-library/assets/css # Ignore 'sandbox'. This is where you can play around with features etc sandbox/ ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change. Please note we have a code of conduct, please follow it in all your interactions with the project. ## Pull Request Process 1. Ensure any install or build dependencies are removed before the end of the layer when doing a build. 2. Ensure your work is thoroughly tested, to the best of your abilities 2. You may merge the Pull Request in once you have the sign-off from a maintainer ## Code of Conduct ### Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. ### Our Standards Examples of behavior that contributes to creating a positive environment include: - Using welcoming and inclusive language - Being respectful of differing viewpoints and experiences - Gracefully accepting constructive criticism - Focusing on what is best for the community - Showing empathy towards other community members Examples of unacceptable behavior by participants include: - The use of sexualized language or imagery and unwelcome sexual attention or advances - Trolling, insulting/derogatory comments, and personal or political attacks - Public or private harassment - Publishing others' private information, such as a physical or electronic address, without explicit permission - Other conduct which could reasonably be considered inappropriate in a professional setting ### Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ### Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ### Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at andy@hankchizljaw.io. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ### Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/ ================================================ FILE: LICENSE.txt ================================================ MIT License Copyright (c) 2018 hankchizljaw.io and other contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: assets/js/boilerform.js ================================================ import Validation from './modules/validation'; // Import Sass so that webpack picks it up require('../scss/boilerform.scss'); (function() { // Look for child and root forms const boilerforms = [...document.querySelectorAll('.boilerform form, form.boilerform')]; if(boilerforms.length) { // Add a validator to each form instance boilerforms.map(item => { let validationInstance = new Validation(item); validationInstance.init(); }); } }()); ================================================ FILE: assets/js/modules/validation.js ================================================ export default class Validation { /** * Load up an instance of Validation * @param {HTMLFormElement} baseForm */ constructor(baseForm) { this.baseForm = baseForm; // Load child input elements this.inputElems = [...baseForm.querySelectorAll('input, textarea, select')]; } /** * Public init method */ init() { let self = this; self.bind(); } /** * Bind events to input elements */ bind() { let self = this; // Add an invalid listener that self.inputElems.map(item => { item.addEventListener('invalid', () => { self.processValidity(item); self.checkSiblings(item); }, false); }); } /** * Toggle the visual state of an item based on the based state key * @param {HTMLElement} item * @param {String} state */ process(item, state = 'invalid') { switch(state) { case 'invalid': item.classList.add('is-error'); break; default: item.classList.remove('is-error'); break; } } /** * Filter sibling elements and run them through the validity checker * * @param {HTMLFormElement} exludedField */ checkSiblings(exludedField) { let self = this; self.inputElems .filter(item => item !== exludedField) .map(item => self.processValidity(item)); } /** * Run some checks to determine if the passed item is valid or not * @param {HTMLElement} item */ processValidity(item) { let self = this; // If an item is valid, run the processor and bail if(item.validity.valid) { self.process(item, 'valid'); return; } // If we're here, it's invalid self.process(item, 'invalid'); } }; ================================================ FILE: assets/scss/_config.scss ================================================ // Colors $colors: ( base: ( text: #141414, border: #cccccc ), button: ( background: #666666, background--hover: #888888, text: #ffffff ), check: ( decor: #eeeeee, decor--active: #aaaaaa, decor__inner: #888888 ), field: ( background: #ffffff ), state: ( error: #cf0b00 ) ); // Metrics $button-padding: 11px 25px 10px 25px; $check-field-decor-size: 20px; $check-field-flow: 10px; $check-field-label-padding: 3px 0 0 10px; $input-field-vertical-padding: 10px; $input-field-horizontal-padding: 15px; $input-field-padding: #{ $input-field-vertical-padding + 1 } $input-field-horizontal-padding $input-field-vertical-padding $input-field-horizontal-padding; $multiline-min-height: 80px; // Decorative $border-radius: 2px; // Typography $base-font-family: sans-serif; $base-font-size: 16px; $input-field-font-size: 1rem; ================================================ FILE: assets/scss/_functions.scss ================================================ /*------------------------------------*\ COLOR Pass in a group name and a key to get a value. E.G color(field, background) will return the background item in the field group. Colors are defined in $colors in _config.scss \*------------------------------------*/ @function color($group, $color) { @return map-get(map-get($colors, $group), $color); } ================================================ FILE: assets/scss/_helpers.scss ================================================ // All input fields share these styles. Also includes select menus %c-field-shared-inputs { background: color(field, background); border: 1px solid color(base, border); padding: $input-field-padding; border-radius: $border-radius; font-size: $input-field-font-size; } // Visually hide an element, but allow a screen-reader to see it %visually-hidden { display: block; height: 1px; width: 1px; overflow: hidden; clip: rect(1px 1px 1px 1px); clip: rect(1px, 1px, 1px, 1px); clip-path: inset(1px); white-space: nowrap; position: absolute; } ================================================ FILE: assets/scss/_reset.scss ================================================ @include namespace(true) { // Set base pixel size for REM units to work off font-size: $base-font-size; // Set the base color color: color(base, text); // Set base border color border-color: color(base, border); // Box sizing border-box FTW &, & * { box-sizing: border-box; } // All field elements [class*="-field"] { margin: 0; display: inline-block; vertical-align: middle; white-space: normal; line-height: 1.1; font-family: $base-font-family; } // All decorative elements [class*="decor"] { line-height: 0; } // Turn off the recent search in WebKit. ::-webkit-search-decoration { display: none; } // Normalise form field line-height in WebKit input::-webkit-input-placeholder, textarea::-webkit-input-placeholder, select::-webkit-input-placeholder { line-height: normal; } // Make a search box appear like a text box input[type="search"] { -webkit-appearance: textfield; } } ================================================ FILE: assets/scss/boilerform.scss ================================================ // Pull config @import "config"; // Mixins @import "mixins/namespace"; // Functions @import "functions"; // Helpers @import "helpers"; // Resets @import "reset"; // Components @import "components/c-button"; @import "components/c-check-field"; @import "components/c-input-field"; @import "components/c-label"; @import "components/c-select-field"; // Layouts @import "layouts/l-form"; // Shared styles @include namespace(true) { // Override border color for errors .is-error { &, [class*="menu"], [class*="check"] { border-color: color(state, error); // Remove default focus and replace with a heavy shadow if invalid &:focus { outline: none; box-shadow: 0 0 0 2px color(state, error); } } } } ================================================ FILE: assets/scss/components/_c-button.scss ================================================ /*------------------------------------*\ BUTTON COMPONENT Base button styles and reset \*------------------------------------*/ $namespace: ".c-button"; #{ $namespace } { @include namespace() { display: inline-block; border: none; padding: 0; margin: 0; text-decoration: none; background: color(button, background); color: color(button, text); padding: $button-padding; font-family: $base-font-family; font-size: 1rem; border-radius: $border-radius; cursor: pointer; text-align: center; -webkit-appearance: none; -moz-appearance: none; &:hover, &:focus { background: color(button, background--hover); } } } ================================================ FILE: assets/scss/components/_c-check-field.scss ================================================ /*------------------------------------*\ CHECK FIELD COMPONENT Radio buttons and checkboxes \*------------------------------------*/ $namespace: ".c-check-field"; #{ $namespace } { @include namespace() { display: flex; flex-direction: row; align-items: flex-start; // Visually hide the input &__input { @extend %visually-hidden; } &__decor { display: block; width: $check-field-decor-size; height: $check-field-decor-size; flex-shrink: 0; background: color(check, decor); border: 1px solid color(base, border); border-radius: $border-radius; position: relative; cursor: pointer; &:after { content: ""; speak: none; display: block; opacity: 0; width: 70%; height: 70%; position: absolute; top: 15%; left: 15%; background: color(check, decor__inner); border-radius: #{ $border-radius / 2 }; } } &__label { padding: $check-field-label-padding; cursor: pointer; } // Radio modifier &--radio #{ $namespace }__decor { &, &:after { border-radius: 50%; } } // Checked state &__input:checked ~ [class*="decor"] { &:after { opacity: 1; } } // Focused state &__input:focus ~ [class*="decor"] { outline: 1px dotted #212121; outline: 5px auto -webkit-focus-ring-color; } // Flow between instances & + #{ $namespace } { padding-top: $check-field-flow; } } } ================================================ FILE: assets/scss/components/_c-input-field.scss ================================================ /*------------------------------------*\ INPUT FIELD COMPONENT All input based form field elements \*------------------------------------*/ $namespace: ".c-input-field"; #{ $namespace } { @include namespace() { @extend %c-field-shared-inputs; // Reduce right-hand padding for number inputs &[type="number"] { padding-right: #{ $input-field-padding / 2 }; } // Multiline fields like ================================================ FILE: dist/markup/label/default/markup.html ================================================ ================================================ FILE: dist/markup/select-field/error-state/markup.html ================================================
================================================ FILE: dist/markup/select-field/select-menu/markup.html ================================================
================================================ FILE: generator/dist.js ================================================ var findRemoveSync = require('find-remove'); var fs = require('fs'); var ncp = require('ncp'); var path = require('path'); var rimraf = require('rimraf'); // Delete the markup dist dir rimraf(path.join(__dirname, '../dist/markup'), function() { // Copy the components from the pattern lib ncp(path.join(__dirname, '../pattern-library/components'), path.join(__dirname, '../dist/markup'), function(error) { if(error) return console.log(error); // Remove all markdown files findRemoveSync(path.join(__dirname, '../dist/markup'), { extensions: '.md' }); }); }); ================================================ FILE: package.json ================================================ { "name": "boilerform", "version": "1.1.1", "description": "A little collection of common form elements that have base markup and CSS set up for you.", "scripts": { "sass:dist-min": "uglifycss dist/css/boilerform.css > dist/css/boilerform.min.css", "watch": "webpack --watch", "build": "NODE_ENV=production webpack && npm run sass:dist-min && node generator/dist.js && echo Done 👍🏼" }, "repository": { "type": "git", "url": "git+https://github.com/hankchizljaw/boilerform.git" }, "author": "hankchizljaw", "license": "MIT", "bugs": { "url": "https://github.com/hankchizljaw/boilerform/issues" }, "homepage": "https://github.com/hankchizljaw/boilerform#readme", "devDependencies": { "babel-core": "^6.26.0", "babel-loader": "^7.1.2", "babel-plugin-add-module-exports": "^0.2.1", "babel-preset-env": "^1.6.1", "css-loader": "^0.28.7", "dotenv": "^5.0.1", "extract-text-webpack-plugin": "^3.0.2", "find-remove": "^1.2.0", "ncp": "^2.0.0", "node-sass": "^4.7.2", "rimraf": "^2.6.2", "sass-loader": "^6.0.6", "uglifycss": "0.0.27", "webpack": "^3.10.0" } } ================================================ FILE: pattern-library/LICENSE.txt ================================================ Copyright (c) Astrum by No Divide Studio Ltd (http://nodividestudio.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: pattern-library/app/css/styles.css ================================================ /** * Base styles * ----------------------------------------// */ .ndpl-body { background-color: #FFF; -ms-overflow-style: -ms-autohiding-scrollbar; margin: 0; padding: 0; } [class^="ndpl-"], [class*=" ndpl-"] { box-sizing: border-box; } .ndpl-disable-scrolling { overflow: hidden; } .ndpl-body.nav-open { overflow-y: hidden; } .ndpl-loading__title, .ndpl-error, .ndpl-info, .ndpl-header, .ndpl-sidebar, .ndpl-intro, .ndpl-library__title, .ndpl-group__description, .ndpl-component__title, .ndpl-component__description, .ndpl-component__label, .ndpl-component__code-toggle, .ndpl-component__color, .ndpl-page, .ndpl-nav__title, .ndpl-sidebar__title { font-family: 'Open Sans', 'Trebuchet MS', 'Lucida Grande', 'Lucida Sans Unicode', 'Lucida Sans', Tahoma, sans-serif; } /* Heading type sizes */ .ndpl-library__title { font-size: 27px; font-weight: 400; line-height: 36px; } .ndpl-component__title { font-size: 18px; font-weight: 300; line-height: 32px; } /* Body type size */ .ndpl-page, .ndpl-intro, .ndpl-group__description, .ndpl-component__description { font-size: 12px; font-weight: 300; line-height: 24px; } /* Page sizes */ .ndpl-page h1 { margin-bottom: 24px; } .ndpl-page h2, .ndpl-page h3, .ndpl-page h4, .ndpl-page h5, .ndpl-page h6 { margin: 24px 0 12px; } .ndpl-page h2:first-child, .ndpl-page h3:first-child, .ndpl-page h4:first-child, .ndpl-page h5:first-child, .ndpl-page h6:first-child { margin-top: 0; } .ndpl-page h1 { font-size: 26px; font-weight: 400; line-height: 36px; } .ndpl-page h2 { font-size: 21px; font-weight: 300; line-height: 36px; } .ndpl-page h3 { font-size: 18px; font-weight: 300; line-height: 32px; } .ndpl-page h4 { font-size: 16px; font-weight: 300; line-height: 27px; } .ndpl-page h5 { font-size: 14px; font-weight: 300; line-height: 24px; } .ndpl-page h6 { font-size: 14px; font-weight: 400; line-height: 24px; } .ndpl-page code, .ndpl-component__description code, .ndpl-group__description code { display: inline-block; color: #BABEC7; border: 1px solid #E1E1E1; border-radius: 3px; line-height: 18px; padding: 0 3px; } .ndpl-page a, .ndpl-page a[href] { text-decoration: none; } .ndpl-page a:hover, .ndpl-page a[href]:hover { text-decoration: underline; } .ndpl-page p { margin-bottom: 24px; } @media only screen and (min-width: 60em) { .ndpl-page h1 { margin-bottom: 48px; } .ndpl-page h2, .ndpl-page h3, .ndpl-page h4, .ndpl-page h5, .ndpl-page h6 { margin: 48px 0 24px; } /* Heading type sizes */ .ndpl-library__title { font-size: 36px; line-height: 36px; } .ndpl-component__title { font-size: 21px; line-height: 32px; } /* Body type size */ .ndpl-page, .ndpl-intro, .ndpl-group__description, .ndpl-component__description { font-size: 14px; line-height: 21px; } /* Page sizes */ .ndpl-page h1 { font-size: 36px; line-height: 36px; } .ndpl-page h2 { font-size: 28px; line-height: 36px; } .ndpl-page h3 { font-size: 21px; line-height: 32px; } .ndpl-page h4 { font-size: 18px; line-height: 27px; } .ndpl-page h5 { font-size: 16px; line-height: 24px; } .ndpl-page h6 { font-size: 16px; line-height: 24px; } } /** * #303637 - Heading color * #616367 - Body color * #B0B1B3 - Dimmed color * * Theme colors * ----------------------------------------// */ .ndpl-c-background { background-color: #FFF; } /* Background color */ .ndpl-c-border { border-color: #E0E6ED; } /* Border color */ .ndpl-c-highlight { background-color: #F9FAFC; } /* Highlight background */ .ndpl-c-brand-c { color: #FEA1AC; } /* Brand color */ .ndpl-c-brand-bg { background-color: #FEA1AC; } /* Brand background color */ .ndpl-c-brand-b { border-color: #FEA1AC; } /* Brand border color */ .ndpl-c-brand-a:hover { color: #FEA1AC; } /* Brand anchor on hover */ .ndpl-c-brand-ca a, .ndpl-c-brand-ca a[href], .ndpl-c-brand-ca a[href]:focus, .ndpl-c-brand-ca a:focus, .ndpl-c-brand-ca a[href]:active, .ndpl-c-brand-ca a:active, .ndpl-c-brand-ca a[href]:visited, .ndpl-c-brand-ca a:visited { color: #303637; } /* Brand child anchors */ .ndpl-c-brand-ca a[href]:hover, .ndpl-c-brand-ca a:hover { color: #FEA1AC; } /* Brand child anchors on hover */ .ndpl-c-brand-cai a, .ndpl-c-brand-cai a[href], .ndpl-c-brand-cai a[href]:focus, .ndpl-c-brand-cai a:focus, .ndpl-c-brand-cai a[href]:active, .ndpl-c-brand-cai a:active, .ndpl-c-brand-cai a[href]:visited, .ndpl-c-brand-cai a:visited { color: #FEA1AC; } /* Brand child anchors */ .ndpl-c-brand-cai a[href]:hover, .ndpl-c-brand-cai a:hover { color: #303637 !important; } /* Brand child anchors on hover */ /** * Helpers * ----------------------------------------// */ /* No state change for anchors */ .ndpl-nsc, .ndpl-nsc:focus, .ndpl-nsc[href]:focus, .ndpl-nsc:hover, .ndpl-nsc[href]:hover, .ndpl-nsc:active, .ndpl-nsc[href]:active, .ndpl-nsc:visited, .ndpl-nsc[href]:visited { color: #303637 !important; text-decoration: none; } .ndpl-cf:after { content: ""; display: block; clear: both; } .ndpl-dark-text { color: #616367 !important; } .ndpl-light-text { color: #FFF !important; } .ndpl-apply-border { border: 1px solid #E0E6ED; } .ndpl-apply-border + .ndpl-apply-border { border-top: none; } /** * Loading * ----------------------------------------// */ .ndpl-loading__title { color: #303637; font-weight: 300; margin: 0 24px 24px; opacity: 0; transition: opacity .5s ease; } .wf-opensans-n4-active .ndpl-loading__title { opacity: 1; } .ndpl-container { opacity: 0; transition: opacity .5s ease .5s; } .ndpl-container.loaded { opacity: 1; } .ndpl-container.resizing { visibility: hidden; } .ndpl-loading { left: -9999px; opacity: 0; padding: 96px 0; position: fixed; text-align: center; transition: opacity .5s ease; width: 100%; } .ndpl-loading.in-progress { left: 0; opacity: 1; } .ndpl-loading__title { font-size: 27px; padding-top: 24px; } @media only screen and (min-width: 60em) { .ndpl-loading__title { font-size: 36px; padding-top: 24px; } } /** * Errors * ----------------------------------------// */ .ndpl-error, .ndpl-info { border-radius: 6px; color: #FFF; display: inline-block; list-style: none; margin: 0 12px; padding: 24px; font-size: 14px; } .ndpl-error { background-color: #f97d7d; } .ndpl-info { background-color: #7da9f9; } .ndpl-error code, .ndpl-info code { padding: 0 3px; } .ndpl-error code { background-color: #e07070; } .ndpl-info code { background-color: #7098e0; } .ndpl-error .ndpl-pre, .ndpl-info .ndpl-pre { margin-bottom: 0; } @media only screen and (min-width: 60em) { .ndpl-error, .ndpl-info { margin: 0; } } /** * Folding cube animation * Created by Tobias Ahlin * http://tobiasahlin.com/spinkit/ * ----------------------------------------// */ .ndpl-folding-cube { margin: 20px auto; width: 40px; height: 40px; position: relative; -webkit-transform: rotateZ(45deg); transform: rotateZ(45deg); } .ndpl-folding-cube .ndpl-cube { float: left; width: 50%; height: 50%; position: relative; -webkit-transform: scale(1.1); -ms-transform: scale(1.1); transform: scale(1.1); } .ndpl-folding-cube .ndpl-cube:before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: #303637; -webkit-animation: ndpl-foldCubeAngle 2.4s infinite linear both; animation: ndpl-foldCubeAngle 2.4s infinite linear both; -webkit-transform-origin: 100% 100%; -ms-transform-origin: 100% 100%; transform-origin: 100% 100%; } .ndpl-folding-cube .ndpl-cube2 { -webkit-transform: scale(1.1) rotateZ(90deg); transform: scale(1.1) rotateZ(90deg); } .ndpl-folding-cube .ndpl-cube3 { -webkit-transform: scale(1.1) rotateZ(180deg); transform: scale(1.1) rotateZ(180deg); } .ndpl-folding-cube .ndpl-cube4 { -webkit-transform: scale(1.1) rotateZ(270deg); transform: scale(1.1) rotateZ(270deg); } .ndpl-folding-cube .ndpl-cube2:before { -webkit-animation-delay: 0.3s; animation-delay: 0.3s; } .ndpl-folding-cube .ndpl-cube3:before { -webkit-animation-delay: 0.6s; animation-delay: 0.6s; } .ndpl-folding-cube .ndpl-cube4:before { -webkit-animation-delay: 0.9s; animation-delay: 0.9s; } @-webkit-keyframes ndpl-foldCubeAngle { 0%, 10% { -webkit-transform: perspective(140px) rotateX(-180deg); transform: perspective(140px) rotateX(-180deg); opacity: 0; } 25%, 75% { -webkit-transform: perspective(140px) rotateX(0deg); transform: perspective(140px) rotateX(0deg); opacity: 1; } 90%, 100% { -webkit-transform: perspective(140px) rotateY(180deg); transform: perspective(140px) rotateY(180deg); opacity: 0; } } @keyframes ndpl-foldCubeAngle { 0%, 10% { -webkit-transform: perspective(140px) rotateX(-180deg); transform: perspective(140px) rotateX(-180deg); opacity: 0; } 25%, 75% { -webkit-transform: perspective(140px) rotateX(0deg); transform: perspective(140px) rotateX(0deg); opacity: 1; } 90%, 100% { -webkit-transform: perspective(140px) rotateY(180deg); transform: perspective(140px) rotateY(180deg); opacity: 0; } } /** * Header * ----------------------------------------// */ .ndpl-header { background-color: #FFF; border-bottom: 1px solid #DDD; box-shadow: 0 0 1px rgba(0,0,0,0.1); margin:0 0 36px; padding: 12px; position: fixed; top: 0; width: 100%; z-index: 9998; } .ndpl-header:after { display: none; } .ndpl-header__logo { float: left; height: 28px; margin: 0 6px 0 0; } .ndpl-header__title { color: #303637; font-size: 18px; font-weight: 700; line-height: 28px; float: left; margin: 0; } .ndpl-header__title a { display: none; } .ndpl-header__title a, .ndpl-header__title a:hover { text-decoration: none !important; } .ndpl-header__title small { font-size: 60%; font-weight: 300; margin-left: 6px; } @media only screen and (min-width: 60em) { .ndpl-header { display: none; } .ndpl-header__title a { display: block; } } /** * Sidebar * ----------------------------------------// */ .ndpl-sidebar { background-color: #FFF; bottom: 0; box-shadow: 1px 0 2px rgba(0,0,0,0.2); height: 100%; left: -100%; overflow-y: auto; overflow-x: hidden; padding: 103px 0 24px; position: fixed; right: 0; top: 0; width: 100%; z-index: 9997; } .ndpl-mobile .ndpl-sidebar { transition: left .5s ease; } .ndpl-sidebar.open { left: 0; } .ndpl-sidebar__header { display: none; } .ndpl-sidebar__logo { float: left; margin: 0 0 24px 0; height: 50px; } @media only screen and (min-width: 60em) { .ndpl-sidebar { background-color: #FFF; bottom: 0; display: block; left: -264px; padding: 0; position: fixed; top: 0; width: 264px; } .loaded .ndpl-sidebar { left: 0; } /** * Sidebar - Header * ----------------------------------------// */ .ndpl-sidebar__header { display: block; padding: 24px 24px 36px; } .ndpl-sidebar__title { color: #303637; clear: left; display: block; font-size: 18px; line-height: 24px; font-weight: 700; margin: 0; } .ndpl-sidebar__title a { text-decoration: none; } .ndpl-sidebar__title a:hover { color: #FEA1AC; } .ndpl-sidebar__title small { display: block; font-size: 16px; font-weight: 400; } } /** * Copyright info * ----------------------------------------// */ .ndpl-copyright { display: block; padding: 0 24px 24px; } .ndpl-copyright p { color: #B0B1B3; font-size: 12px; font-weight: 300; line-height: 21px; } .ndpl-copyright p:last-of-type { margin: 0; } .ndpl-copyright a { text-decoration: none; } /** * Navigation - Title * ----------------------------------------// */ .ndpl-nav__title { color: #303637; font-size: 12px; font-weight: 700; letter-spacing: 1px; margin: 0 0 21px; padding: 0 24px; text-transform: uppercase; } /** * Navigation - Structure * ----------------------------------------// */ .ndpl-nav__items { border-top: 1px solid transparent; font-size: 14px; font-weight: 400; line-height: 24px; list-style: none; margin: 0 0 72px; padding: 0; } .ndpl-nav__item { position: relative; } .ndpl-nav__item.active .ndpl-nav__group { font-weight: 700; } .ndpl-nav__child-items { display: none; font-size: 14px; list-style: none; min-height: 0; padding: 0; margin: 0; } .active .ndpl-nav__child-items { display: block; } .ndpl-nav__child-item { border-bottom: 1px solid transparent; border-radius: 4px; } /** * Navigation - Page * ----------------------------------------// */ .ndpl-nav__page { border-bottom: 1px solid #E0E6ED; border-left: 6px solid transparent; cursor: pointer; display: block; font-weight: 400; padding: 6px 24px 6px 18px; position: relative; text-decoration: none; } .ndpl-nav__page.active, .ndpl-nav__page:hover { border-left-color: #FEA1AC; } /** * Navigation - Group * ----------------------------------------// */ .ndpl-nav__group { border-bottom: 1px solid #E0E6ED; display: block; font-weight: 400; padding: 6px 24px; position: relative; text-decoration: none; } .ndpl-nav__group:after { background: transparent url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5IiBoZWlnaHQ9IjE1IiB2aWV3Qm94PSIwIDAgOSAxNSI+CiAgPGRlZnM+CiAgICA8c3R5bGU+CiAgICAgIC5jbH MtMSB7CiAgICAgICAgZmlsbDogIzIzMWYyMDsKICAgICAgICBmaWxsLXJ1bGU6IGV2ZW5vZGQ7CiAgICAgIH0KICAgIDwvc3R5bGU+CiAgPC9kZWZzPgogIDxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQ2MC40NDgsNDkxLjAwOUw0NjgsNDk4LjVsLTcuNTQ4LDcuNDkyTDQ1OSw1MDQuNTU3bDYuMS02LjA1NS02LjEtNi4wNTdaIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNDU5IC00OTEpIi8+Cjwvc3ZnPgo=") center no-repeat; background-size: 100% auto; content: ""; display: block; height: 8px; margin-top: -4px; position: absolute; right: 24px; top: 50%; transform: rotate(90deg); transition: transform .25s ease; width: 5px; } .active .ndpl-nav__group:after { transform: rotate(-90deg); } /** * Navigation - Component * ----------------------------------------// */ .ndpl-nav__component { border-left: 6px solid transparent; color: #616367 !important; display: block; font-size: 14px; font-weight: 300; padding: 6px 24px 6px 30px; text-decoration: none; } .ndpl-nav__component.active, .ndpl-nav__component:hover { border-left-color: #FEA1AC; } .ndpl-nav__arrow { margin: -4px 0 0; opacity: 0.25; position: absolute; right: 12px; top: 18px; width: 16px; } .active .ndpl-nav__arrow { transform: rotate(180deg); } /* * Navigation * ----------------------------------------// */ .ndpl-nav-handle { display: block; cursor: pointer; height: 27px; overflow: hidden; position: fixed; right: 0; transform: rotate(0deg); transition: .5s ease-in-out; top: 15px; width: 48px; z-index: 9999; } .ndpl-nav-handle.open { position: fixed; } .ndpl-nav-handle__container { padding: 12px 0 0; } .ndpl-nav-handle span { background-color: #303637; display: block; height: 3px; opacity: 1; position: absolute; right: 12px; transform: rotate(0deg); transition: .25s ease-in-out; width: 27px; } .ndpl-nav-handle span:nth-child(1) { top: 0px; } .ndpl-nav-handle span:nth-child(2) { top: 9px; } .ndpl-nav-handle span:nth-child(3) { top: 18px; } .ndpl-nav-handle.open span:nth-child(1) { top: 11px; transform: rotate(-45deg); } .ndpl-nav-handle.open span:nth-child(2) { opacity: 0; right: -60px; } .ndpl-nav-handle.open span:nth-child(3) { top: 11px; transform: rotate(45deg); } @media only screen and (min-width: 60em) { .ndpl-nav-handle { display: none; } } /** * Content containers * ----------------------------------------// */ .ndpl-page, .ndpl-library { padding-top: 79px; } .ndpl-page { color: #616367; padding-left: 12px; padding-right: 12px; } .ndpl-page h1, .ndpl-page h2, .ndpl-page h3, .ndpl-page h4, .ndpl-page h5, .ndpl-page h6 { color: #303637; } .ndpl-preloaded { left: -9999px; position: absolute; top: -9999px; } @media only screen and (min-width: 35em) { .ndpl-page { max-width: 580px; margin: 0 auto; } } @media only screen and (min-width: 60em) { .ndpl-page, .ndpl-library { margin: 0 auto; padding: 56px 0; } .ndpl-page h1:first-child, .ndpl-page h2:first-child, .ndpl-page h3:first-child, .ndpl-page h4:first-child, .ndpl-page h5:first-child, .ndpl-page h6:first-child, .ndpl-library h1:first-child, .ndpl-library h2:first-child, .ndpl-library h3:first-child, .ndpl-library h4:first-child, .ndpl-library h5:first-child, .ndpl-library h6:first-child { margin-top: 0; } .ndpl-content { padding: 36px 48px 36px 312px; } } /** * Component Group * ----------------------------------------// */ .ndpl-library__group { overflow: auto; zoom: 1; } .ndpl-library__title { color: #303637; padding-left: 12px; padding-right: 12px; margin-bottom: 24px; } @media only screen and (min-width: 60em) { .ndpl-library__title { padding-left: 0; padding-right: 0; margin-bottom: 24px; } } /** * Group * ----------------------------------------// */ .ndpl-group__description { color: #616367; margin-bottom: 48px; padding: 0 12px; } @media only screen and (min-width: 60em) { .ndpl-group__description { padding: 0; } } /** * Component * ----------------------------------------// */ .ndpl-component { clear: both; margin-bottom: 60px; } .ndpl-component__title, .ndpl-component__description { color: #616367; padding: 0 12px; } .ndpl-component__title { margin-bottom: 12px; } .ndpl-component__description { padding-bottom: 24px; } @media only screen and (min-width: 60em) { .ndpl-component__title, .ndpl-component__description { padding: 0; } } /** * Component - Half Width * ----------------------------------------// */ @media only screen and (min-width: 60em) { .ndpl-components { display: -ms-flexbox; display: -webkit-flex; display: flex; -ms-flex-direction: row; -webkit-flex-direction: row; flex-direction: row; -ms-flex-wrap: wrap; -webkit-flex-wrap: wrap; flex-wrap: wrap; margin-left: -36px; } .ndpl-component { padding-left: 36px; } .ndpl-component--half { -ms-flex-grow: 2; -webkit-flex-grow: 2; flex-grow: 2; max-width: 50%; width: 50%; } .ndpl-component--full { -ms-flex-grow: 1; -webkit-flex-grow: 1; flex-grow: 1; width: 100%; } } /** * Component - Colours * ----------------------------------------// */ .ndpl-component__colors { padding: 0 12px; } .ndpl-component__color-container { float: left; margin-top: 24px; width: 100%; } .ndpl-component__color-container:first-of-type { margin-top: 0; } .ndpl-component__color-container:nth-child(even) { margin-right: 0; } .ndpl-component__color { float: left; line-height: 1; padding: 24px 0; text-align: center; width: 50%; } .ndpl-component__color:first-of-type { border-radius: 6px 0 0 6px; } .ndpl-component__color:last-of-type { border-radius: 0 6px 6px 0; } .ndpl-component__color:first-of-type:last-of-type { border-radius: 6px; width: 100%; } .ndpl-component__color div { border: 1px solid #FFF; border-radius: 3px; color: #FFF; display: inline-block; font-size: 13px; letter-spacing: 1px; line-height: 13px; padding: 6px 9px; text-transform: uppercase; } .ndpl-component__color div.ndpl-dark-text { color: #B0B1B3 !important; border-color: #B0B1B3; } @media only screen and (min-width: 60em) { .ndpl-component__colors { padding: 0; } .ndpl-component__color-container { margin-right: 3%; width: 17.5%; } .ndpl-component__color-container:nth-child(even) { margin-right: 3%; } .ndpl-component__color-container:nth-child(5n) { margin-right: 0; } .ndpl-component__color-container:nth-child(-n + 5) { margin-top: 0; } .ndpl-component__color { padding: 48px 0; width: 100%; } .ndpl-component__color:first-of-type { border-radius: 6px 6px 0 0; } .ndpl-component__color:last-of-type { border-radius: 0 0 6px 6px; } } /** * Component - Preview & code sample * ----------------------------------------// */ .ndpl-component__sample { background-color: #FFF; border-top: 1px solid #E0E6ED; border-bottom: 1px solid #E0E6ED; padding: 36px 12px; position: relative; } .ndpl-component__sample:after { display: block; clear: both; content: ""; } .ndpl-component__sample--inverted { background-color: #333; } .ndpl-component__sample-missing, .ndpl-component__sample-hidden { display: block; margin: 0 12px; text-align: center; } .ndpl-component__code { border-bottom: 1px solid #E0E6ED; } .ndpl-component__code .ndpl-pre { margin: 0; } /* We apply the same code styling to page, description and component elements. */ .ndpl-page pre code, .ndpl-component__description pre code, .ndpl-component__code .ndpl-code { box-sizing: border-box; color: #616367; font-size: 12px; line-height: 18px; opacity: 0.75; overflow-x: auto; overflow-y: hidden; -ms-overflow-style: -ms-autohiding-scrollbar; padding: 36px 12px; white-space: pre; width: 100%; } .ndpl-page pre code, .ndpl-component__description pre code { padding: 12px; } .ndpl-component__code-toggle { border-bottom: 1px solid transparent; color: #B0B1B3; cursor: pointer; display: block; font-size: 12px; letter-spacing: 1px; padding: 9px 12px 9px 12px; text-align: center; text-transform: uppercase; } @media only screen and (min-width: 60em) { .ndpl-component__sample { border: 1px solid #E0E6ED; border-radius: 6px 6px 0 0; padding: 36px; } .ndpl-component__sample--disabled-code { border-radius: 6px; } .ndpl-component__sample-missing, .ndpl-component__sample-hidden { margin: 0; } .ndpl-component__code { border: 1px solid #E0E6ED; border-top: none; } .ndpl-page pre code, .ndpl-component__description pre code, .ndpl-component__code .ndpl-code { font-size: 15px; line-height: 21px; padding: 36px; } .ndpl-page pre code, .ndpl-component__description pre code { padding: 12px; } .ndpl-component__code-toggle { border-left: 1px solid transparent; border-right: 1px solid transparent; border-radius: 0 0 6px 6px; } } ================================================ FILE: pattern-library/app/js/main.js ================================================ /** * Component component */ var ndplComponent = Vue.extend({ data: function() { return { loaded: false, hide_sample_code: false } }, props: { component: { required: true } }, computed: { inline_styles: function() { var _this = this, styles = ''; // These inline style are only applied after the component has fully loaded if(_this.loaded) { if(_this.component.options.sample_min_height) { styles += 'min-height:' + _this.component.options.sample_min_height + 'px;'; } } if(_this.component.options.sample_overflow_hidden) { styles += 'overflow: hidden;'; } if(_this.component.options.sample_background_color) { styles += 'background-color:' + _this.component.options.sample_background_color + ' !important;'; } return styles; } }, watch: { 'component.html': function() { var _this = this; // Apply syntax highlighting when component html is loaded if(this.component.html.length) { _this.$root.applySyntaxHighlighting(_this.$el); } } }, ready: function() { var _this = this; // Listen for loaded event _this.$on('loaded', function() { // Monitor scroll and resize events and update navigation active state appropirately window.addEventListener('scroll', _this.updateActive); window.addEventListener('resize', _this.updateActive); _this.setHideSample(function() { _this.loaded = true; }); }); // Listen for resizing event _this.$on('resizing', function(is_resizing) { _this.loaded = false; if(! is_resizing) { _this.setHideSample(function() { _this.loaded = true; }); } }); if (_this.component.html) { _this.$root.applySyntaxHighlighting(_this.$el); } }, methods: { /** * Update component active in navigation. */ updateActive: function() { var _this = this; // If scroll position is great than or equal to component offset top - 60 pixels // and scroll position is less than component offset top plus component height plus 60 pixels // and active component is not this component if(_this.$root && _this.$root.scroll_position >= _this.$el.offsetTop - 60 && _this.$root.scroll_position < _this.$el.offsetTop + _this.$el.offsetHeight) { // If not currently auto scrolling to component // and component is not active if(!_this.$root.scrolling_to && !_this.isActive(_this.component)) { // Set this component to active _this.$root.active_components.push(_this.component); _this.$root.open_group = null; _this.$root.updateHash(_this.component.id); } } else { // If not currently auto scrolling to component if(_this.$root && !_this.$root.scrolling_to) { // Loop through active components and remove this component for (var i = 0; i < _this.$root.active_components.length; i++) { var component = _this.$root.active_components[i]; if (component.id === _this.component.id) { _this.$root.active_components.splice(i, 1); return; } } } } }, /** * Is component active in navigation. * * @param component * @returns {boolean} */ isActive: function(component) { var _this = this; for (var i = 0; i < _this.$root.active_components.length; i++) { var c = _this.$root.active_components[i]; if (component.id === c.id) { return true; } } return false; }, /** * Should invert text based on hex brightness. * * @param hex * @returns {boolean} */ shouldInvertText: function(hex) { var rgb = this.$root.convertHexToRgb(hex), brightness = this.$root.getColorBrightness(rgb); return brightness > 210; }, /** * Should apply border based on hex brightness. * * @param hex * @returns {boolean} */ shouldApplyBorder: function(hex) { var rgb = this.$root.convertHexToRgb(hex), brightness = this.$root.getColorBrightness(rgb); return brightness > 240; }, /** * Set component sample element to be hidden if the sample * itself is hidden in the assets CSS stylesheet. * * @param callback */ setHideSample: function(callback) { callback = typeof callback !== 'undefined' ? callback : function() {}; var _this = this; _this.hide_sample_code = false; setTimeout(function() { if(_this.$el.querySelector('.ndpl-component__code')) { /** * Auto-detect hidden sample. */ if (_this.$el.querySelector('.ndpl-component__sample').offsetHeight <= 74 && !_this.component.options.disabled_auto_sample_hiding) { _this.hide_sample_code = true; } /** * If manually specifying when to show nad hide samples. */ if (_this.component.options.disabled_auto_sample_hiding && _this.component.options.disabled_auto_sample_hiding.hasOwnProperty('show_on_mobile') && _this.component.options.disabled_auto_sample_hiding.hasOwnProperty('show_on_desktop')) { if(_this.$root.mobile_view) { _this.hide_sample_code = !_this.component.options.disabled_auto_sample_hiding.show_on_mobile; } else { _this.hide_sample_code = !_this.component.options.disabled_auto_sample_hiding.show_on_desktop; } } } callback(); }, 0); }, /** * Is sample code visible. * * @returns {boolean} */ isCodeVisible: function() { var _this = this; return ! _this.hide_sample_code; } } }); Vue.component('ndpl-component', ndplComponent); /** * Group component */ var ndplGroup = Vue.extend({ props: { group: { required: true } } }); Vue.component('ndpl-group', ndplGroup); /** * Script component */ var ndplScript = Vue.extend({ props: { script: { required: true } }, methods: { /** * Loads TypeKit. */ loadTypekit: function() { try { Typekit.load({ async: true }); } catch(e) {}; } } }); Vue.component('ndpl-script', ndplScript); /** * Vue instance */ new Vue({ el: 'html', data: { intro: null, project_logo: null, project_favicon: null, project_name: null, project_url: null, copyright_start_year: null, client_name: null, client_url: null, creators: {}, content: {}, groups: {}, theme: {}, assets: { css: [], js: [] }, font_libraries: { typekit_code: null, google_web_fonts: null, typography_web_fonts: null }, log: { error: [], info: [] }, components_count: 0, groups_count: 0, components_loaded_count: 0, groups_loaded_count: 0, groups_loaded: false, loaded: false, resizing: false, typekit_loaded: false, scroll_position: 0, prev_scroll_position: 0, active_group: null, active_components: [], active_page: null, open_group: null, show_first_page_on_load: false, scrolling_to: false, sidebar_scrolling: false, window_outer_width: 0, breakpoint: 960, mobile_view: false, open_nav: false, rtime: new Date(1, 1, 2000, 12,00,00), timeout: false, delta: 200, version: null }, computed: { project: function() { if(this.project_name && this.project_url) { return '' + this.project_name + ''; } if(this.project_name && !this.project_url) { return this.project_name; } return null; }, copyright_year: function() { var date = new Date(); if(date.getFullYear() == this.copyright_start_year) { return this.copyright_start_year; } return this.copyright_start_year + ' - ' + date.getFullYear(); }, client: function() { if(this.client_name && this.client_url) { return '' + this.client_name + ''; } if(this.client_name && !this.client_url) { return this.client_name; } return null; }, all_creators: function() { var formattedCreators = ''; if(this.creators.length && this.creators[0].name) { for (var i = 0; i < this.creators.length; i++) { prefix = i === this.creators.length - 1 ? ' & ' : ', '; url = this.creators[i].url; name = this.creators[i].name.replace(' ', ' '); formattedCreators += prefix + '' + name + ''; } return formattedCreators.substring(2); } return null; }, library_inline_styles: function() { var _this = this, styles = ''; if(_this.theme.max_width) { styles += 'max-width:' + _this.theme.max_width + 'px;'; } return styles; } }, watch: { groups_loaded: function() { var _this = this; _this.setupComponents(); }, loaded: function() { var _this = this; _this.scrollTo(window.location.hash); _this.$broadcast('loaded'); } }, ready: function() { var _this = this; _this.loadDataFile(); _this.window_outer_width = window.outerWidth; _this.mobile_view = _this.window_outer_width >= _this.breakpoint ? false : true; window.addEventListener('scroll', _this.setScrollPosition); window.addEventListener('resize', function() { _this.window_outer_width = window.outerWidth; _this.setScrollPosition(); _this.mobile_view = _this.window_outer_width >= _this.breakpoint ? false : true; _this.rtime = new Date(); if (_this.timeout === false && !_this.mobile_view) { _this.timeout = true; setTimeout(_this.trackResizing, _this.delta); } }); /** * Disable body scrolling when mouseover/mouseleave * sidebar to prevent library scroll jumping. */ var sidebar = document.querySelector('.ndpl-sidebar'); sidebar.addEventListener('mouseover', function(e) { _this.sidebar_scrolling = true; }) sidebar.addEventListener('mouseleave', function(e) { _this.sidebar_scrolling = false; }); /** * Set active page based on hash or show first * page on load variable. */ setTimeout(function() { var page = _this.isLoadingPage(); if(page) { _this.loadPage(page); } }, 0); }, methods: { /** * Apply syntax highlighting to pre code elements * within passed element. * * @param el */ applySyntaxHighlighting: function(el) { setTimeout(function() { var blocks = el.querySelectorAll('pre code'); for(var i = 0; i < blocks.length; i++) { var block = blocks[i]; hljs.highlightBlock(block); } }, 0); }, /** * Reads the data.json file. */ loadDataFile: function () { var _this = this; _this.$http.get('./data.json' + '?cb=' + new Date()).then(function (response) { _this.initData(response.data, function() { if(_this.$data.groups.length) { _this.setupGroups(); } else { _this.logInfo('You need to add a component to your library before it can be loaded.
You can either do this manually by editing your data.json file,
or you can use the command line helper: astrum new [group_name/component_name]'); } }); }); }, /** * Determine if a page should be loaded. */ isLoadingPage: function() { var _this = this, hash = location.hash; if(_this.content.pages !== undefined && _this.content.pages.length) { if(hash) { for (var i = 0; i < _this.content.pages.length; i++) { var page = _this.content.pages[i]; if (page.name == hash.replace('#', '')) return page; } } else if(_this.content.show_first_page_on_load) { return _this.content.pages[0]; } } return false; }, /** * Initilise data bindings. * * @param data */ initData: function(data, callback) { callback = typeof callback !== 'undefined' ? callback : function() {}; var _this = this; for(var key in data) { _this.$set(key, data[key]); } callback(); }, /** * Update URL hash. * * @param hash */ updateHash: function(hash) { history.pushState ? history.pushState(null, null, '#' + hash) : location.hash = hash; }, /** * Setup component groups. */ setupGroups: function() { var _this = this; // Loop through the groups for (var i = 0; i < _this.groups.length; i++) { var group = _this.groups[i]; // Set group navigation navigation _this.$set('groups[' + i + '].id', 'group-' + group.name); _this.$set('groups[' + i + '].active', false); // Set default variables _this.$set('groups[' + i + '].description', ''); // Count groups _this.groups_count = _this.groups.length; // Load group _this.loadGroup(_this.groups[i]); } }, setupComponents: function() { var _this = this; // Loop through the components for (var i = 0; i < _this.groups.length; i++) { var group = _this.groups[i]; // Count components _this.components_count += group.components.length; // Add group components to group for (var j = 0; j < group.components.length; j++) { // Set default variables _this.$set('groups[' + i + '].components[' + j + '].id', 'group-' + group.name + '-component-' + group.components[j].name); _this.$set('groups[' + i + '].components[' + j + '].group_id', 'group-' + group.name); _this.$set('groups[' + i + '].components[' + j + '].active', false); _this.$set('groups[' + i + '].components[' + j + '].options', group.components[j].options ? group.components[j].options : false); _this.$set('groups[' + i + '].components[' + j + '].options.sample_always_show', group.components[j].options.sample_always_show ? group.components[j].options.sample_always_show : false); _this.$set('groups[' + i + '].components[' + j + '].options.sample_mobile_hidden', group.components[j].options.sample_mobile_hidden ? group.components[j].options.sample_mobile_hidden : false); _this.$set('groups[' + i + '].components[' + j + '].options.sample_dark_background', group.components[j].options.sample_dark_background ? group.components[j].options.sample_dark_background : false); _this.$set('groups[' + i + '].components[' + j + '].options.disable_code_sample', group.components[j].options.disable_code_sample ? group.components[j].options.disable_code_sample : false); _this.$set('groups[' + i + '].components[' + j + '].code_show', false); _this.$set('groups[' + i + '].components[' + j + '].type', group.components[j].type ? group.components[j].type : 'standard'); _this.$set('groups[' + i + '].components[' + j + '].width', group.components[j].width ? group.components[j].width : 'full'); // Add html and description properties to the component object. _this.$set('groups[' + i + '].components[' + j + '].html', ''); _this.$set('groups[' + i + '].components[' + j + '].description', ''); _this.loadComponent(_this.groups[i].components[j]); } } }, /** * Load group files. * * @param group */ loadGroup: function(group) { var _this = this, group_path = './components/' + group.name; // Get and set component description _this.$http.get(group_path + '/description.md' + '?cb=' + new Date()).then(function (response) { group.description = marked(response.data); _this.areGroupsLoaded(); }, function () { _this.logError('Description file for ' + group.name + ' group failed to load from ' + group_path + '/description.md'); }); }, /** * Load component files. * * @param component */ loadComponent: function(component) { var _this = this, component_path = './components/' + component.group + '/' + component.name; // Get and set component markup _this.$http.get(component_path + '/markup.html' + '?cb=' + new Date()).then(function (response) { component.html = response.data; _this.areComponentsLoaded(); }, function () { _this.logError('HTML file for ' + component.name + ' component failed to load from ' + component_path + '/html.md'); }); // Get and set component description _this.$http.get(component_path + '/description.md' + '?cb=' + new Date()).then(function (response) { component.description = marked(response.data); _this.areComponentsLoaded(); }, function () { _this.logError('Description file for ' + component.name + ' component failed to load from ' + component_path + '/description.md'); }); }, /** * Increment groups loaded. */ areGroupsLoaded: function() { var _this = this; _this.groups_loaded_count += 1; if (_this.groups_loaded_count === _this.groups_count) { setTimeout(function() { _this.groups_loaded = true; }, 1000); } }, /** * Increment components loaded. */ areComponentsLoaded: function() { var _this = this; _this.components_loaded_count += 1; if (_this.components_loaded_count === _this.components_count * 2) { setTimeout(function() { _this.loaded = true; }, 2000); } }, /** * Add to log. * * @param message * @param data * @param type */ addLog: function(message, data, type) { var _this = this; type = typeof type !== 'undefined' ? type : 'error'; data = typeof data !== 'undefined' ? data : null; _this.log[type].push(message); console[type]('[Pattern Library warn]: ' + message); if(data) { console[type](data); } }, /** * Log error helper. * * @param message * @param data */ logError: function(message, data) { var _this = this; _this.addLog(message, data, 'error'); }, /** * Log info helper. * * @param message * @param data */ logInfo: function(message, data) { var _this = this; _this.addLog(message, data, 'info'); }, /** * Set scroll position. */ setScrollPosition: function() { var _this = this, doc = document.documentElement, top = doc && doc.scrollTop || document.body.scrollTop; _this.prev_scroll_position = _this.scroll_position; _this.scroll_position = top; }, /** * Get scroll direction. * * @returns {string} */ getScrollDirection: function() { var _this = this; return _this.prev_scroll_position < _this.scroll_position ? 'down' : 'up'; }, /** * Scroll to element. * * @param e */ scrollToHref: function(e) { var _this = this; _this.scrollTo(e.target.hash); _this.active_page = null; }, /** * Animate scroll to. * * @param hash */ scrollTo: function(hash) { var _this = this, offset = _this.mobile_view ? 79 : 30; if(!hash) return; _this.scrolling_to = true; smoothScroll.animateScroll(hash, null, { offset: offset, callback: function() { _this.scrolling_to = false; _this.open_nav = false; } }); }, /** * Toggle navigation. */ toggleNav: function() { var _this = this; _this.open_nav = ! _this.open_nav; }, /** * Toggle open groups. * * @param group */ toggleOpenGroups: function(group) { var _this = this; _this.open_group = _this.open_group == group.id ? null : group.id; _this.active_page = null; }, /** * Load content page. * @param page */ loadPage: function(page) { var _this = this; _this.active_page = page; _this.active_components = []; _this.open_group = null; _this.open_nav = false; _this.$http.get(page.file + '?cb=' + new Date()).then(function (response) { _this.$set('active_page.markup', marked(response.data)); _this.applySyntaxHighlighting(document); }); _this.updateHash(page.name); }, /** * Track resizing and broadcast resizing events. */ trackResizing: function() { var _this = this; _this.resizing = true; _this.$broadcast('resizing', true); if (new Date() - _this.rtime < _this.delta) { setTimeout(_this.trackResizing, _this.delta); } else { _this.timeout = false; setTimeout(function() { _this.resizing = false; _this.$broadcast('resizing', false); }, 1000); } }, /** * Convert hex color value to rgb color values. * * @param hex * @returns {{r: number, g: number, b: number}} */ convertHexToRgb: function(hex) { // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; hex = hex.replace(shorthandRegex, function(m, r, g, b) { return r + r + g + g + b + b; }); var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null; }, /** * Get color brightness value from rgb color values. * * @param rgb * @returns {number} */ getColorBrightness: function(rgb) { return Math.round(((parseInt(rgb.r) * 299) + (parseInt(rgb.g) * 587) + (parseInt(rgb.b) * 114)) /1000); } } }); ================================================ FILE: pattern-library/assets/js/patterns.js ================================================ (function() { var componentSamples = [].slice.call(document.querySelectorAll('.ndpl-component__sample')); if(componentSamples.length) { componentSamples.map(function(item) { item.classList.add('boilerform'); }); } }()); ================================================ FILE: pattern-library/components/button/default/description.md ================================================ ================================================ FILE: pattern-library/components/button/default/markup.html ================================================ ================================================ FILE: pattern-library/components/button/description.md ================================================ ================================================ FILE: pattern-library/components/check-field/checkbox/description.md ================================================ ================================================ FILE: pattern-library/components/check-field/checkbox/markup.html ================================================
================================================ FILE: pattern-library/components/check-field/description.md ================================================ ================================================ FILE: pattern-library/components/check-field/error-state/description.md ================================================ ================================================ FILE: pattern-library/components/check-field/error-state/markup.html ================================================
================================================ FILE: pattern-library/components/check-field/radio/description.md ================================================ ================================================ FILE: pattern-library/components/check-field/radio/markup.html ================================================
================================================ FILE: pattern-library/components/input-field/description.md ================================================ Generic input fields with variations for size, placeholders and validation states. Relevant attributes are added to help users input data as efficiently as possible. ================================================ FILE: pattern-library/components/input-field/email/description.md ================================================ ================================================ FILE: pattern-library/components/input-field/email/markup.html ================================================ ================================================ FILE: pattern-library/components/input-field/error-state/description.md ================================================ ================================================ FILE: pattern-library/components/input-field/error-state/markup.html ================================================ ================================================ FILE: pattern-library/components/input-field/number/description.md ================================================ ================================================ FILE: pattern-library/components/input-field/number/markup.html ================================================ ================================================ FILE: pattern-library/components/input-field/search/description.md ================================================ ================================================ FILE: pattern-library/components/input-field/search/markup.html ================================================ ================================================ FILE: pattern-library/components/input-field/tel/description.md ================================================ ================================================ FILE: pattern-library/components/input-field/tel/markup.html ================================================ ================================================ FILE: pattern-library/components/input-field/text/description.md ================================================ ================================================ FILE: pattern-library/components/input-field/text/markup.html ================================================ ================================================ FILE: pattern-library/components/input-field/text-area/description.md ================================================ ================================================ FILE: pattern-library/components/input-field/text-area/markup.html ================================================ ================================================ FILE: pattern-library/components/label/default/description.md ================================================ ================================================ FILE: pattern-library/components/label/default/markup.html ================================================ ================================================ FILE: pattern-library/components/label/description.md ================================================ ================================================ FILE: pattern-library/components/select-field/description.md ================================================ ================================================ FILE: pattern-library/components/select-field/error-state/description.md ================================================ ================================================ FILE: pattern-library/components/select-field/error-state/markup.html ================================================
================================================ FILE: pattern-library/components/select-field/select-menu/description.md ================================================ ================================================ FILE: pattern-library/components/select-field/select-menu/markup.html ================================================
================================================ FILE: pattern-library/data.json ================================================ { "project_logo": "/assets/images/logo/logo.svg", "project_favicon": "favicon.png", "project_name": "Boilerform", "project_url": null, "copyright_start_year": null, "client_name": null, "client_url": null, "creators": [ { "name": "Boilerform site", "url": "//boilerform.hankchizljaw.com" }, { "name": "Boilerform repo", "url": "//github.com/hankchizljaw/boilerform" }, { "name": "By hankchizljaw", "url": "//hankchizljaw.com" } ], "theme": { "border_color": "#E0E6ED", "highlight_color": "#F9FAFC", "brand_color": "#A03EA0", "background_color": "#FFFFFF", "code_highlight_theme": "github", "override_code_highlight_bg": "#F9FAFC", "sample_dark_background": "#333333", "show_project_name": false, "show_version": true, "max_width": null, "titles": { "library_title": "Patterns", "pages_title": "Overview", "components_title": "Components" } }, "assets": { "css": [ "https://cdn.statically.io/gh/hankchizljaw/boilerform/70a13a07/dist/css/boilerform.min.css" ], "js": [ "/assets/js/patterns.js?v=1.1.1" ] }, "font_libraries": { "typekit_code": null, "typography_web_fonts": null, "google_web_fonts": null }, "content": null, "groups": [ { "name": "input-field", "title": "Input Field", "components": [ { "group": "input-field", "name": "text", "title": "Text", "width": "half" }, { "group": "input-field", "name": "email", "title": "Email", "width": "half" }, { "group": "input-field", "name": "search", "title": "Search", "width": "half" }, { "group": "input-field", "name": "number", "title": "Number", "width": "half" }, { "group": "input-field", "name": "tel", "title": "Tel", "width": "half" }, { "group": "input-field", "name": "text-area", "title": "Textarea / Multiline", "width": "half" }, { "group": "input-field", "name": "error-state", "title": "Error State", "width": "half" } ] }, { "name": "select-field", "title": "Select Field", "components": [ { "group": "select-field", "name": "select-menu", "title": "Select Menu", "width": "half" }, { "group": "select-field", "name": "error-state", "title": "Error State", "width": "half" } ] }, { "name": "check-field", "title": "Check Field", "components": [ { "group": "check-field", "name": "checkbox", "title": "Checkbox", "width": "half" }, { "group": "check-field", "name": "radio", "title": "Radio", "width": "half" }, { "group": "check-field", "name": "error-state", "title": "Error State", "width": "half" } ] }, { "name": "button", "title": "Button", "components": [ { "group": "button", "name": "default", "title": "Default", "width": "half" } ] }, { "name": "label", "title": "Label", "components": [ { "group": "label", "name": "default", "title": "Default", "width": "half" } ] } ], "version": "1.9.5" } ================================================ FILE: pattern-library/index.html ================================================

Building pattern library...

Hold up! We have some errors...

Looks like you have some setup to do...

{{{ project }}}

{{{ project }}}

{{{ active_page.markup }}}

{{ group.title }}

{{ component.title }}

================================================ FILE: readme.md ================================================ # Boilerform The Boilerform logo Boilerform is a little HTML and CSS boilerplate to take the pain away from working with forms. By providing baseline BEM structured CSS and appropriate attributes on elements: Boilerform gives you a head start building forms in the best possible way with a view to being dropped into most projects. The idea was first thought-up by [@chriscoyier](https://twitter.com/chriscoyier) on [CSS Tricks](https://css-tricks.com/boilerform). 🌍 ## Getting started Boilerform is designed to be straight-forward to implement. In its most basic form, you can drop a CSS file into your head with the following snippet: ```html ``` Then all you need to do is wrap your elements in a `.boilerform` wrapper. It could be something like this: ```html
``` You can also take compiled CSS and HTML from the [dist directory](https://github.com/hankchizljaw/boilerform/tree/master/dist/) of this repository, if that's what you prefer. If you want a bit more control, you can work with the [Sass](https://github.com/hankchizljaw/boilerform/tree/master/assets/scss) and [Pattern Library](https://github.com/hankchizljaw/boilerform/tree/master/pattern-library). This is where the source of Boilerform lives. To compile assets, you can run the following commands in your terminal: - `npm run watch` will compile your assets and watch for further changes - `npm run build` will compile your assets into a production ready state in the `dist` directory The pattern library is powered by [Astrum](http://astrum.nodividestudio.com/). You can find [detailed documentation here](https://github.com/NoDivide/Astrum). ## Validation interface There's a basic validation interface available with Boilerform which extends the native HTML validation facility with a few visual tweaks. ### Getting started First of all, you need the JavaScript in your project. You can either take the [source code](https://github.com/hankchizljaw/boilerform/blob/master/assets/js/modules/validation.js) and add to your project, or add the dist version to bottom of your page. ```html ``` Now that you've got the script, it'll work, as long as your elements have the `required` attribute, which will allow them to fire an `invalid` event. You'll also need to make sure your `
` elements either live in a `.boilerform` parent element or have the `.boilerform` class. --- Made with ❤️ by [HankChizlJaw](https://twitter.com/hankchizljaw) and [friends](https://github.com/hankchizljaw/boilerform/graphs/contributors). ================================================ FILE: webpack.config.js ================================================ // Pull in .env settings require('dotenv').config(); // Create CSS and JS output paths var CSS_OUTPUT_PATH = process.env.CSS_OUTPUT_PATH ? process.env.CSS_OUTPUT_PATH : '../css/boilerform.css'; var JS_OUTPUT_PATH = process.env.JS_OUTPUT_PATH ? process.env.JS_OUTPUT_PATH : '/dist/js'; // Define webpack stuff var ExtractTextPlugin = require('extract-text-webpack-plugin'); var isProduction = process.env.NODE_ENV === 'production'; var path = require('path'); var plugins = []; var settings = { libraryName: 'boilerform', inputs: { js: { entryPath: '/assets/js/boilerform.js' } }, outputs: { js: { fileName: 'boilerform.js', minFileName: 'boilerform.min.js', path: JS_OUTPUT_PATH }, css: { path: CSS_OUTPUT_PATH } } }; var webpack = require('webpack'); if(isProduction) { plugins.push(new webpack.optimize.UglifyJsPlugin({ minimize: true })); } // Create an extract text plugin instance for Sass var extractPlugin = new ExtractTextPlugin(settings.outputs.css.path); plugins.push(extractPlugin); module.exports = { entry: path.join(__dirname, settings.inputs.js.entryPath), devtool: 'source-map', output: { path: path.join(__dirname, settings.outputs.js.path), filename: (isProduction ? settings.outputs.js.minFileName : settings.outputs.js.fileName), library: settings.libraryName, libraryTarget: 'umd', umdNamedDefine: true }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: [ { loader: 'babel-loader' } ] }, { test: /\.scss$/, use: extractPlugin.extract({ use: ['css-loader', 'sass-loader'] }) } ] }, resolve: { extensions: ['.js'] }, plugins: plugins };