├── .editorconfig ├── .eslintignore ├── .eslintrc.json ├── .gitignore ├── .ncurc.js ├── .npmignore ├── .npmrc ├── .stylelintrc ├── .travis.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── babel.config.js ├── babel.ext.json ├── declination.json ├── docs ├── branches.md ├── commands.md ├── componentSpecific │ ├── a.md │ ├── alert.md │ ├── badge.md │ ├── list-group.md │ ├── media.md │ └── navbar-align.md ├── conditionals │ ├── box-shadow.md │ ├── conditional.md │ ├── hover.md │ └── transition.md ├── configuration.md ├── contribute.md ├── css-mixins.md ├── cssHelpers │ ├── background-variant.md │ ├── border-radius.md │ ├── breakpoints.md │ ├── clearfix.md │ ├── float.md │ ├── gradients.md │ ├── gridbreakpoints.md │ ├── lists.md │ ├── nav-divider.md │ ├── screen-reader.md │ ├── size.md │ ├── text-emphasis.md │ ├── text-hide.md │ ├── text-truncate.md │ └── visibility.md ├── faq.md ├── getting-started.md ├── installation.md ├── introduction.md ├── prerequisite.md └── release.md ├── internals └── testing │ └── test-bundler.js ├── package.json ├── rollup.config.js ├── sonar-project.properties ├── src ├── MixinError.js ├── a.js ├── alert.js ├── background-variant.js ├── badge.js ├── border-radius.js ├── box-shadow.js ├── breakpoints.js ├── buttonGroup.js ├── buttons.js ├── cards.js ├── clearfix.js ├── conditional.js ├── customForms.js ├── float.js ├── forms.js ├── gradients.js ├── grid-framework.js ├── grid.js ├── hover.js ├── image.js ├── index.js ├── list-group.js ├── lists.js ├── media.js ├── nav-divider.js ├── nav.js ├── navbar-align.js ├── navbar-toggleable.js ├── navbar.js ├── paginations.js ├── progress.js ├── regex.js ├── reset-filter.js ├── reset-text.js ├── resize.js ├── screen-reader.js ├── size.js ├── tab-focus.js ├── table-row.js ├── tests │ ├── MixinError.test.js │ ├── a.test.js │ ├── alert.test.js │ ├── background-variant.test.js │ ├── badge.test.js │ ├── border-radius.test.js │ ├── box-shadow.test.js │ ├── breakpoints.test.js │ ├── buttonGroup.test.js │ ├── buttons.test.js │ ├── cards.test.js │ ├── clearfix.test.js │ ├── conditional.test.js │ ├── customForm.test.js │ ├── float.test.js │ ├── forms.test.js │ ├── gradients.test.js │ ├── grid-framework.test.js │ ├── grid.test.js │ ├── hover.test.js │ ├── image.test.js │ ├── index.test.js │ ├── list-group.test.js │ ├── lists.test.js │ ├── media.test.js │ ├── nav-divider.test.js │ ├── nav.test.js │ ├── navbar-align.test.js │ ├── navbar-toggleable.test.js │ ├── navbar.test.js │ ├── paginations.test.js │ ├── progress.test.js │ ├── regex.test.js │ ├── reset-filter.test.js │ ├── reset-text.test.js │ ├── resize.test.js │ ├── screen-reader.test.js │ ├── size.test.js │ ├── tab-focus.test.js │ ├── table-row.test.js │ ├── text-emphasis.test.js │ ├── text-hide.test.js │ ├── text-truncate.test.js │ ├── transition.test.js │ ├── typography.test.js │ ├── utilities.test.js │ └── visibility.test.js ├── text-emphasis.js ├── text-hide.js ├── text-truncate.js ├── transition.js ├── typography.js ├── utilities.js └── visibility.js ├── styleguide.config.js └── styleguide ├── jsdoc.sh ├── prepare.sh ├── setup.js └── styleguide.ext.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_size = 2 6 | end_of_line = lf 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | lib/ 2 | dist/ 3 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": ["airbnb"], 4 | "globals": { 5 | "__SERVER__": true, 6 | "__VERSION__": true 7 | }, 8 | "env": { 9 | "browser": true, 10 | "node": true, 11 | "jest": true, 12 | "es6": true 13 | }, 14 | "parserOptions": { 15 | "ecmaVersion": 7, 16 | "sourceType": "module", 17 | "ecmaFeatures": { 18 | "impliedStrict": true, 19 | "jsx": true 20 | } 21 | }, 22 | "settings": { 23 | "import/resolver": { 24 | "node": { 25 | "extensions": [ 26 | ".js", 27 | ".mjs" 28 | ] 29 | } 30 | } 31 | }, 32 | "rules": { 33 | "curly": [2, "multi-line"], 34 | "no-continue": 0, 35 | "no-duplicate-imports": 0, 36 | "no-else-return": 0, 37 | "no-prototype-builtins": 0, 38 | "no-underscore-dangle": 0, 39 | "no-unused-vars": [2], 40 | "react/destructuring-assignment": 0, 41 | "react/no-multi-comp": 0, 42 | "react/prefer-stateless-function": 0, 43 | "react/sort-comp": 0, 44 | "symbol-description": 0, 45 | "no-restricted-syntax": ["error", "ForOfStatement", "LabeledStatement", "WithStatement"], 46 | "no-return-assign": 0, 47 | "no-undef": 0, 48 | "no-plusplus": "off", 49 | "arrow-parens": [ 50 | "error", 51 | "always" 52 | ], 53 | "arrow-body-style": [ 54 | 2, 55 | "as-needed" 56 | ], 57 | "comma-dangle": [ 58 | 2, 59 | "always-multiline" 60 | ], 61 | "import/extensions": [ 62 | "error", 63 | "always", 64 | { 65 | "js": "never", 66 | "mjs": "never" 67 | } 68 | ], 69 | "import/imports-first": 0, 70 | "import/newline-after-import": 0, 71 | "import/no-dynamic-require": 0, 72 | "import/no-extraneous-dependencies": 0, 73 | "import/no-named-as-default": 0, 74 | "import/no-unresolved": 2, 75 | "import/prefer-default-export": 0, 76 | "indent": [ 77 | 2, 78 | 2, 79 | { 80 | "SwitchCase": 1 81 | } 82 | ], 83 | "max-len": 0, 84 | "newline-per-chained-call": 0, 85 | "no-confusing-arrow": 0, 86 | "no-console": 1, 87 | "no-use-before-define": 0, 88 | "object-curly-newline": "warn", 89 | "prefer-template": 2, 90 | "class-methods-use-this": 0, 91 | "require-yield": 0, 92 | "jsx-a11y/aria-props": 2, 93 | "jsx-a11y/heading-has-content": 0, 94 | "jsx-a11y/label-has-for": 2, 95 | "jsx-a11y/mouse-events-have-key-events": 2, 96 | "jsx-a11y/role-has-required-aria-props": 2, 97 | "jsx-a11y/role-supports-aria-props": 2, 98 | "react/forbid-prop-types": 0, 99 | "react/jsx-first-prop-new-line": [ 100 | 2, 101 | "multiline" 102 | ], 103 | "react/jsx-filename-extension": 0, 104 | "react/jsx-no-target-blank": 0, 105 | "react/require-extension": 0, 106 | "react/self-closing-comp": 0, 107 | "react/require-default-props": 0 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | tmp.json 4 | .DS_Store 5 | bundle-stats.html 6 | .idea/ 7 | coverage/ 8 | /reports 9 | /test-report.xml 10 | jest_0 11 | lib 12 | dist 13 | /public 14 | /docs/cli 15 | /docs/declinations 16 | .git-credentials 17 | package-lock.json 18 | -------------------------------------------------------------------------------- /.ncurc.js: -------------------------------------------------------------------------------- 1 | const { createConfig } = require('@rollup-umd/ncu'); 2 | module.exports = createConfig(); 3 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | sonar-project.properties 3 | .gitlab-ci.yml 4 | internals 5 | .babelrc 6 | babel.ext.json 7 | babel.config.json 8 | .editorconfig 9 | .eslintignore 10 | bundle-stats.html 11 | CODE_OF_CONDUCT.md 12 | CONTRIBUTING.md 13 | CHANGELOG.md 14 | README.md 15 | declination.json 16 | rollup.config.js 17 | /styleguide.config.js 18 | test-report.xml 19 | .idea/ 20 | coverage/ 21 | docs/ 22 | reports/ 23 | /styleguide 24 | .ncurc.js 25 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "processors": [ 3 | "stylelint-processor-styled-components" 4 | ], 5 | "extends": [ 6 | "stylelint-config-recommended", 7 | "stylelint-config-styled-components" 8 | ], 9 | "rules": { 10 | "color-no-invalid-hex": true, 11 | "color-hex-case": "upper", 12 | "unit-no-unknown": true, 13 | "property-no-unknown": true, 14 | "at-rule-semicolon-newline-after": "always", 15 | "declaration-block-no-duplicate-properties":true, 16 | "block-no-empty": null 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: required 3 | dist: trusty 4 | 5 | # Blocklist 6 | branches: 7 | except: 8 | - gh-pages 9 | 10 | cache: 11 | directories: 12 | - node_modules 13 | 14 | before_install: 15 | - npm install -g npm 16 | # const 17 | - export PACKAGE_NAME=$(node -p "require('./package.json').name") 18 | - export PACKAGE_VERSION=$(node -p "require('./package.json').version") 19 | - export SONAR_VERSION=${PACKAGE_VERSION}-b${TRAVIS_BUILD_ID}-${TRAVIS_BRANCH} 20 | - export NODE_VERSION=$(node --version) 21 | - export NPM_VERSION=$(npm --version) 22 | 23 | # logging 24 | - npm --version || echo npm not installed 25 | - node --version || echo node not installed 26 | - echo "package version $PACKAGE_VERSION" 27 | 28 | stages: 29 | - build 30 | - test 31 | - release 32 | - deploy 33 | 34 | jobs: 35 | include: 36 | 37 | # Job: Build 38 | - stage: build 39 | node_js: 40 | - 'lts/*' 41 | - '10' 42 | - '8' 43 | script: 44 | - npm run build 45 | # Job: Test 46 | - stage: test 47 | node_js: 48 | - 'lts/*' 49 | - '10' 50 | - '8' 51 | addons: 52 | sonarcloud: 53 | organization: $(echo $TRAVIS_REPO_SLUG | awk -F '/' '{print $1}') 54 | script: 55 | - npm run test 56 | - if [[ "$TRAVIS_BRANCH" != greenkeeper* ]]; then sonar-scanner -Dsonar.projectVersion=${SONAR_VERSION}; fi 57 | 58 | # Job: Release 59 | - stage: release 60 | if: branch = master AND type = push AND fork = false 61 | node_js: 62 | - 'lts/*' 63 | skip_cleanup: true 64 | script: 65 | - npx semantic-release 66 | 67 | # Job: Page 68 | - stage: deploy 69 | if: branch = master AND type = push AND fork = false 70 | node_js: 71 | - 'lts/*' 72 | script: 73 | - git fetch --tags 74 | - git checkout refs/tags/$(git describe --tags `git rev-list --tags --max-count=1`) 75 | - npm install 76 | - chmod +x styleguide/prepare.sh 77 | - styleguide/prepare.sh 78 | - npm run styleguide:build 79 | deploy: 80 | - provider: pages 81 | skip_cleanup: true 82 | github_token: $GH_TOKEN # Set in the settings page of your repository, as a secure variable 83 | keep_history: true 84 | local_dir: public/ 85 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at contact@yeutech.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | Please note we have a [code of conduct](./CODE_OF_CONDUCT.md), please follow it in all your interactions with the project. 7 | 8 | ## Pull Request Process 9 | 10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a 11 | build. 12 | 2. Format your commit messages with [commitizen](#creating-releases). 13 | 3. You may merge the Pull Request in once you have the sign-off of two other developers, or if you 14 | do not have permission to do that, you may request the second reviewer to merge it for you. 15 | 16 | ## Creating releases 17 | 18 | [commitizen](https://github.com/commitizen/cz-cli) uses [semantic-release](https://github.com/semantic-release/semantic-release) 19 | to release new versions automatically. 20 | 21 | * Commits of type `fix` will trigger bugfix releases, think `0.0.1` 22 | * Commits of type `feat` will trigger feature releases, think `0.1.0` 23 | * Commits with `BREAKING CHANGE` in body or footer will trigger breaking releases, think `1.0.0` 24 | 25 | All other commit types will trigger no new release. 26 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2017-2018 Yeutech Company Limited. https://bootstrap-styled.yeutech.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # css-mixins 2 | 3 | [![Build Status](https://travis-ci.org/bootstrap-styled/css-mixins.svg?branch=master)](https://travis-ci.org/bootstrap-styled/css-mixins) [![npm Version](https://img.shields.io/npm/v/@bootstrap-styled/css-mixins.svg?style=flat)](https://www.npmjs.com/package/@bootstrap-styled/css-mixins) [![License](https://img.shields.io/npm/l/@bootstrap-styled/css-mixins.svg?style=flat)](https://www.npmjs.com/package/@bootstrap-styled/css-mixins) [![NPM monthly downloads](https://img.shields.io/npm/dm/@bootstrap-styled/css-mixins.svg?style=flat)](https://npmjs.org/package/@bootstrap-styled/css-mixins) [![NPM total downloads](https://img.shields.io/npm/dt/@bootstrap-styled/css-mixins.svg?style=flat)](https://npmjs.org/package/@bootstrap-styled/css-mixins) [![npm Version](https://img.shields.io/node/v/@bootstrap-styled/css-mixins.svg?style=flat)](https://www.npmjs.com/package/@bootstrap-styled/css-mixins) [![Module formats](https://img.shields.io/badge/module%20formats-umd%2C%20cjs%2C%20esm-green.svg?style=flat)](https://www.npmjs.com/package/@bootstrap-styled/css-mixins) 4 | [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=com.github.bootstrap-styled.css-mixins&metric=coverage)](https://sonarcloud.io/dashboard?id=com.github.bootstrap-styled.css-mixins) [![Quality gate status](https://sonarcloud.io/api/project_badges/measure?project=com.github.bootstrap-styled.css-mixins&metric=alert_status)](https://sonarcloud.io/dashboard?id=com.github.bootstrap-styled.css-mixins) 5 | [![gitter](https://badges.gitter.im/bootstrap-styled/bootstrap-styled.svg)](https://gitter.im/bootstrap-styled) 6 | [![Greenkeeper badge](https://badges.greenkeeper.io/bootstrap-styled/css-mixins.svg)](https://greenkeeper.io/) 7 | 8 | Bootstrap mixins and utilities in javascript for bootstrap-styled. 9 | 10 | ## Table of Contents 11 | 12 | - [Documentation](#documentation) 13 | - [Contributing](#contributing) 14 | - [License MIT](#license-mit) 15 | 16 | --- 17 | 18 | ## Documentation 19 | 20 | Read [css-mixins documentation](https://bootstrap-styled.github.io/css-mixins). 21 | 22 | 23 | ## Contributing 24 | 25 | If you want to contribute to css-mixins please see our [contributing and community guidelines](https://github.com/bootstrap-styled/css-mixins/blob/master/CONTRIBUTING.md), they\'ll help you get set up locally and explain the whole process. 26 | 27 | Please also note that all repositories under the bootstrap-styled organization follow our [Code of Conduct](https://github.com/bootstrap-styled/css-mixins/blob/master/CODE_OF_CONDUCT.md), make sure to review and follow it. 28 | 29 | ## License MIT 30 | 31 | The MIT License 32 | 33 | Copyright (c) 2017-2018 Yeutech Company Limited. https://bootstrap-styled.github.io 34 | 35 | Permission is hereby granted, free of charge, to any person obtaining a copy 36 | of this software and associated documentation files (the "Software"), to deal 37 | in the Software without restriction, including without limitation the rights 38 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 39 | copies of the Software, and to permit persons to whom the Software is 40 | furnished to do so, subject to the following conditions: 41 | 42 | The above copyright notice and this permission notice shall be included in 43 | all copies or substantial portions of the Software. 44 | 45 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 46 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 47 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 48 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 49 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 50 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 51 | THE SOFTWARE. 52 | 53 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | only: [ 3 | 'src', 4 | 'styleguide', 5 | ], 6 | presets: [ 7 | [ 8 | '@babel/preset-env', 9 | { 10 | modules: false, 11 | }, 12 | ], 13 | ], 14 | plugins: [ 15 | '@babel/plugin-syntax-dynamic-import', 16 | '@babel/plugin-syntax-import-meta', 17 | '@babel/plugin-proposal-class-properties', 18 | '@babel/plugin-proposal-json-strings', 19 | [ 20 | '@babel/plugin-proposal-decorators', 21 | { 22 | legacy: true, 23 | }, 24 | ], 25 | ], 26 | env: { 27 | production: { 28 | plugins: [ 29 | 'add-module-exports', 30 | '@babel/plugin-transform-modules-commonjs', 31 | ], 32 | }, 33 | test: { 34 | plugins: [ 35 | '@babel/plugin-transform-modules-commonjs', 36 | 'dynamic-import-node', 37 | ], 38 | }, 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /babel.ext.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [], 3 | "plugins": [ 4 | "babel-plugin-array-includes" 5 | ] 6 | } -------------------------------------------------------------------------------- /declination.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /docs/branches.md: -------------------------------------------------------------------------------- 1 | 1. `master` is used to release the version. 2 | 1. `master` only accept merge requests from `dev` 3 | 1. `dev` is the development branch. It should be used by developers for applying their merge requests. 4 | 1. If you need to implement a new feature or edit an existing one, you need to submit to `dev` a merge request from your own branch with your modification. 5 | 6 | This is how you can create your own branch: 7 | 8 | ```bash 9 | $ git checkout dev 10 | $ git checkout -b $(whoami)-dev 11 | ``` 12 | 13 | You can now start working on your branch. 14 | 15 | When you are done, you can push to it: 16 | 17 | ```bash 18 | $ git push -u origin $(whoami)-dev 19 | ``` 20 | 21 | > `-u` will fix your default upstream, so next time you can just type `git push` to push to your branch. 22 | 23 | If you want to get the latest change in `dev` branch when you do `git pull`, run once: 24 | 25 | ```bash 26 | $ git pull -u origin dev 27 | ``` 28 | 29 | > `-u` will fix your default downstream, so next time you can just type `git pull` to pull from `dev` branch. 30 | 31 | When applying merge to `dev`, don't forget to check `Delete branch on merge` checkbox if you don't need it anymore. 32 | -------------------------------------------------------------------------------- /docs/commands.md: -------------------------------------------------------------------------------- 1 | Build project: 2 | 3 | ```bash 4 | $ npm run build 5 | ``` 6 | 7 | Run unit test: 8 | 9 | ```bash 10 | $ npm test 11 | ``` 12 | 13 | Watch unit test: 14 | 15 | ```bash 16 | $ npm run test:watch 17 | ``` 18 | 19 | Build the `/lib` directory: 20 | 21 | ```bash 22 | $ npm run build:lib 23 | ``` 24 | 25 | Build the `/dist` directory: 26 | 27 | ```bash 28 | $ npm run build:dist 29 | ``` 30 | 31 | Build the `/dist` directory "uncompressed": 32 | 33 | ```bash 34 | $ npm run build:dist:dev 35 | ``` 36 | 37 | Watch the `/dist` directory: 38 | 39 | ```bash 40 | $ npm run build:dist:watch 41 | ``` 42 | 43 | Watch the `/lib` directory: 44 | 45 | ```bash 46 | $ npm run build:lib:watch 47 | ``` 48 | 49 | Start a documentation server and watch the `/docs` directory: 50 | 51 | ```bash 52 | $ npm run styleguide 53 | ``` 54 | 55 | Build documentation in `/public` directory: 56 | 57 | ```bash 58 | $ npm run styleguide:build 59 | ``` 60 | -------------------------------------------------------------------------------- /docs/componentSpecific/a.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## a 4 | 5 | Basic css for Anchor component. 6 | 7 | ### Parameters 8 | 9 | - `$linkColor` **[string][1]** (optional, default `defaultProps['$link-color']`) 10 | - `$linkDecoration` **[string][1]** (optional, default `defaultProps['$link-decoration']`) 11 | - `$linkHoverColor` **[string][1]** (optional, default `defaultProps['$link-hover-color']`) 12 | - `$linkHoverDecoration` **[string][1]** (optional, default `defaultProps['$link-hover-decoration']`) 13 | - `$enableHoverMediaQuery` **[boolean][2]** (optional, default `defaultProps['$enable-hover-media-query']`) 14 | 15 | Returns **[string][1]** 16 | 17 | ## hover 18 | 19 | ### Parameters 20 | 21 | - `content` **[string][1]** 22 | 23 | Returns **[string][1]** 24 | 25 | ## hoverFocus 26 | 27 | ### Parameters 28 | 29 | - `enableHoverMediaQuery` **[boolean][2]** (optional, default `defaultProps['$enable-hover-media-query']`) 30 | - `content` **[string][1]** 31 | 32 | Returns **[string][1]** 33 | 34 | ## plainHoverFocus 35 | 36 | ### Parameters 37 | 38 | - `enableHoverMediaQuery` **[boolean][2]** (optional, default `defaultProps['$enable-hover-media-query']`) 39 | - `content` **[string][1]** 40 | 41 | Returns **[string][1]** 42 | 43 | ## hoverFocusActive 44 | 45 | ### Parameters 46 | 47 | - `enableHoverMediaQuery` **[boolean][2]** (optional, default `defaultProps['$enable-hover-media-query']`) 48 | - `content` **[string][1]** 49 | 50 | Returns **[string][1]** 51 | 52 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 53 | 54 | [2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean 55 | -------------------------------------------------------------------------------- /docs/componentSpecific/alert.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## alertVariant 4 | 5 | Basic css helper for different colored Alert components. 6 | 7 | ### Parameters 8 | 9 | - `background` **[string][1]** 10 | - `border` **[string][1]** 11 | - `bodyColor` **[string][1]** 12 | 13 | Returns **[string][1]** 14 | 15 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 16 | -------------------------------------------------------------------------------- /docs/componentSpecific/badge.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## badgeVariant 4 | 5 | Basic css helper for Badge components background. 6 | 7 | ### Parameters 8 | 9 | - `enableHoverMediaQuery` 10 | - `badgeColor` 11 | 12 | Returns **[string][1]** 13 | 14 | ## hover 15 | 16 | ### Parameters 17 | 18 | - `content` **[string][1]** 19 | 20 | Returns **[string][1]** 21 | 22 | ## hoverFocus 23 | 24 | ### Parameters 25 | 26 | - `enableHoverMediaQuery` **[boolean][2]** (optional, default `defaultProps['$enable-hover-media-query']`) 27 | - `content` **[string][1]** 28 | 29 | Returns **[string][1]** 30 | 31 | ## plainHoverFocus 32 | 33 | ### Parameters 34 | 35 | - `enableHoverMediaQuery` **[boolean][2]** (optional, default `defaultProps['$enable-hover-media-query']`) 36 | - `content` **[string][1]** 37 | 38 | Returns **[string][1]** 39 | 40 | ## hoverFocusActive 41 | 42 | ### Parameters 43 | 44 | - `enableHoverMediaQuery` **[boolean][2]** (optional, default `defaultProps['$enable-hover-media-query']`) 45 | - `content` **[string][1]** 46 | 47 | Returns **[string][1]** 48 | 49 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 50 | 51 | [2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean 52 | -------------------------------------------------------------------------------- /docs/componentSpecific/list-group.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## listGroupItemVariant 4 | 5 | Basic css helper for different colored ListGroupItem components. 6 | 7 | ### Parameters 8 | 9 | - `enableHoverMediaQuery` **[boolean][1]** (optional, default `defaultProps['$enable-hover-media-query']`) 10 | - `state` **[string][2]** 11 | - `background` **[string][2]** 12 | - `listColor` **[string][2]** 13 | 14 | Returns **[string][2]** 15 | 16 | ## hover 17 | 18 | ### Parameters 19 | 20 | - `content` **[string][2]** 21 | 22 | Returns **[string][2]** 23 | 24 | ## hoverFocus 25 | 26 | ### Parameters 27 | 28 | - `enableHoverMediaQuery` **[boolean][1]** (optional, default `defaultProps['$enable-hover-media-query']`) 29 | - `content` **[string][2]** 30 | 31 | Returns **[string][2]** 32 | 33 | ## plainHoverFocus 34 | 35 | ### Parameters 36 | 37 | - `enableHoverMediaQuery` **[boolean][1]** (optional, default `defaultProps['$enable-hover-media-query']`) 38 | - `content` **[string][2]** 39 | 40 | Returns **[string][2]** 41 | 42 | ## hoverFocusActive 43 | 44 | ### Parameters 45 | 46 | - `enableHoverMediaQuery` **[boolean][1]** (optional, default `defaultProps['$enable-hover-media-query']`) 47 | - `content` **[string][2]** 48 | 49 | Returns **[string][2]** 50 | 51 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean 52 | 53 | [2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 54 | -------------------------------------------------------------------------------- /docs/componentSpecific/media.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## media 4 | 5 | Basic css helper for Media components. 6 | 7 | Returns **[string][1]** 8 | 9 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 10 | -------------------------------------------------------------------------------- /docs/componentSpecific/navbar-align.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## navbarVerticalAlign 4 | 5 | Vertically center elements in the navbar depending on the value of its height. 6 | 7 | ### Parameters 8 | 9 | - `navbarHeight` **[string][1]** (optional, default `defaultProps['$navbar-height']`) 10 | - `elementHeight` **[string][1]** 11 | 12 | Returns **[string][1]** 13 | 14 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 15 | -------------------------------------------------------------------------------- /docs/conditionals/box-shadow.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## boxShadow 4 | 5 | Applies box-shadow if enableShadows is true. 6 | 7 | ### Parameters 8 | 9 | - `enableShadows` **[boolean][1]** (optional, default `defaultProps['$enable-shadows']`) 10 | - `args` **...any** 11 | 12 | Returns **[string][2]** 13 | 14 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean 15 | 16 | [2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 17 | -------------------------------------------------------------------------------- /docs/conditionals/conditional.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## ifThen 4 | 5 | Returns a css if and ONLY if condition is true. 6 | 7 | ### Parameters 8 | 9 | - `conditions` **[boolean][1]** 10 | - `returnTrue` **[string][2]** 11 | 12 | Returns **any** 13 | 14 | ## ifElse 15 | 16 | Returns a different css depending on condition value. 17 | 18 | ### Parameters 19 | 20 | - `conditions` **[boolean][1]** 21 | - `returnTrue` **[string][2]** 22 | - `returnFalse` **[string][2]** 23 | 24 | Returns **any** 25 | 26 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean 27 | 28 | [2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 29 | -------------------------------------------------------------------------------- /docs/conditionals/hover.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## hover 4 | 5 | ### Parameters 6 | 7 | - `content` **[string][1]** 8 | 9 | Returns **[string][1]** 10 | 11 | ## hoverFocus 12 | 13 | ### Parameters 14 | 15 | - `enableHoverMediaQuery` **[boolean][2]** (optional, default `defaultProps['$enable-hover-media-query']`) 16 | - `content` **[string][1]** 17 | 18 | Returns **[string][1]** 19 | 20 | ## plainHoverFocus 21 | 22 | ### Parameters 23 | 24 | - `enableHoverMediaQuery` **[boolean][2]** (optional, default `defaultProps['$enable-hover-media-query']`) 25 | - `content` **[string][1]** 26 | 27 | Returns **[string][1]** 28 | 29 | ## hoverFocusActive 30 | 31 | ### Parameters 32 | 33 | - `enableHoverMediaQuery` **[boolean][2]** (optional, default `defaultProps['$enable-hover-media-query']`) 34 | - `content` **[string][1]** 35 | 36 | Returns **[string][1]** 37 | 38 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 39 | 40 | [2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean 41 | -------------------------------------------------------------------------------- /docs/conditionals/transition.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## transition 4 | 5 | Enables transition if enableTransitions is true. 6 | 7 | ### Parameters 8 | 9 | - `enableTransitions` **[boolean][1]** (optional, default `defaultProps['$enable-transitions']`) 10 | - `args` **[array][2]** 11 | 12 | Returns **[string][3]** 13 | 14 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean 15 | 16 | [2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array 17 | 18 | [3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 19 | -------------------------------------------------------------------------------- /docs/configuration.md: -------------------------------------------------------------------------------- 1 | WIP 2 | 3 | ```js 4 | 5 | Start documenting $PACKAGE_NAME configuration, read how to at 6 | this link 7 | 8 | ``` 9 | -------------------------------------------------------------------------------- /docs/contribute.md: -------------------------------------------------------------------------------- 1 | We highly encourage contribution, any feature request and merge request will be reviewed. 2 | -------------------------------------------------------------------------------- /docs/css-mixins.md: -------------------------------------------------------------------------------- 1 | Series of functions that returns chunks of css. Basic css or helpers to speed up css boilerplate production. 2 | 3 | Be sure to check and use the conditional mixins which can later on be toggled with the BootstrapProvider. 4 | -------------------------------------------------------------------------------- /docs/cssHelpers/background-variant.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## bgVariant 4 | 5 | Css helper for component backgrounds. 6 | 7 | ### Parameters 8 | 9 | - `enableHoverMediaQuery` **[boolean][1]** Toggles hovering coloring if anchor is present. (optional, default `defaultProps['$enable-hover-media-query']`) 10 | - `selector` **[string][2]** 11 | - `bgColor` **[string][2]** 12 | 13 | Returns **[string][2]** 14 | 15 | ## hover 16 | 17 | ### Parameters 18 | 19 | - `content` **[string][2]** 20 | 21 | Returns **[string][2]** 22 | 23 | ## hoverFocus 24 | 25 | ### Parameters 26 | 27 | - `enableHoverMediaQuery` **[boolean][1]** (optional, default `defaultProps['$enable-hover-media-query']`) 28 | - `content` **[string][2]** 29 | 30 | Returns **[string][2]** 31 | 32 | ## plainHoverFocus 33 | 34 | ### Parameters 35 | 36 | - `enableHoverMediaQuery` **[boolean][1]** (optional, default `defaultProps['$enable-hover-media-query']`) 37 | - `content` **[string][2]** 38 | 39 | Returns **[string][2]** 40 | 41 | ## hoverFocusActive 42 | 43 | ### Parameters 44 | 45 | - `enableHoverMediaQuery` **[boolean][1]** (optional, default `defaultProps['$enable-hover-media-query']`) 46 | - `content` **[string][2]** 47 | 48 | Returns **[string][2]** 49 | 50 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean 51 | 52 | [2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 53 | -------------------------------------------------------------------------------- /docs/cssHelpers/border-radius.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## borderRadius 4 | 5 | Applies border-radius if enableRounded is true. 6 | 7 | ### Parameters 8 | 9 | - `enableRounded` **[boolean][1]** (optional, default `defaultProps['$enable-rounded']`) 10 | - `radius` **[string][2]** (optional, default `defaultProps['$border-radius']`) 11 | 12 | Returns **[string][2]** 13 | 14 | ## borderTopRadius 15 | 16 | Applies border-radius to the top corners if enableRounded is true. 17 | 18 | ### Parameters 19 | 20 | - `enableRounded` **[boolean][1]** (optional, default `defaultProps['$enable-rounded']`) 21 | - `radius` **[string][2]** (optional, default `defaultProps['$border-radius']`) 22 | 23 | Returns **[string][2]** 24 | 25 | ## borderRightRadius 26 | 27 | Applies border-radius to the right corners if enableRounded is true. 28 | 29 | ### Parameters 30 | 31 | - `enableRounded` **[boolean][1]** (optional, default `defaultProps['$enable-rounded']`) 32 | - `radius` **[string][2]** (optional, default `defaultProps['$border-radius']`) 33 | 34 | Returns **[string][2]** 35 | 36 | ## borderBottomRadius 37 | 38 | Applies border-radius to the bottom corners if enableRounded is true. 39 | 40 | ### Parameters 41 | 42 | - `enableRounded` **[boolean][1]** (optional, default `defaultProps['$enable-rounded']`) 43 | - `radius` **[string][2]** (optional, default `defaultProps['$border-radius']`) 44 | 45 | Returns **[string][2]** 46 | 47 | ## borderLeftRadius 48 | 49 | Applies border-radius to the left corners if enableRounded is true. 50 | 51 | ### Parameters 52 | 53 | - `enableRounded` **[boolean][1]** (optional, default `defaultProps['$enable-rounded']`) 54 | - `radius` **[string][2]** (optional, default `defaultProps['$border-radius']`) 55 | 56 | Returns **[string][2]** 57 | 58 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean 59 | 60 | [2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 61 | -------------------------------------------------------------------------------- /docs/cssHelpers/breakpoints.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## mediaBreakpointUp 4 | 5 | Media of at least the minimum breakpoint width. No query for the smallest breakpoint. Makes the @content apply to the given breakpoint and wider. 6 | 7 | ### Parameters 8 | 9 | - `name` **[string][1]** the breakpoint name (xs, sm, ...) 10 | - `breakpoints` **[object][2]** Layout grid breakpoints (optional, default `{ 11 | xs:'0', 12 | sm:'576px', 13 | md:'768px', 14 | lg:'992px', 15 | xl:'1200px', 16 | }`) 17 | - `content` **[string][1]** css (optional, default `""`) 18 | 19 | Returns **[string][1]** media css rules 20 | 21 | ## mediaBreakpointDown 22 | 23 | Media of at most the maximum breakpoint width. No query for the largest breakpoint. MMakes the @content apply to the given breakpoint and narrower. 24 | 25 | ### Parameters 26 | 27 | - `name` **[string][1]** the breakpoint name (xs, sm, ...) 28 | - `breakpoints` **[object][2]** Layout grid breakpoints (optional, default `{ 29 | xs:'0', 30 | sm:'576px', 31 | md:'768px', 32 | lg:'992px', 33 | xl:'1200px', 34 | }`) 35 | - `content` **[string][1]** css (optional, default `""`) 36 | 37 | Returns **[string][1]** 38 | 39 | ## mediaBreakpointBetween 40 | 41 | Media that spans multiple breakpoint widths. Makes the @content apply between the min and max breakpoints. 42 | 43 | ### Parameters 44 | 45 | - `lower` **[string][1]** 46 | - `upper` **[string][1]** 47 | - `breakpoints` **[object][2]** Layout grid breakpoints (optional, default `{ 48 | xs:'0', 49 | sm:'576px', 50 | md:'768px', 51 | lg:'992px', 52 | xl:'1200px', 53 | }`) 54 | - `content` **[string][1]** css (optional, default `""`) 55 | 56 | Returns **[string][1]** 57 | 58 | ## mediaBreakpointOnly 59 | 60 | Media between the breakpoint's minimum and maximum widths. 61 | No minimum for the smallest breakpoint, and no maximum for the largest one. 62 | Makes the @content apply only to the given breakpoint, not viewports any wider or narrower. 63 | 64 | ### Parameters 65 | 66 | - `name` **[string][1]** the breakpoint name (xs, sm, ...) 67 | - `breakpoints` **[object][2]** [breakpoints={ 68 | xs: '0', 69 | sm: '576px', 70 | md: '768px', 71 | lg: '992px', 72 | xl: '1200px', 73 | }] - Layout grid breakpoints (optional, default `defaultProps['$grid-breakpoints']`) 74 | - `content` **[string][1]** [content=""] - css 75 | 76 | Returns **[string][1]** 77 | 78 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 79 | 80 | [2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object 81 | -------------------------------------------------------------------------------- /docs/cssHelpers/clearfix.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## clearfix 4 | 5 | Returns **[string][1]** 6 | 7 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 8 | -------------------------------------------------------------------------------- /docs/cssHelpers/float.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## floatLeft 4 | 5 | Forces float left with !important. 6 | 7 | Returns **[string][1]** 8 | 9 | ## floatRight 10 | 11 | Forces float right with !important. 12 | 13 | Returns **[string][1]** 14 | 15 | ## floatNone 16 | 17 | Forces float none with !important. 18 | 19 | Returns **[string][1]** 20 | 21 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 22 | -------------------------------------------------------------------------------- /docs/cssHelpers/gradients.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## gradientX 4 | 5 | Horizontal gradient, from left to right. 6 | 7 | ### Parameters 8 | 9 | - `startColor` **[string][1]** (optional, default `'#555'`) 10 | - `endColor` **[string][1]** (optional, default `'#333'`) 11 | - `startPercent` **[string][1]** (optional, default `'0%'`) 12 | - `endPercent` **[string][1]** (optional, default `'100%'`) 13 | 14 | Returns **[string][1]** 15 | 16 | ## gradientY 17 | 18 | Vertical gradient, from top to bottom. 19 | 20 | ### Parameters 21 | 22 | - `startColor` **[string][1]** (optional, default `'#555'`) 23 | - `endColor` **[string][1]** (optional, default `'#333'`) 24 | - `startPercent` **[string][1]** (optional, default `'0%'`) 25 | - `endPercent` **[string][1]** (optional, default `'100%'`) 26 | 27 | Returns **[string][1]** 28 | 29 | ## gradientDirectional 30 | 31 | Directional gradient. 32 | 33 | ### Parameters 34 | 35 | - `startColor` **[string][1]** (optional, default `'#555'`) 36 | - `endColor` **[string][1]** (optional, default `'#333'`) 37 | - `deg` **[string][1]** (optional, default `'45deg'`) 38 | 39 | Returns **[string][1]** 40 | 41 | ## gradientXThreeColors 42 | 43 | Three colours gradient. 44 | 45 | ### Parameters 46 | 47 | - `startColor` **[string][1]** (optional, default `'#00b3ee'`) 48 | - `midColor` **[string][1]** (optional, default `'#7a43b6'`) 49 | - `colorStop` **[string][1]** (optional, default `'50%'`) 50 | - `endColor` **[string][1]** (optional, default `'#c3325f'`) 51 | 52 | Returns **[string][1]** 53 | 54 | ## gradientYThreeColors 55 | 56 | Vertical three colours gradient. 57 | 58 | ### Parameters 59 | 60 | - `startColor` **[string][1]** (optional, default `'#00b3ee'`) 61 | - `midColor` **[string][1]** (optional, default `'#7a43b6'`) 62 | - `colorStop` **[string][1]** (optional, default `'50%'`) 63 | - `endColor` **[string][1]** (optional, default `'#c3325f'`) 64 | 65 | Returns **[string][1]** 66 | 67 | ## gradientRadial 68 | 69 | Radial gradient. 70 | 71 | ### Parameters 72 | 73 | - `innerColor` **[string][1]** (optional, default `'#555'`) 74 | - `outerColor` **[string][1]** (optional, default `'#333'`) 75 | 76 | Returns **[string][1]** 77 | 78 | ## gradientStriped 79 | 80 | Striped angled gradient. 81 | 82 | ### Parameters 83 | 84 | - `color` **[string][1]** (optional, default `'rgba(255,255,255,.15)'`) 85 | - `angle` **[string][1]** (optional, default `'45deg'`) 86 | 87 | Returns **[string][1]** 88 | 89 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 90 | -------------------------------------------------------------------------------- /docs/cssHelpers/gridbreakpoints.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/cssHelpers/lists.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## listUnstyled 4 | 5 | Unstyled keeps list items block level, just removes default browser padding and list-style. 6 | 7 | Returns **[string][1]** 8 | 9 | ## listInlineItem 10 | 11 | Inline list and removes margin for last child. 12 | 13 | ### Parameters 14 | 15 | - `listInlinePadding` 16 | 17 | Returns **[string][1]** 18 | 19 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 20 | -------------------------------------------------------------------------------- /docs/cssHelpers/nav-divider.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## navDivider 4 | 5 | Dividers for certain components (Dropdown, Nav, List, ...). 6 | 7 | ### Parameters 8 | 9 | - `spacerY` **[string][1]** (optional, default `defaultProps['$spacer-y']`) 10 | - `dividerColor` **[string][1]** (optional, default `'#e5e5e5'`) 11 | 12 | Returns **[string][1]** 13 | 14 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 15 | -------------------------------------------------------------------------------- /docs/cssHelpers/screen-reader.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## srOnly 4 | 5 | Only display content to screen readers. See: [http://a11yproject.com/posts/how-to-hide-content][1] 6 | 7 | Returns **[string][2]** 8 | 9 | ## srOnlyFocusable 10 | 11 | Use in conjunction with .sr-only to only display content when it's focused. Useful for 'Skip to main content' links; see [https://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1][3] 12 | 13 | Returns **[string][2]** 14 | 15 | [1]: http://a11yproject.com/posts/how-to-hide-content 16 | 17 | [2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 18 | 19 | [3]: https://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 20 | -------------------------------------------------------------------------------- /docs/cssHelpers/size.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## size 4 | 5 | ### Parameters 6 | 7 | - `width` **[string][1]** 8 | - `height` **[string][1]** If unspecified will use width value by default. (optional, default `width`) 9 | 10 | Returns **[string][1]** 11 | 12 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 13 | -------------------------------------------------------------------------------- /docs/cssHelpers/text-emphasis.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## textEmphasisVariant 4 | 5 | Forces text color and hovering from a parent component. 6 | 7 | ### Parameters 8 | 9 | - `enableHoverMediaQuery` **[boolean][1]** (optional, default `defaultProps['$enable-hover-media-query']`) 10 | - `parent` **[string][2]** 11 | - `textColor` **[string][2]** 12 | 13 | Returns **[string][2]** 14 | 15 | ## hover 16 | 17 | ### Parameters 18 | 19 | - `content` **[string][2]** 20 | 21 | Returns **[string][2]** 22 | 23 | ## hoverFocus 24 | 25 | ### Parameters 26 | 27 | - `enableHoverMediaQuery` **[boolean][1]** (optional, default `defaultProps['$enable-hover-media-query']`) 28 | - `content` **[string][2]** 29 | 30 | Returns **[string][2]** 31 | 32 | ## plainHoverFocus 33 | 34 | ### Parameters 35 | 36 | - `enableHoverMediaQuery` **[boolean][1]** (optional, default `defaultProps['$enable-hover-media-query']`) 37 | - `content` **[string][2]** 38 | 39 | Returns **[string][2]** 40 | 41 | ## hoverFocusActive 42 | 43 | ### Parameters 44 | 45 | - `enableHoverMediaQuery` **[boolean][1]** (optional, default `defaultProps['$enable-hover-media-query']`) 46 | - `content` **[string][2]** 47 | 48 | Returns **[string][2]** 49 | 50 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean 51 | 52 | [2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 53 | -------------------------------------------------------------------------------- /docs/cssHelpers/text-hide.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## textHide 4 | 5 | Hides text. 6 | 7 | Returns **[string][1]** 8 | 9 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 10 | -------------------------------------------------------------------------------- /docs/cssHelpers/text-truncate.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## textTruncate 4 | 5 | Text truncate. Requires inline-block or block for proper styling. 6 | 7 | Returns **[string][1]** 8 | 9 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 10 | -------------------------------------------------------------------------------- /docs/cssHelpers/visibility.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## invisible 4 | 5 | Forces visibility value with !important 6 | 7 | ### Parameters 8 | 9 | - `visibility` 10 | 11 | Returns **[string][1]** 12 | 13 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 14 | -------------------------------------------------------------------------------- /docs/faq.md: -------------------------------------------------------------------------------- 1 | - What is rollup-umd ? 2 | 3 | > It is the boilerplate for all JS project aimed to be packaged. 4 | It is made on top of rollup because the distribution can work everywhere. 5 | If you are a contributor, we strongly suggest you to read [rollup-umd documentation](https://dev-tools.yeutech.com/rollup-umd/). 6 | 7 | - What is rollup-umd-scripts ? 8 | 9 | > It is a package containing scripts for creating and maintaining all rollup-umd projects. 10 | We use it with `npx`, the benefits compare to `npm install -g` is that we don't need to install it or upgrade, it download the CLI for every commands. 11 | If you are a contributor, we strongly suggest you to read [rollup-umd-scripts documentation](https://dev-tools.yeutech.com/rollup-umd-scripts/). 12 | 13 | - What is rollup-umd-documentation ? 14 | 15 | > It is our react-styleguide configuration, it also provide UI components for the documentation. 16 | If you are a contributor, we strongly suggest you to read [rollup-documentation documentation](https://dev-tools.yeutech.com/rollup-documentation/). 17 | -------------------------------------------------------------------------------- /docs/getting-started.md: -------------------------------------------------------------------------------- 1 | Like every [rollup-umd](dev-tools.yeutech.com/rollup-umd) project $PACKAGE_NAME provide two distribution: 2 | 3 | 1. `dist` folder with all the javascript bundled in one file. You will have a UMD and ES5 file. 4 | 1. `lib` folder that just contain the ES6 transpiled in ES5. 5 | 6 | Whenever you use $PACKAGE_NAME, you need to import the one appropriate to your environment (node or browser). 7 | 8 | If you are building a distributed package in a node environment, you want to prevent bundling the whole library you are importing (if made with rollup-umd). 9 | 10 | To do so, always import from `lib`. 11 | 12 | This is correct: 13 | 14 | ```js static 15 | import myLib from '$PACKAGE_NAME/lib'; 16 | ``` 17 | 18 | This is wrong: 19 | 20 | ```js static 21 | import myLib from '$PACKAGE_NAME'; 22 | ``` 23 | 24 | If you are a developer, you want to read more [here](http://dev-tools.yeutech.com/rollup-umd/#distribution). 25 | -------------------------------------------------------------------------------- /docs/installation.md: -------------------------------------------------------------------------------- 1 | ```bash 2 | $ npm install $PACKAGE_NAME --save 3 | ``` 4 | -------------------------------------------------------------------------------- /docs/introduction.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/bootstrap-styled/css-mixins.svg?branch=master)](https://travis-ci.org/bootstrap-styled/css-mixins) [![npm Version](https://img.shields.io/npm/v/@bootstrap-styled/css-mixins.svg?style=flat)](https://www.npmjs.com/package/@bootstrap-styled/css-mixins) [![License](https://img.shields.io/npm/l/@bootstrap-styled/css-mixins.svg?style=flat)](https://www.npmjs.com/package/@bootstrap-styled/css-mixins) [![npm Version](https://img.shields.io/node/v/@bootstrap-styled/css-mixins.svg?style=flat)](https://www.npmjs.com/package/@bootstrap-styled/css-mixins) [![Module formats](https://img.shields.io/badge/module%20formats-umd%2C%20cjs%2C%20esm-green.svg?style=flat)](https://www.npmjs.com/package/@bootstrap-styled/css-mixins) 2 | 3 | Bootstrap mixins and utilities in javascript for bootstrap-styled. 4 | -------------------------------------------------------------------------------- /docs/prerequisite.md: -------------------------------------------------------------------------------- 1 | If you don't have them, install all the `peerDependencies` in your project: 2 | 3 | ```bash 4 | $ $PACKAGE_PEERS 5 | ``` 6 | -------------------------------------------------------------------------------- /docs/release.md: -------------------------------------------------------------------------------- 1 | Merge `dev` into `master` will release the documentation and tag a new version. 2 | -------------------------------------------------------------------------------- /internals/testing/test-bundler.js: -------------------------------------------------------------------------------- 1 | const Enzyme = require('enzyme'); 2 | const Adapter = require('enzyme-adapter-react-16'); 3 | Enzyme.configure({ adapter: new Adapter() }); 4 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | const { createConfig } = require('@rollup-umd/rollup'); 2 | module.exports = createConfig(); 3 | -------------------------------------------------------------------------------- /sonar-project.properties: -------------------------------------------------------------------------------- 1 | sonar.testExecutionReportPaths=reports/test-report.xml 2 | sonar.projectKey=com.github.bootstrap-styled.css-mixins 3 | sonar.projectName=com.github.bootstrap-styled.css-mixins 4 | sonar.sources=src 5 | sonar.exclusions=/src/**/tests/*.test.js 6 | sonar.test.exclusions=/src/**/tests/*.test.js 7 | sonar.dynamicAnalysis=reuseReports 8 | sonar.javascript.jstest.reportsPath=coverage 9 | sonar.javascript.lcov.reportPaths=coverage/lcov.info 10 | sonar.organization=bootstrap-styled 11 | -------------------------------------------------------------------------------- /src/MixinError.js: -------------------------------------------------------------------------------- 1 | export default class MixinError extends Error { 2 | constructor(args) { 3 | super(args); 4 | Error.captureStackTrace(this, MixinError); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/a.js: -------------------------------------------------------------------------------- 1 | import { tabFocus } from './tab-focus'; 2 | import { hoverFocus } from './hover'; 3 | 4 | export const defaultProps = { 5 | '$link-color': '#0275d8', 6 | '$link-decoration': 'none', 7 | '$link-hover-color': '#014C8D', 8 | '$link-hover-decoration': 'underline', 9 | '$enable-hover-media-query': false, 10 | }; 11 | 12 | /** 13 | * @public 14 | * @description Basic css for Anchor component. 15 | * @param {string} $linkColor 16 | * @param {string} $linkDecoration 17 | * @param {string} $linkHoverColor 18 | * @param {string} $linkHoverDecoration 19 | * @param {boolean} $enableHoverMediaQuery 20 | * @returns {string} 21 | */ 22 | export function a( 23 | $linkColor = defaultProps['$link-color'], 24 | $linkDecoration = defaultProps['$link-decoration'], 25 | $linkHoverColor = defaultProps['$link-hover-color'], 26 | $linkHoverDecoration = defaultProps['$link-hover-decoration'], 27 | $enableHoverMediaQuery = defaultProps['$enable-hover-media-query'], 28 | ) { 29 | return ` 30 | color: ${$linkColor}; 31 | text-decoration: ${$linkDecoration}; 32 | background-color: transparent; 33 | -webkit-text-decoration-skip: objects; 34 | 35 | ${hoverFocus($enableHoverMediaQuery, ` 36 | color: ${$linkHoverColor}; 37 | text-decoration: ${$linkHoverDecoration}; 38 | `)} 39 | 40 | &:focus { 41 | ${tabFocus()} 42 | } 43 | 44 | a:not([href]):not([tabindex]) { 45 | color: inherit; 46 | text-decoration: none; 47 | 48 | ${hoverFocus($enableHoverMediaQuery, ` 49 | color: inherit; 50 | text-decoration: none; 51 | `)} 52 | 53 | &:focus { 54 | outline: 0; 55 | } 56 | } 57 | `; 58 | } 59 | 60 | export default { 61 | defaultProps, 62 | a, 63 | }; 64 | -------------------------------------------------------------------------------- /src/alert.js: -------------------------------------------------------------------------------- 1 | import color from '@bootstrap-styled/color'; 2 | 3 | /** 4 | * @public 5 | * @description Basic css helper for different colored Alert components. 6 | * @param {string} background 7 | * @param {string} border 8 | * @param {string} bodyColor 9 | * @returns {string} 10 | */ 11 | export function alertVariant(background, border, bodyColor) { 12 | return ` 13 | background-color: ${background}; 14 | border-color: ${border}; 15 | color: ${bodyColor}; 16 | 17 | hr { 18 | border-top-color: ${color(border).darken(0.5).toString()}; 19 | } 20 | .alert-link { 21 | color: ${color(bodyColor).darken(0.1).toString()}; 22 | } 23 | `; 24 | } 25 | 26 | export default { 27 | alertVariant, 28 | }; 29 | -------------------------------------------------------------------------------- /src/background-variant.js: -------------------------------------------------------------------------------- 1 | import color from '@bootstrap-styled/color'; 2 | import { hoverFocus } from './hover'; 3 | 4 | export const defaultProps = { 5 | '$enable-hover-media-query': false, 6 | }; 7 | 8 | /** 9 | * @public 10 | * @description Css helper for component backgrounds. 11 | * @param {boolean} enableHoverMediaQuery Toggles hovering coloring if anchor is present. 12 | * @param {string} selector 13 | * @param {string} bgColor 14 | * @returns {string} 15 | */ 16 | export function bgVariant(enableHoverMediaQuery = defaultProps['$enable-hover-media-query'], selector, bgColor) { 17 | return ` 18 | ${selector} { 19 | background-color: ${bgColor} !important; 20 | } 21 | a${selector} { 22 | ${hoverFocus(enableHoverMediaQuery, `background-color: ${color(bgColor).darken(0.2).rgb()} !important;`)} 23 | } 24 | `; 25 | } 26 | 27 | export default { 28 | bgVariant, 29 | }; 30 | -------------------------------------------------------------------------------- /src/badge.js: -------------------------------------------------------------------------------- 1 | import color from '@bootstrap-styled/color'; 2 | import { hoverFocus } from './hover'; 3 | 4 | export const defaultProps = { 5 | '$enable-hover-mediaQuery': false, 6 | }; 7 | 8 | /** 9 | * @public 10 | * @description Basic css helper for Badge components background. 11 | * @param enableHoverMediaQuery 12 | * @param badgeColor 13 | * @returns {string} 14 | */ 15 | export function badgeVariant(enableHoverMediaQuery = defaultProps['$enable-hover-mediaQuery'], badgeColor) { 16 | return ` 17 | background-color: ${badgeColor}; 18 | 19 | &[href] { 20 | ${hoverFocus(enableHoverMediaQuery, `background-color: ${color(badgeColor).darken(0.1).toString()};`)} 21 | } 22 | `; 23 | } 24 | 25 | export default { 26 | defaultProps, 27 | badgeVariant, 28 | }; 29 | -------------------------------------------------------------------------------- /src/border-radius.js: -------------------------------------------------------------------------------- 1 | export const defaultProps = { 2 | '$border-radius': '.25rem', 3 | '$enable-rounded': true, 4 | }; 5 | 6 | /** 7 | * @public 8 | * @description Applies border-radius if enableRounded is true. 9 | * @param {boolean} enableRounded 10 | * @param {string} radius 11 | * @returns {string} 12 | */ 13 | export function borderRadius(enableRounded = defaultProps['$enable-rounded'], radius = defaultProps['$border-radius']) { 14 | if (enableRounded) { 15 | return ` 16 | border-radius: ${radius}; 17 | `; 18 | } 19 | return ''; 20 | } 21 | /** 22 | * @public 23 | * @description Applies border-radius to the top corners if enableRounded is true. 24 | * @param {boolean} enableRounded 25 | * @param {string} radius 26 | * @returns {string} 27 | */ 28 | export function borderTopRadius(enableRounded = defaultProps['$enable-rounded'], radius = defaultProps['$border-radius']) { 29 | if (enableRounded) { 30 | return ` 31 | border-top-right-radius: ${radius}; 32 | border-top-left-radius: ${radius}; 33 | `; 34 | } 35 | return ''; 36 | } 37 | 38 | /** 39 | * @public 40 | * @description Applies border-radius to the right corners if enableRounded is true. 41 | * @param {boolean} enableRounded 42 | * @param {string} radius 43 | * @returns {string} 44 | */ 45 | export function borderRightRadius(enableRounded = defaultProps['$enable-rounded'], radius = defaultProps['$border-radius']) { 46 | if (enableRounded) { 47 | return ` 48 | border-bottom-right-radius: ${radius}; 49 | border-top-right-radius: ${radius}; 50 | `; 51 | } 52 | return ''; 53 | } 54 | 55 | /** 56 | * @public 57 | * @description Applies border-radius to the bottom corners if enableRounded is true. 58 | * @param {boolean} enableRounded 59 | * @param {string} radius 60 | * @returns {string} 61 | */ 62 | export function borderBottomRadius(enableRounded = defaultProps['$enable-rounded'], radius = defaultProps['$border-radius']) { 63 | if (enableRounded) { 64 | return ` 65 | border-bottom-right-radius: ${radius}; 66 | border-bottom-left-radius: ${radius}; 67 | `; 68 | } 69 | return ''; 70 | } 71 | 72 | /** 73 | * @public 74 | * @description Applies border-radius to the left corners if enableRounded is true. 75 | * @param {boolean} enableRounded 76 | * @param {string} radius 77 | * @returns {string} 78 | */ 79 | export function borderLeftRadius(enableRounded = defaultProps['$enable-rounded'], radius = defaultProps['$border-radius']) { 80 | if (enableRounded) { 81 | return ` 82 | border-bottom-left-radius: ${radius}; 83 | border-top-left-radius: ${radius}; 84 | `; 85 | } 86 | return ''; 87 | } 88 | 89 | export default { 90 | defaultProps, 91 | all: borderRadius, 92 | top: borderTopRadius, 93 | right: borderRightRadius, 94 | bottom: borderBottomRadius, 95 | left: borderLeftRadius, 96 | }; 97 | -------------------------------------------------------------------------------- /src/box-shadow.js: -------------------------------------------------------------------------------- 1 | export const defaultProps = { 2 | '$enable-shadows': false, 3 | }; 4 | 5 | /** 6 | * @public 7 | * @description Applies box-shadow if enableShadows is true. 8 | * @param {boolean} enableShadows 9 | * @param {array} ...args 10 | * @returns {string} 11 | */ 12 | export function boxShadow(enableShadows = defaultProps['$enable-shadows'], ...args) { 13 | if (enableShadows) { 14 | return ` 15 | box-shadow: ${args.join(' ')}; 16 | `; 17 | } 18 | return ''; 19 | } 20 | 21 | export default { 22 | defaultProps, 23 | boxShadow, 24 | }; 25 | -------------------------------------------------------------------------------- /src/breakpoints.js: -------------------------------------------------------------------------------- 1 | // Breakpoint viewport sizes and media queries. 2 | // 3 | // Breakpoints are defined as a map of (name: minimum width), order from small to large: 4 | // 5 | // (xs: 0, sm: 544px, md: 768px) 6 | // 7 | // The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default. 8 | 9 | import unitUtils from '@bootstrap-styled/utils/lib/unitUtils'; 10 | 11 | export const defaultProps = { 12 | '$grid-breakpoints': { 13 | xs: '0', 14 | sm: '576px', 15 | md: '768px', 16 | lg: '992px', 17 | xl: '1200px', 18 | }, 19 | }; 20 | 21 | /** 22 | * @private 23 | * @description Name of the next breakpoint, or null for the last breakpoint. 24 | * @param {string} name - the breakpoint name (xs, sm, ...) 25 | * @param {object} [breakpoints={ 26 | xs: '0', 27 | sm: '576px', 28 | md: '768px', 29 | lg: '992px', 30 | xl: '1200px', 31 | }] - Layout grid breakpoints 32 | * @param {array} breakpointNames 33 | * @example 34 | * breakpointNext('sm') 35 | * // md 36 | * @example 37 | * breakpointNext('sm', { xs: 0, sm: '544px', md: '768px' }) 38 | * // md 39 | * @example 40 | * breakpointNext('sm', null, ['xs', 'sm', 'md']) 41 | * // md 42 | * @returns {*} 43 | */ 44 | export function breakpointNext(name, breakpoints = defaultProps['$grid-breakpoints'], breakpointNames = Object.keys(breakpoints)) { 45 | const n = breakpointNames.indexOf(name); 46 | if (n !== -1 && n + 1 < breakpointNames.length) { 47 | return breakpointNames[n + 1]; 48 | } 49 | return null; 50 | } 51 | 52 | /** 53 | * @private 54 | * @description Minimum breakpoint width. Null for the smallest (first) breakpoint. 55 | * @param {string} name - the breakpoint name (xs, sm, ...) 56 | * @param {object} [breakpoints={ 57 | xs: '0', 58 | sm: '576px', 59 | md: '768px', 60 | lg: '992px', 61 | xl: '1200px', 62 | }] - Layout grid breakpoints 63 | * @example 64 | * breakpointMin('sm', { xs: '0', sm: '544px', md: '768px' }); 65 | * // 544px 66 | * @returns {*} 67 | */ 68 | export function breakpointMin(name, breakpoints = defaultProps['$grid-breakpoints']) { 69 | const min = breakpoints[name]; 70 | return min !== '0' ? min : null; 71 | } 72 | 73 | /** 74 | * @private 75 | * @description Maximum breakpoint width. Null for the largest (last) breakpoint. 76 | * @param {string} name - the breakpoint name (xs, sm, ...) 77 | * @param {object} [breakpoints={ 78 | xs: '0', 79 | sm: '576px', 80 | md: '768px', 81 | lg: '992px', 82 | xl: '1200px', 83 | }] - Layout grid breakpoints 84 | * @example 85 | * breakpointMax('sm', { xs: 0, sm: '544px', md: '768px' }) 86 | * // 767px 87 | * @returns {string|null} 88 | */ 89 | export function breakpointMax(name, breakpoints = defaultProps['$grid-breakpoints']) { 90 | const next = breakpointNext(name, breakpoints); 91 | if (next) { 92 | const min = unitUtils.rmUnit(breakpointMin(next, breakpoints), unitUtils.UNIT.PX); 93 | return (min - 1).toString() + unitUtils.UNIT.PX; 94 | } 95 | return null; 96 | } 97 | 98 | /** 99 | * @private 100 | * @description Returns a blank string if smallest breakpoint, otherwise returns the name with a dash infront. 101 | * @param {string} name - the breakpoint name (xs, sm, ...) 102 | * @param {object} [breakpoints={ 103 | xs: '0', 104 | sm: '576px', 105 | md: '768px', 106 | lg: '992px', 107 | xl: '1200px', 108 | }] - Layout grid breakpoints 109 | * @example 110 | * breakpointInfix('xs', { xs: 0, sm: '576px', md: '768px', lg: '992px', xl: '1200px' }) 111 | * // (return a blank string) 112 | * @example 113 | * breakpointInfix('sm', { xs: 0, sm: '576px', md: '768px', lg: '992px', xl: '1200px' }) 114 | * // -sm 115 | * @returns {string} 116 | */ 117 | export function breakpointInfix(name, breakpoints = defaultProps['$grid-breakpoints']) { 118 | return !name || breakpointMin(name, breakpoints) === null ? '' : `-${name}`; 119 | } 120 | 121 | /** 122 | * @public 123 | * @description Media of at least the minimum breakpoint width. No query for the smallest breakpoint. Makes the @content apply to the given breakpoint and wider. 124 | * @param {string} name - the breakpoint name (xs, sm, ...) 125 | * @param {object} [breakpoints={ 126 | xs: '0', 127 | sm: '576px', 128 | md: '768px', 129 | lg: '992px', 130 | xl: '1200px', 131 | }] - Layout grid breakpoints 132 | * @param {string} [content=""] - css 133 | * @returns {string} media css rules 134 | */ 135 | export function mediaBreakpointUp(name, breakpoints = defaultProps['$grid-breakpoints'], content = '') { 136 | const min = breakpointMin(name, breakpoints); 137 | if (min) { 138 | return ` 139 | @media (min-width: ${min}) { 140 | ${content} 141 | } 142 | `; 143 | } 144 | return content; 145 | } 146 | 147 | /** 148 | * @public 149 | * @description Media of at most the maximum breakpoint width. No query for the largest breakpoint. MMakes the @content apply to the given breakpoint and narrower. 150 | * @param {string} name - the breakpoint name (xs, sm, ...) 151 | * @param {object} [breakpoints={ 152 | xs: '0', 153 | sm: '576px', 154 | md: '768px', 155 | lg: '992px', 156 | xl: '1200px', 157 | }] - Layout grid breakpoints 158 | * @param {string} [content=""] - css 159 | * @returns {string} 160 | */ 161 | export function mediaBreakpointDown(name, breakpoints = defaultProps['$grid-breakpoints'], content) { 162 | const max = breakpointMax(name, breakpoints); 163 | if (max) { 164 | return ` 165 | @media (max-width: ${max}) { 166 | ${content} 167 | } 168 | `; 169 | } 170 | return content; 171 | } 172 | 173 | 174 | /** 175 | * @public 176 | * @description Media that spans multiple breakpoint widths. Makes the @content apply between the min and max breakpoints. 177 | * @param {string} lower 178 | * @param {string} upper 179 | * @param {object} [breakpoints={ 180 | xs: '0', 181 | sm: '576px', 182 | md: '768px', 183 | lg: '992px', 184 | xl: '1200px', 185 | }] - Layout grid breakpoints 186 | * @param {string} [content=""] - css 187 | * @returns {string} 188 | */ 189 | export function mediaBreakpointBetween(lower, upper, breakpoints = defaultProps['$grid-breakpoints'], content) { 190 | const min = breakpointMin(lower, breakpoints); 191 | const max = breakpointMax(upper, breakpoints); 192 | if (min && max) { 193 | return ` 194 | @media (min-width: ${min}) and (max-width: ${max}) { 195 | ${content} 196 | } 197 | `; 198 | } else if (min) { 199 | return ` 200 | @media (min-width: ${min}) { 201 | ${content} 202 | } 203 | `; 204 | } else if (max) { 205 | return ` 206 | @media (max-width: ${max}) { 207 | ${content} 208 | } 209 | `; 210 | } 211 | return content; 212 | } 213 | 214 | /** 215 | * @public 216 | * @description Media between the breakpoint's minimum and maximum widths. 217 | * No minimum for the smallest breakpoint, and no maximum for the largest one. 218 | * Makes the @content apply only to the given breakpoint, not viewports any wider or narrower. 219 | * @param {string} name - the breakpoint name (xs, sm, ...) 220 | * @param {object} breakpoints [breakpoints={ 221 | xs: '0', 222 | sm: '576px', 223 | md: '768px', 224 | lg: '992px', 225 | xl: '1200px', 226 | }] - Layout grid breakpoints 227 | * @param {string} content [content=""] - css 228 | * @returns {string} 229 | */ 230 | export function mediaBreakpointOnly(name, breakpoints = defaultProps['$grid-breakpoints'], content) { 231 | return mediaBreakpointBetween(name, name, breakpoints, content); 232 | } 233 | 234 | export default { 235 | defaultProps, 236 | up: mediaBreakpointUp, 237 | down: mediaBreakpointDown, 238 | between: mediaBreakpointBetween, 239 | only: mediaBreakpointOnly, 240 | }; 241 | -------------------------------------------------------------------------------- /src/clearfix.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @public 3 | * @decription Basic css for clearfix feature. 4 | * @returns {string} 5 | */ 6 | export function clearfix() { 7 | return ` 8 | &::after { 9 | content: ""; 10 | display: table; 11 | clear: both; 12 | } 13 | `; 14 | } 15 | 16 | export default { 17 | clearfix, 18 | }; 19 | -------------------------------------------------------------------------------- /src/conditional.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @public 3 | * @description Returns a css if and ONLY if condition is true. 4 | * @param {boolean} conditions 5 | * @param {string} returnTrue 6 | * @returns {*} 7 | */ 8 | export function ifThen(conditions, returnTrue) { 9 | return ifElse(conditions, returnTrue, ''); 10 | } 11 | 12 | /** 13 | * @public 14 | * @description Returns a different css depending on condition value. 15 | * @param {boolean} conditions 16 | * @param {string} returnTrue 17 | * @param {string} returnFalse 18 | * @returns {*} 19 | */ 20 | export function ifElse(conditions, returnTrue, returnFalse) { 21 | return conditions ? returnTrue : returnFalse; 22 | } 23 | 24 | export default { 25 | ifThen, 26 | ifElse, 27 | }; 28 | -------------------------------------------------------------------------------- /src/float.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @public 3 | * @description Forces float left with !important. 4 | * @returns {string} 5 | */ 6 | export function floatLeft() { 7 | return ` 8 | float: left !important; 9 | `; 10 | } 11 | 12 | /** 13 | * @public 14 | * @description Forces float right with !important. 15 | * @returns {string} 16 | */ 17 | export function floatRight() { 18 | return ` 19 | float: right !important; 20 | `; 21 | } 22 | 23 | /** 24 | * @public 25 | * @description Forces float none with !important. 26 | * @returns {string} 27 | */ 28 | export function floatNone() { 29 | return ` 30 | float: none !important; 31 | `; 32 | } 33 | 34 | export default { 35 | floatLeft, 36 | floatRight, 37 | floatNone, 38 | }; 39 | -------------------------------------------------------------------------------- /src/gradients.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @public 3 | * @description Horizontal gradient, from left to right. 4 | * @param {string} startColor 5 | * @param {string} endColor 6 | * @param {string} startPercent 7 | * @param {string} endPercent 8 | * @returns {string} 9 | */ 10 | export function gradientX(startColor = '#555', endColor = '#333', startPercent = '0%', endPercent = '100%') { 11 | return ` 12 | background-image: linear-gradient(to right, ${startColor} ${startPercent}, ${endColor} ${endPercent}); 13 | background-repeat: repeat-x; 14 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str(${startColor})}', endColorstr='#{ie-hex-str(${endColor})}', GradientType=1); // IE9 15 | `; 16 | } 17 | 18 | /** 19 | * @public 20 | * @description Vertical gradient, from top to bottom. 21 | * @param {string} startColor 22 | * @param {string} endColor 23 | * @param {string} startPercent 24 | * @param {string} endPercent 25 | * @returns {string} 26 | */ 27 | export function gradientY(startColor = '#555', endColor = '#333', startPercent = '0%', endPercent = '100%') { 28 | return ` 29 | background-image: linear-gradient(to bottom, ${startColor} ${startPercent}, ${endColor} ${endPercent}); 30 | background-repeat: repeat-x; 31 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str(${startColor})}', endColorstr='#{ie-hex-str(${endColor})}', GradientType=0); // IE9 32 | `; 33 | } 34 | 35 | /** 36 | * @public 37 | * @description Directional gradient. 38 | * @param {string} startColor 39 | * @param {string} endColor 40 | * @param {string} deg 41 | * @returns {string} 42 | */ 43 | export function gradientDirectional(startColor = '#555', endColor = '#333', deg = '45deg') { 44 | return ` 45 | background-repeat: repeat-x; 46 | background-image: linear-gradient(${deg}, ${startColor}, ${endColor}); 47 | `; 48 | } 49 | 50 | /** 51 | * @public 52 | * @description Three colours gradient. 53 | * @param {string} startColor 54 | * @param {string} midColor 55 | * @param {string} colorStop 56 | * @param {string} endColor 57 | * @returns {string} 58 | */ 59 | export function gradientXThreeColors(startColor = '#00b3ee', midColor = '#7a43b6', colorStop = '50%', endColor = '#c3325f') { 60 | return ` 61 | background-image: linear-gradient(to right, ${startColor}, ${midColor} ${colorStop}, ${endColor}); 62 | background-repeat: no-repeat; 63 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str(${startColor})}', endColorstr='#{ie-hex-str(${endColor})}', GradientType=1); // IE9 gets no color-stop at all for proper fallback 64 | `; 65 | } 66 | 67 | /** 68 | * @public 69 | * @description Vertical three colours gradient. 70 | * @param {string} startColor 71 | * @param {string} midColor 72 | * @param {string} colorStop 73 | * @param {string} endColor 74 | * @returns {string} 75 | */ 76 | export function gradientYThreeColors(startColor = '#00b3ee', midColor = '#7a43b6', colorStop = '50%', endColor = '#c3325f') { 77 | return ` 78 | background-image: linear-gradient(${startColor}, ${midColor} ${colorStop}, ${endColor}); 79 | background-repeat: no-repeat; 80 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str(${startColor})}', endColorstr='#{ie-hex-str(${endColor})}', GradientType=0); // IE9 gets no color-stop at all for proper fallback 81 | `; 82 | } 83 | 84 | /** 85 | * @public 86 | * @description Radial gradient. 87 | * @param {string} innerColor 88 | * @param {string} outerColor 89 | * @returns {string} 90 | */ 91 | export function gradientRadial(innerColor = '#555', outerColor = '#333') { 92 | return ` 93 | background-image: radial-gradient(circle, ${innerColor}, ${outerColor}); 94 | background-repeat: no-repeat; 95 | `; 96 | } 97 | 98 | /** 99 | * @public 100 | * @description Striped angled gradient. 101 | * @param {string} color 102 | * @param {string} angle 103 | * @returns {string} 104 | */ 105 | export function gradientStriped(color = 'rgba(255,255,255,.15)', angle = '45deg') { 106 | return ` 107 | background-image: linear-gradient(${angle}, ${color} 25%, transparent 25%, transparent 50%, ${color} 50%, ${color} 75%, transparent 75%, transparent); 108 | `; 109 | } 110 | 111 | export default { 112 | x: gradientX, 113 | y: gradientY, 114 | directional: gradientDirectional, 115 | xThreeColors: gradientXThreeColors, 116 | yThreeColors: gradientYThreeColors, 117 | radial: gradientRadial, 118 | striped: gradientStriped, 119 | }; 120 | -------------------------------------------------------------------------------- /src/grid-framework.js: -------------------------------------------------------------------------------- 1 | // Framework grid generation 2 | // 3 | // Used only by Bootstrap to generate the correct number of grid classes given 4 | // any value of `$grid-columns`. 5 | 6 | import { makeCol, makeColOffset, defaultProps } from './grid'; 7 | import { mediaBreakpointUp, breakpointInfix } from './breakpoints'; 8 | 9 | /** 10 | * @public 11 | * @description Used only by Bootstrap to generate the correct number of grid classes given any value of `$grid-columns`. 12 | * @param {boolean} [enableGridClasses=true] - if `false`, the function will return an empty string 13 | * @param {number} [columns=12] - the number of columns 14 | * @param {string|number} [gutter=30px] - the grid gutter width 15 | * @param {object} [breakpoints={ 16 | xs: '0', 17 | sm: '576px', 18 | md: '768px', 19 | lg: '992px', 20 | xl: '1200px', 21 | }] - The layout max-width grid breakpoint 22 | * 23 | * @returns {string} - css mixins utilities for bootstrap grid system 24 | */ 25 | export function makeGridColumns( 26 | enableGridClasses = defaultProps['$enable-grid-classes'], 27 | columns = defaultProps['$grid-columns'], 28 | gutter = defaultProps['$grid-gutter-width'], 29 | breakpoints = defaultProps['$grid-breakpoints'] 30 | ) { 31 | // Common properties for all breakpoints 32 | const gridColumn = ` 33 | position: relative; 34 | width: 100%; 35 | min-height: 1px; // Prevent columns from collapsing when empty 36 | padding-right: calc(${gutter} / 2); 37 | padding-left: calc(${gutter} / 2); 38 | `; 39 | 40 | return enableGridClasses ? Object.keys(breakpoints).map((bp) => { 41 | const infix = breakpointInfix(bp, breakpoints); 42 | // Allow columns to stretch full width below their breakpoints 43 | return `${Array.from({ length: columns }, (_, ind) => { 44 | const i = ind + 1; 45 | return `&.col${infix}-${i}, & .col${infix}-${i} { ${gridColumn} }`; 46 | }).join('\n')} 47 | 48 | &.col${infix}, 49 | & .col${infix}-auto { 50 | ${gridColumn} 51 | } 52 | 53 | ${// Provide basic `.col-{bp}` classes for equal-width flexbox columns 54 | mediaBreakpointUp(bp, breakpoints, ` 55 | &.col${infix}, 56 | & .col${infix} { 57 | flex-basis: 0; 58 | flex-grow: 1; 59 | max-width: 100%; 60 | } 61 | &.col${infix}-auto, 62 | & .col${infix}-auto { 63 | flex: 0 0 auto; 64 | width: auto; 65 | max-width: none; // reset earlier grid tiers 66 | } 67 | 68 | ${Array.from({ length: columns }, (_, i) => ` 69 | &.col${infix}-${i + 1}, 70 | & .col${infix}-${i + 1} { 71 | ${makeCol(i + 1, columns)} 72 | } 73 | `)} 74 | 75 | &.order${infix}-first, 76 | & .order${infix}-first { order: -1; } 77 | 78 | &.order${infix}-last, 79 | & .order${infix}-last { order: ${columns + 1}; } 80 | 81 | ${Array.from({ length: columns }, (_, i) => ` 82 | &.order${infix}-${i}, 83 | & .order${infix}-${i} { 84 | order: ${i}; 85 | } 86 | `).join('\n')} 87 | 88 | ${// `$columns - 1` because offsetting by the width of an entire row isn't possible 89 | Array.from({ length: columns - 1 }, (_, i) => ` 90 | &.offset${infix}-${i}, 91 | & .offset${infix}-${i} { 92 | ${makeColOffset(i, columns)} 93 | } 94 | `).join('\n')} 95 | `)} 96 | `; 97 | }).join('\n') : ''; 98 | } 99 | 100 | export default { 101 | makeGridColumns, 102 | }; 103 | -------------------------------------------------------------------------------- /src/grid.js: -------------------------------------------------------------------------------- 1 | import unitUtils from '@bootstrap-styled/utils/lib/unitUtils'; 2 | import { mediaBreakpointUp } from './breakpoints'; 3 | 4 | const { toPercent } = unitUtils; 5 | 6 | export const defaultProps = { 7 | '$grid-gutter-width': '30px', 8 | '$container-max-widths': { 9 | sm: '540px', 10 | md: '720px', 11 | lg: '960px', 12 | xl: '1140px', 13 | }, 14 | '$grid-breakpoints': { 15 | xs: '0', 16 | sm: '576px', 17 | md: '768px', 18 | lg: '992px', 19 | xl: '1200px', 20 | }, 21 | '$grid-columns': 12, 22 | '$enable-grid-classes': true, 23 | }; 24 | 25 | // / Grid system 26 | 27 | /** 28 | * @public 29 | * @description Generate semantic grid columns with these mixins. 30 | * @param enableGridClasses {boolean} [enableGridClasses=true] - Enable grid system 31 | * @param gridGutterWidth {string} [gridGutterWidth=30px] - margin between each grid 32 | * @returns {string} 33 | */ 34 | export function makeContainer(enableGridClasses = defaultProps['$enable-grid-classes'], gridGutterWidth = defaultProps['$grid-gutter-width']) { 35 | return enableGridClasses ? ` 36 | width: 100%; 37 | padding-right: calc(${gridGutterWidth} / 2); 38 | padding-left: calc(${gridGutterWidth} / 2); 39 | margin-right: auto; 40 | margin-left: auto; 41 | ` : ''; 42 | } 43 | 44 | 45 | /** 46 | * @public 47 | * @description For each breakpoint, define the maximum width of the container in a media query 48 | * @param enableGridClasses {boolean} [enableGridClasses=true] - Enable grid system 49 | * @param maxWidths {Object} [maxWidth={ 50 | sm: '540px', 51 | md: '720px', 52 | lg: '960px', 53 | xl: '1140px', 54 | }] - Container max widths 55 | * @param breakpoints {Object} [breakpoints={ 56 | xs: '0', 57 | sm: '576px', 58 | md: '768px', 59 | lg: '992px', 60 | xl: '1200px', 61 | }] - Application media breakpoints 62 | * @returns {string} 63 | */ 64 | export function makeContainerMaxWidths(enableGridClasses = defaultProps['$enable-grid-classes'], maxWidths = defaultProps['$container-max-widths'], breakpoints = defaultProps['$grid-breakpoints']) { 65 | return enableGridClasses ? Object.keys(breakpoints) 66 | .map((bp) => maxWidths[bp] ? mediaBreakpointUp(bp, breakpoints, `max-width: ${maxWidths[bp]};`) : '') 67 | .join('\n') : ''; 68 | } 69 | 70 | /** 71 | * @private 72 | * @description Default common css 73 | * @param enableGridClasses {boolean} [enableGridClasses=true] - Enable grid system 74 | * @param gridGutterWidth {string} [gridGutterWidth=30px] - margin between each grid 75 | * @returns {string} 76 | */ 77 | export function makeRow(enableGridClasses = defaultProps['$enable-grid-classes'], gridGutterWidth = defaultProps['$grid-gutter-width']) { 78 | return enableGridClasses ? ` 79 | display: flex; 80 | flex-wrap: wrap; 81 | margin-right: calc(${gridGutterWidth} / -2); 82 | margin-left: calc(${gridGutterWidth} / -2); 83 | ` : ''; 84 | } 85 | 86 | /** 87 | * @private 88 | * @description Default css 89 | * @param gridGutterWidth 90 | * @returns {string} 91 | */ 92 | export function makeColReady(gridGutterWidth = defaultProps['$grid-gutter-width']) { 93 | // Prevent columns from becoming too narrow when at smaller grid tiers by 94 | // always setting `width: 100%;`. This works because we use `flex` values 95 | // later on to override this initial width. 96 | return ` 97 | position: relative; 98 | width: 100%; 99 | min-height: 1px; // Prevent collapsing 100 | padding-right: calc(${gridGutterWidth} / 2); 101 | padding-left: calc(${gridGutterWidth} / 2); 102 | `; 103 | } 104 | 105 | /** 106 | * @private 107 | * @description Create max-width and flex position 108 | * @param {number} [size=0] 109 | * @param {number} [columns=12] - number of column using $grid-columns variable 110 | * @returns {string} max-width and flex css rules 111 | */ 112 | export function makeCol(size = 0, columns = defaultProps['$grid-columns']) { 113 | // Add a `max-width` to ensure content within each column does not blow out 114 | // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari 115 | // do not appear to require this. 116 | return ` 117 | flex: 0 0 ${toPercent(size, columns)}; 118 | max-width: ${toPercent(size, columns)}; 119 | `; 120 | } 121 | 122 | /** 123 | * @private 124 | * @description Create margin-left offset from size 125 | * @param {number} [size=0] 126 | * @param {number} [columns=12] - number of column using $grid-columns variable 127 | * @returns {string} margin-left css rule 128 | */ 129 | export function makeColOffset(size = 0, columns = defaultProps['$grid-columns']) { 130 | return `margin-left: ${toPercent(size, columns)};`; 131 | } 132 | 133 | export default { 134 | makeRow, 135 | makeContainer, 136 | makeContainerMaxWidths, 137 | }; 138 | -------------------------------------------------------------------------------- /src/hover.js: -------------------------------------------------------------------------------- 1 | import MixinError from './MixinError'; 2 | 3 | export const defaultProps = { 4 | '$enable-hover-media-query': false, 5 | }; 6 | 7 | /** 8 | * @public Css helper for hovering. 9 | * @description 10 | * @param {string} content 11 | * @returns {string} 12 | */ 13 | export function hover(content) { 14 | if (!content) throw new MixinError('content is required'); 15 | // TODO: re-enable along with mq4-hover-shim 16 | // @if $enable-hover-media-query { 17 | // // See Media Queries Level 4: https://drafts.csswg.org/mediaqueries/#hover 18 | // // Currently shimmed by https://github.com/twbs/mq4-hover-shim 19 | // @media (hover: hover) { 20 | // &:hover { @content } 21 | // } 22 | // } 23 | // @else { 24 | return `&:hover, &.hover { ${content} }`; 25 | } 26 | 27 | /** 28 | * @public Css helper for focus and hovering. 29 | * @description 30 | * @param {boolean} enableHoverMediaQuery 31 | * @param {string} content 32 | * @returns {string} 33 | */ 34 | export function hoverFocus(enableHoverMediaQuery = defaultProps['$enable-hover-media-query'], content) { 35 | if (enableHoverMediaQuery) { 36 | return ` 37 | &:focus, &.focus { ${content} } 38 | ${hover(content)} 39 | `; 40 | } 41 | return ` 42 | &:focus, 43 | &.focus, 44 | &:hover, 45 | &.hover { 46 | ${content} 47 | } 48 | `; 49 | } 50 | 51 | /** 52 | * @public Css helper for plain focus and hovering. 53 | * @description 54 | * @param {boolean} enableHoverMediaQuery 55 | * @param {string} content 56 | * @returns {string} 57 | */ 58 | export function plainHoverFocus(enableHoverMediaQuery = defaultProps['$enable-hover-media-query'], content) { 59 | if (enableHoverMediaQuery) { 60 | return ` 61 | &, 62 | &:focus, 63 | &.focus { 64 | ${content} 65 | } 66 | ${hover(content)} 67 | `; 68 | } 69 | return ` 70 | &, 71 | &:focus, 72 | &.focus, 73 | &:hover, 74 | &.hover { 75 | ${content} 76 | } 77 | `; 78 | } 79 | 80 | /** 81 | * @public Css helper for focus and active. 82 | * @description 83 | * @param {boolean} enableHoverMediaQuery 84 | * @param {string} content 85 | * @returns {string} 86 | */ 87 | export function hoverFocusActive(enableHoverMediaQuery = defaultProps['$enable-hover-media-query'], content) { 88 | if (enableHoverMediaQuery) { 89 | return ` 90 | &:focus, 91 | &.focus, 92 | &:active, 93 | &.active { 94 | ${content} 95 | } 96 | ${hover(content)} 97 | `; 98 | } 99 | return ` 100 | &:focus, 101 | &.focus, 102 | &:active, 103 | &.active, 104 | &:hover, 105 | &.hover { 106 | ${content} 107 | } 108 | `; 109 | } 110 | 111 | 112 | hover.focus = hoverFocus; 113 | hover.plainFocus = plainHoverFocus; 114 | hover.activeFocus = hoverFocusActive; 115 | 116 | export default { 117 | defaultProps, 118 | hover, 119 | hoverFocus, 120 | plainHoverFocus, 121 | hoverFocusActive, 122 | }; 123 | -------------------------------------------------------------------------------- /src/image.js: -------------------------------------------------------------------------------- 1 | // Image Mixins 2 | // - Responsive image 3 | // - Retina image 4 | 5 | 6 | // Responsive image 7 | // 8 | // Keep images from scaling beyond the width of their parents. 9 | 10 | export function imgFluid() { 11 | return ` 12 | /* Part 1: Set a maximum relative to the parent */ 13 | max-width: 100%; 14 | /* Part 2: Override the height to auto, otherwise images will be stretched */ 15 | /* when setting a width and height attribute on the img element. */ 16 | height: auto; 17 | `; 18 | } 19 | 20 | 21 | // Retina image 22 | // 23 | // Short retina mixin for setting background-image and -size. 24 | export function imgRetina(file1x, file2x, width1x, height1x) { 25 | return ` 26 | background-image: url(${file1x}); 27 | 28 | /* Autoprefixer takes care of adding -webkit-min-device-pixel-ratio and -o-min-device-pixel-ratio, */ 29 | /* but doesn't convert dppx=>dpi. */ 30 | /* There's no such thing as unprefixed min-device-pixel-ratio since it's nonstandard. */ 31 | /* Compatibility info: http://caniuse.com/#feat=css-media-resolution */ 32 | @media only screen and (min-resolution: 192dpi), /* IE9-11 don't support dppx */ 33 | only screen and (min-resolution: 2dppx) { /* Standardized */ 34 | background-image: url(${file2x}); 35 | background-size: ${width1x} ${height1x}; 36 | } 37 | `; 38 | } 39 | 40 | export default { 41 | imgFluid, 42 | imgRetina, 43 | }; 44 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // mixins 2 | export { default as aMixins } from './a'; 3 | export { default as alertMixins } from './alert'; 4 | export { default as backgroundVariantMixins } from './background-variant'; 5 | export { default as badgeMixins } from './badge'; 6 | export { default as radius } from './border-radius'; 7 | export { boxShadow } from './box-shadow'; 8 | export { default as bp } from './breakpoints'; 9 | export { default as buttonsMixins } from './buttons'; 10 | export { default as buttonGroupMixins } from './buttonGroup'; 11 | export { default as cardsMixins } from './cards'; 12 | export { clearfix } from './clearfix'; 13 | export { ifElse, ifThen } from './conditional'; 14 | export { default as floatMixins } from './float'; 15 | export { default as formsMixins } from './forms'; 16 | export { default as customformsMixins } from './customForms'; 17 | export { default as gradient } from './gradients'; 18 | export { default as gridMixins } from './grid'; 19 | export { default as gridFrameworkMixins } from './grid-framework'; 20 | export { hover } from './hover'; 21 | export { default as listGroupMixins } from './list-group'; 22 | export { default as listsMixins } from './lists'; 23 | export { default as navMixins } from './nav'; 24 | export { default as navbarMixins } from './navbar'; 25 | export { default as navDividerMixins } from './nav-divider'; 26 | export { default as navbarAlignMixins } from './navbar-align'; 27 | export { default as navbarToggleableMixins } from './navbar-toggleable'; 28 | export { default as paginationsMixins } from './paginations'; 29 | export { default as progressMixins } from './progress'; 30 | export { default as resetFilterMixins } from './reset-filter'; 31 | export { default as resetTextMixins } from './reset-text'; 32 | export { default as resizeMixins } from './resize'; 33 | export { srOnly, srOnlyFocusable } from './screen-reader'; 34 | export { size } from './size'; 35 | export { default as tabFocusMixins } from './tab-focus'; 36 | export { default as tableRowMixins } from './table-row'; 37 | export { default as textEmphasisMixins } from './text-emphasis'; 38 | export { default as textHideMixins } from './text-hide'; 39 | export { textTruncate } from './text-truncate'; 40 | export { transition } from './transition'; 41 | export { default as typographyMixins } from './typography'; 42 | export { generateUtility } from './utilities'; 43 | export { invisible } from './visibility'; 44 | // extra 45 | export { default as unit } from '@bootstrap-styled/utils/lib/unitUtils'; 46 | -------------------------------------------------------------------------------- /src/list-group.js: -------------------------------------------------------------------------------- 1 | import color from '@bootstrap-styled/color'; 2 | import { plainHoverFocus, hoverFocus } from './hover'; 3 | 4 | export const defaultProps = { 5 | '$enable-hover-media-query': false, 6 | }; 7 | 8 | /** 9 | * @public 10 | * @description Basic css helper for different colored ListGroupItem components. 11 | * @param {boolean} enableHoverMediaQuery 12 | * @param {string} state 13 | * @param {string} background 14 | * @param {string} listColor 15 | * @returns {string} 16 | */ 17 | export function listGroupItemVariant(enableHoverMediaQuery = defaultProps['$enable-hover-media-query'], state, background, listColor) { 18 | return ` 19 | & .list-group-item-${state} { 20 | color: ${listColor}; 21 | background-color: ${background}; 22 | } 23 | 24 | & a.list-group-item-${state}, 25 | button.list-group-item-${state} { 26 | color: ${listColor}; 27 | 28 | .list-group-item-heading { 29 | color: inherit; 30 | } 31 | 32 | ${hoverFocus(enableHoverMediaQuery, ` 33 | color: ${listColor}; 34 | background-color: ${color(background).darken(0.05).toString()}; 35 | `)} 36 | 37 | &.active { 38 | ${plainHoverFocus(enableHoverMediaQuery, ` 39 | color: #fff; 40 | background-color: ${listColor}; 41 | border-color: ${listColor}; 42 | `)} 43 | } 44 | } 45 | `; 46 | } 47 | 48 | export default { 49 | defaultProps, 50 | listGroupItemVariant, 51 | }; 52 | -------------------------------------------------------------------------------- /src/lists.js: -------------------------------------------------------------------------------- 1 | export const defaultProps = { 2 | '$list-inline-padding': '5px', 3 | }; 4 | 5 | /** 6 | * @public 7 | * @description Unstyled keeps list items block level, just removes default browser padding and list-style. 8 | * @returns {string} 9 | */ 10 | export function listUnstyled() { 11 | return ` 12 | padding-left: 0; 13 | list-style: none; 14 | `; 15 | } 16 | 17 | export function listInline() { 18 | return listUnstyled(); 19 | } 20 | 21 | /** 22 | * @public 23 | * @description Inline list and removes margin for last child. 24 | * @param listInlinePadding 25 | * @returns {string} 26 | */ 27 | export function listInlineItem(listInlinePadding = defaultProps['$list-inline-padding']) { 28 | return ` 29 | display: inline-block; 30 | 31 | &:not(:last-child) { 32 | margin-right: ${listInlinePadding}; 33 | } 34 | `; 35 | } 36 | export default { 37 | defaultProps, 38 | listInline, 39 | listUnstyled, 40 | }; 41 | -------------------------------------------------------------------------------- /src/media.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @public 3 | * @description Basic css helper for Media components. 4 | * @returns {string} 5 | */ 6 | export function media() { 7 | return ` 8 | &.media { 9 | display: flex; 10 | align-items: flex-start; 11 | } 12 | 13 | & .media-body { 14 | flex: 1; 15 | } 16 | `; 17 | } 18 | 19 | export default { 20 | media, 21 | }; 22 | -------------------------------------------------------------------------------- /src/nav-divider.js: -------------------------------------------------------------------------------- 1 | import unitUtils from '@bootstrap-styled/utils/lib/unitUtils'; 2 | 3 | export const defaultProps = { 4 | '$spacer-y': '1rem', 5 | }; 6 | 7 | // Horizontal dividers 8 | // 9 | // Dividers (basically an hr) within dropdowns and nav lists 10 | /** 11 | * @public 12 | * @description Dividers for certain components (Dropdown, Nav, List, ...). 13 | * @param {string} spacerY 14 | * @param {string} dividerColor 15 | * @returns {string} 16 | */ 17 | export function navDivider(spacerY = defaultProps['$spacer-y'], dividerColor = '#e5e5e5') { 18 | const marginY = `${unitUtils.rmUnit(spacerY, unitUtils.UNIT.REM) / 2}${unitUtils.UNIT.REM}`; 19 | return ` 20 | height: 1px; 21 | margin: calc(${marginY} / 2) 0; 22 | overflow: hidden; 23 | background-color: ${dividerColor}; 24 | `; 25 | } 26 | 27 | export default { 28 | defaultProps, 29 | navDivider, 30 | }; 31 | -------------------------------------------------------------------------------- /src/nav.js: -------------------------------------------------------------------------------- 1 | import { hoverFocus } from './hover'; 2 | import { borderRadius, borderTopRadius } from './border-radius'; 3 | 4 | export const defaultProps = { 5 | '$enable-rounded': true, 6 | '$enable-hover-media-query': false, 7 | '$nav-link-padding': '.5em 1em', 8 | '$nav-disabled-link-color': '#636c72', 9 | '$cursor-disabled': 'not-allowed', 10 | '$nav-tabs-border-width': '1px', 11 | '$nav-tabs-border-color': '#ddd', 12 | '$nav-tabs-border-radius': '.25rem', 13 | '$nav-tabs-link-hover-border-color': '#eceeef', 14 | '$nav-tabs-active-link-hover-color': '#464a4c', 15 | '$nav-tabs-active-link-hover-bg': '#fff', 16 | '$nav-tabs-active-link-hover-border-color': '#ddd', 17 | '$nav-pills-border-radius': '.25rem', 18 | '$nav-pills-active-link-color': '#fff', 19 | '$nav-pills-active-link-bg': '#0275d8', 20 | }; 21 | 22 | export function nav( 23 | $enableRounded = defaultProps['$enable-rounded'], 24 | $enableHoverMediaQuery = defaultProps['$enable-hover-media-query'], 25 | $navLinkPadding = defaultProps['$nav-link-padding'], 26 | $navDisabledLinkColor = defaultProps['$nav-disabled-link-color'], 27 | $cursorDisabled = defaultProps['$cursor-disabled'], 28 | $navTabBorderWidth = defaultProps['$nav-tabs-border-width'], 29 | $navTabsBorderColor = defaultProps['$nav-tabs-border-color'], 30 | $navTabsBorderRadius = defaultProps['$nav-tabs-border-radius'], 31 | $navTabsLinkHoverBorderColor = defaultProps['$nav-tabs-link-hover-border-color'], 32 | $navTabsActiveLinkHoverColor = defaultProps['$nav-tabs-active-link-hover-color'], 33 | $navTabsActiveLinkHoverBg = defaultProps['$nav-tabs-active-link-hover-bg'], 34 | $navTabsActiveLinkHoverBorderColor = defaultProps['$nav-tabs-active-link-hover-border-color'], 35 | $navPillsBorderRadius = defaultProps['$nav-pills-border-radius'], 36 | $navPillsActiveLinkColor = defaultProps['$nav-pills-active-link-color'], 37 | $navPillsActiveLinkBg = defaultProps['$nav-pills-active-link-bg'], 38 | ) { 39 | return ` 40 | &.nav { 41 | display: flex; 42 | padding-left: 0; 43 | margin-bottom: 0; 44 | list-style: none; 45 | } 46 | 47 | & .nav-link { 48 | display: block; 49 | padding: ${$navLinkPadding}; 50 | ${hoverFocus($enableHoverMediaQuery, 'text-decoration: none;')} 51 | /* Disabled state lightens text and removes hover tab effects */ 52 | &.disabled { 53 | color: ${$navDisabledLinkColor}; 54 | cursor: ${$cursorDisabled}; 55 | } 56 | } 57 | 58 | /* 59 | Tabs 60 | */ 61 | 62 | &.nav-tabs { 63 | border-bottom: ${$navTabBorderWidth} solid ${$navTabsBorderColor}; 64 | & .nav-item { 65 | margin-bottom: -${$navTabBorderWidth}; 66 | } 67 | 68 | & .nav-link { 69 | border: ${$navTabBorderWidth} solid transparent; 70 | ${borderTopRadius($enableRounded, $navTabsBorderRadius)} 71 | ${hoverFocus($enableHoverMediaQuery, ` 72 | border-color: ${$navTabsLinkHoverBorderColor} ${$navTabsLinkHoverBorderColor} ${$navTabsBorderColor}; 73 | `)} 74 | 75 | &.disabled { 76 | color: ${$navDisabledLinkColor}; 77 | background-color: transparent; 78 | border-color: transparent; 79 | } 80 | } 81 | 82 | & .nav-link.active, 83 | .nav-item.open .nav-link { 84 | color: ${$navTabsActiveLinkHoverColor}; 85 | background-color: ${$navTabsActiveLinkHoverBg}; 86 | border-color: ${$navTabsActiveLinkHoverBorderColor} ${$navTabsActiveLinkHoverBorderColor} transparent; 87 | } 88 | 89 | & .dropdown-menu { 90 | /* Make dropdown border overlap tab border */ 91 | margin-top: -${$navTabBorderWidth}; 92 | /* Remove the top rounded corners here since there is a hard edge above the menu */ 93 | ${borderTopRadius($enableRounded, '0')} 94 | } 95 | } 96 | 97 | /* 98 | Pills 99 | */ 100 | 101 | &.nav-pills { 102 | .nav-link { 103 | ${borderRadius($enableRounded, $navPillsBorderRadius)} 104 | } 105 | 106 | .nav-link.active, 107 | .nav-item.show .nav-link { 108 | color: ${$navPillsActiveLinkColor}; 109 | background-color: ${$navPillsActiveLinkBg}; 110 | } 111 | } 112 | 113 | /* 114 | Justified variants 115 | */ 116 | 117 | &.nav-fill { 118 | .nav-item { 119 | flex: 1 1 auto; 120 | text-align: center; 121 | } 122 | } 123 | 124 | &.nav-justified { 125 | .nav-item { 126 | flex: 1 1 100%; 127 | text-align: center; 128 | } 129 | } 130 | 131 | /* Hide tabbable panes to start, show them when .active */ 132 | &.tab-content { 133 | > .tab-pane { 134 | display: none; 135 | } 136 | > .active { 137 | display: block; 138 | } 139 | } 140 | `; 141 | } 142 | 143 | export default { 144 | nav, 145 | }; 146 | -------------------------------------------------------------------------------- /src/navbar-align.js: -------------------------------------------------------------------------------- 1 | import unitUtils from '@bootstrap-styled/utils/lib/unitUtils'; 2 | 3 | export const defaultProps = { 4 | '$navbar-height': '50px', 5 | }; 6 | 7 | /** 8 | * @public 9 | * @description Vertically center elements in the navbar depending on the value of its height. 10 | * @param {string} navbarHeight 11 | * @param {string} elementHeight 12 | * @returns {string} 13 | */ 14 | export function navbarVerticalAlign(navbarHeight = defaultProps['$navbar-height'], elementHeight) { 15 | const marginTop = `${(unitUtils.rmUnit(navbarHeight, unitUtils.UNIT.PX) - unitUtils.rmUnit(elementHeight, unitUtils.UNIT.PX)) / 2}${unitUtils.UNIT.PX}`; 16 | const marginBottom = `${(unitUtils.rmUnit(navbarHeight, unitUtils.UNIT.PX) - unitUtils.rmUnit(elementHeight, unitUtils.UNIT.PX)) / 2}${unitUtils.UNIT.PX}`; 17 | return ` 18 | margin-top: ${marginTop}; 19 | margin-bottom: ${marginBottom}; 20 | `; 21 | } 22 | 23 | export default { 24 | defaultProps, 25 | navbarVerticalAlign, 26 | }; 27 | -------------------------------------------------------------------------------- /src/navbar-toggleable.js: -------------------------------------------------------------------------------- 1 | import { 2 | breakpointNext, mediaBreakpointDown, mediaBreakpointUp, breakpointInfix, 3 | } from './breakpoints'; 4 | 5 | export const defaultProps = { 6 | '$grid-breakpoints': { 7 | xs: '0', 8 | sm: '576px', 9 | md: '768px', 10 | lg: '992px', 11 | xl: '1200px', 12 | }, 13 | }; 14 | 15 | export function navbarToggleable(gridBreakpoints = defaultProps['$grid-breakpoints']) { 16 | const navbarBreakpointList = []; 17 | Object.keys(gridBreakpoints).forEach((breakpoint) => { 18 | const next = breakpointNext(breakpoint, gridBreakpoints); 19 | const infix = breakpointInfix(breakpoint, gridBreakpoints); 20 | 21 | const navbarBreakpoint = ` 22 | &.navbar-toggleable${infix} { 23 | ${mediaBreakpointDown(breakpoint, gridBreakpoints, ` 24 | .navbar-nav { 25 | .dropdown-menu { 26 | position: static; 27 | float: none; 28 | } 29 | } 30 | 31 | > .container { 32 | padding-right: 0; 33 | padding-left: 0; 34 | } 35 | `)} 36 | ${mediaBreakpointUp(next, gridBreakpoints, ` 37 | flex-direction: row; 38 | flex-wrap: nowrap; 39 | align-items: center; 40 | 41 | .navbar-nav { 42 | flex-direction: row; 43 | 44 | .nav-link { 45 | padding-right: .5rem; 46 | padding-left: .5rem; 47 | } 48 | } 49 | 50 | /* For nesting containers, have to redeclare for alignment purposes */ 51 | > .container { 52 | display: flex; 53 | flex-wrap: nowrap; 54 | align-items: center; 55 | } 56 | 57 | .navbar-collapse { 58 | display: flex !important; 59 | width: 100%; 60 | 61 | } 62 | 63 | .navbar-toggler { 64 | display: none; 65 | } 66 | `)} 67 | } 68 | `; 69 | navbarBreakpointList.push(navbarBreakpoint); 70 | }); 71 | return ` 72 | ${navbarBreakpointList.join('\n')} 73 | `; 74 | } 75 | 76 | export default { 77 | defaultProps, 78 | navbarToggleable, 79 | }; 80 | -------------------------------------------------------------------------------- /src/paginations.js: -------------------------------------------------------------------------------- 1 | import { hoverFocus } from './hover'; 2 | import { borderLeftRadius, borderRightRadius, borderRadius } from './border-radius'; 3 | 4 | export const defaultProps = { 5 | '$enable-rounded': true, 6 | '$enable-hover-media-query': false, 7 | '$border-radius': '.25rem', 8 | '$pagination-active-color': '#fff', 9 | '$pagination-active-bg': '#0275d8', 10 | '$pagination-active-border': '#0275d8', 11 | '$pagination-disabled-color': '#636c72', 12 | '$cursor-disabled': 'not-allowed', 13 | '$pagination-disabled-bg': '#fff', 14 | '$pagination-disabled-border': '#ddd', 15 | '$pagination-padding-y': '.5rem', 16 | '$pagination-padding-x': '.75rem', 17 | '$pagination-line-height': '1.25', 18 | '$pagination-color': '#0275d8', 19 | '$pagination-bg': '#fff', 20 | '$pagination-border-width': '1px', 21 | '$pagination-border-color': '#ddd', 22 | '$pagination-hover-color': 'hsl(207.79999999999995, 98.2%, 27.8%)', 23 | '$pagination-hover-bg': '#eceeef', 24 | '$pagination-hover-border': '#ddd', 25 | '$pagination-padding-y-lg': '.75rem', 26 | '$pagination-padding-x-lg': '1.5rem', 27 | '$font-size-lg': '1.25rem', 28 | '$line-height-lg': '1.3', 29 | '$border-radius-lg': '.3rem', 30 | '$pagination-padding-y-sm': '.25rem', 31 | '$pagination-padding-x-sm': '.5rem', 32 | '$font-size-sm': '.875rem', 33 | '$line-height-sm': '1.5', 34 | '$border-radius-sm': '.2rem', 35 | }; 36 | 37 | export const paginationSize = (enableRounded = defaultProps['$enable-rounded'], paddingY, paddingX, fontSize, borderRadiusPagination) => ` 38 | .page-link { 39 | padding: ${paddingY} ${paddingX}; 40 | font-size: ${fontSize}; 41 | } 42 | 43 | .page-item { 44 | &:first-child { 45 | .page-link { 46 | ${borderLeftRadius(enableRounded, borderRadiusPagination)} 47 | } 48 | } 49 | &:last-child { 50 | .page-link { 51 | ${borderRightRadius(enableRounded, borderRadiusPagination)} 52 | } 53 | } 54 | } 55 | `; 56 | 57 | export function pagination( 58 | $enableRounded = defaultProps['$enable-rounded'], 59 | $enableHoverMediaQuery = defaultProps['$enable-hover-media-query'], 60 | $borderRadius = defaultProps['$border-radius'], 61 | $paginationActiveColor = defaultProps['$pagination-active-color'], 62 | $paginationActiveBg = defaultProps['$pagination-active-bg'], 63 | $paginationActiveBorder = defaultProps['$pagination-active-border'], 64 | $paginationDisabledColor = defaultProps['$pagination-disabled-color'], 65 | $cursorDisabled = defaultProps['$cursor-disabled'], 66 | $paginationDisabledBg = defaultProps['$pagination-disabled-bg'], 67 | $paginationDisabledBorder = defaultProps['$pagination-disabled-border'], 68 | $paginationPaddingY = defaultProps['$pagination-padding-y'], 69 | $paginationPaddingX = defaultProps['$pagination-padding-x'], 70 | $paginationLineHeight = defaultProps['$pagination-line-height'], 71 | $paginationColor = defaultProps['$pagination-color'], 72 | $paginationBg = defaultProps['$pagination-bg'], 73 | $paginationBorderWidth = defaultProps['$pagination-border-width'], 74 | $paginationBorderColor = defaultProps['$pagination-border-color'], 75 | $paginationHoverColor = defaultProps['$pagination-hover-color'], 76 | $paginationHoverBg = defaultProps['$pagination-hover-bg'], 77 | $paginationHoverBorder = defaultProps['$pagination-hover-border'], 78 | $paginationPaddingYLg = defaultProps['$pagination-padding-y-lg'], 79 | $paginationPaddingXLg = defaultProps['$pagination-padding-x-lg'], 80 | $fontSizeLg = defaultProps['$font-size-lg'], 81 | $lineHeightLg = defaultProps['$line-height-lg'], 82 | $borderRadiusLg = defaultProps['$border-radius-lg'], 83 | $paginationPaddingYSm = defaultProps['$pagination-padding-y-sm'], 84 | $paginationPaddingXSm = defaultProps['$pagination-padding-x-sm'], 85 | $fontSizeSm = defaultProps['$font-size-sm'], 86 | $lineHeightSm = defaultProps['$line-height-sm'], 87 | $borderRadiusSm = defaultProps['$border-radius-sm'], 88 | ) { 89 | return ` 90 | &.pagination { 91 | display: flex; 92 | padding-left: 0; 93 | list-style: none; 94 | ${borderRadius($enableRounded)} 95 | } 96 | 97 | & .page-item { 98 | &:first-child { 99 | .page-link { 100 | margin-left: 0; 101 | ${borderLeftRadius($enableRounded, $borderRadius)} 102 | } 103 | } 104 | &:last-child { 105 | .page-link { 106 | ${borderRightRadius($enableRounded, $borderRadius)} 107 | } 108 | } 109 | 110 | &.active .page-link { 111 | z-index: 2; 112 | color: ${$paginationActiveColor}; 113 | background-color: ${$paginationActiveBg}; 114 | border-color: ${$paginationActiveBorder}; 115 | } 116 | 117 | &.disabled .page-link { 118 | color: ${$paginationDisabledColor}; 119 | pointer-events: none; 120 | cursor: ${$cursorDisabled}; 121 | background-color: ${$paginationDisabledBg}; 122 | border-color: ${$paginationDisabledBorder}; 123 | } 124 | } 125 | 126 | & .page-link { 127 | position: relative; 128 | display: block; 129 | padding: ${$paginationPaddingY} ${$paginationPaddingX}; 130 | margin-left: -1px; 131 | line-height: ${$paginationLineHeight}; 132 | color: ${$paginationColor}; 133 | background-color: ${$paginationBg}; 134 | border: ${$paginationBorderWidth} solid ${$paginationBorderColor}; 135 | 136 | ${hoverFocus($enableHoverMediaQuery, ` 137 | color: ${$paginationHoverColor}; 138 | text-decoration: none; 139 | background-color: ${$paginationHoverBg}; 140 | border-color: ${$paginationHoverBorder}; 141 | `)} 142 | } 143 | 144 | /* Sizing */ 145 | &.pagination-lg { 146 | ${paginationSize( 147 | $enableRounded, 148 | $paginationPaddingYLg, 149 | $paginationPaddingXLg, 150 | $fontSizeLg, 151 | $lineHeightLg, 152 | $borderRadiusLg 153 | )} 154 | } 155 | 156 | &.pagination-sm { 157 | ${paginationSize( 158 | $enableRounded, 159 | $paginationPaddingYSm, 160 | $paginationPaddingXSm, 161 | $fontSizeSm, 162 | $lineHeightSm, 163 | $borderRadiusSm 164 | )} 165 | } 166 | `; 167 | } 168 | 169 | export default { 170 | defaultProps, 171 | paginationSize, 172 | pagination, 173 | }; 174 | -------------------------------------------------------------------------------- /src/progress.js: -------------------------------------------------------------------------------- 1 | export function progressVariant(bgColor) { 2 | return ` 3 | &[value]::-webkit-progress-value { 4 | background-color: ${bgColor}; 5 | } 6 | 7 | &[value]::-moz-progress-bar { 8 | background-color: ${bgColor}; 9 | } 10 | 11 | /* IE10+, Microsoft Edge */ 12 | &[value]::-ms-fill { 13 | background-color: ${bgColor}; 14 | } 15 | 16 | /* IE9 */ 17 | @media screen and (min-width:0\\0) { 18 | .progress-bar { 19 | background-color: ${bgColor}; 20 | } 21 | } 22 | `; 23 | } 24 | 25 | export default { 26 | progressVariant, 27 | }; 28 | -------------------------------------------------------------------------------- /src/regex.js: -------------------------------------------------------------------------------- 1 | // this regex will return an array of linear gradient color values when doing $var.match(linearGradientRe) 2 | export const linearGradientRe = /#[0-9a-fA-F]{3,6}|rgb ?\([ 0-9.%,]+?\)/g; 3 | -------------------------------------------------------------------------------- /src/reset-filter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @public 3 | * @description When you need to remove a gradient background, do not forget to use this to reset the IE filter for IE9. 4 | * @returns {string} 5 | */ 6 | export function resetFilter() { 7 | return ` 8 | filter: "progid:DXImageTransform.Microsoft.gradient(enabled = false)"; 9 | `; 10 | } 11 | 12 | export default { 13 | resetFilter, 14 | }; 15 | -------------------------------------------------------------------------------- /src/reset-text.js: -------------------------------------------------------------------------------- 1 | export const defaultProps = { 2 | '$font-family-base': true, 3 | '$font-weight-normal': true, 4 | '$line-height-base': true, 5 | }; 6 | 7 | export function resetText(fontFamilyBase = defaultProps['$font-family-base'], fontWeightNormal = defaultProps['$font-weight-normal'], lineHeightBase = defaultProps['$line-height-base']) { 8 | return ` 9 | font-family: ${fontFamilyBase}; 10 | /* We deliberately do NOT reset font-size or word-wrap. */ 11 | font-style: normal; 12 | font-weight: ${fontWeightNormal}; 13 | letter-spacing: normal; 14 | line-break: auto; 15 | line-height: ${lineHeightBase}; 16 | text-align: left; /* Fallback for where 'start' is not supported */ 17 | text-align: start; 18 | text-decoration: none; 19 | text-shadow: none; 20 | text-transform: none; 21 | white-space: normal; 22 | word-break: normal; 23 | word-spacing: normal; 24 | `; 25 | } 26 | 27 | export default { 28 | defaultProps, 29 | resetText, 30 | }; 31 | -------------------------------------------------------------------------------- /src/resize.js: -------------------------------------------------------------------------------- 1 | // Resize anything 2 | 3 | export function resizable(direction) { 4 | const available = ['horizontal', 'vertical', 'both']; 5 | if (available.indexOf(direction) === -1) { 6 | throw new Error(`Wrong resize value. Available are ${available.join(',')}`); 7 | } 8 | return ` 9 | resize: ${direction}; /* Options: horizontal, vertical, both */ 10 | overflow: auto; /* Per CSS3 UI, 'resize' only applies when 'overflow' isn't 'visible' */ 11 | `; 12 | } 13 | 14 | export default { 15 | resizable, 16 | }; 17 | -------------------------------------------------------------------------------- /src/screen-reader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @public 3 | * @description Only display content to screen readers. See: http://a11yproject.com/posts/how-to-hide-content 4 | * @returns {string} 5 | */ 6 | export function srOnly() { 7 | return ` 8 | position: absolute !important; 9 | width: 1px; 10 | height: 1px; 11 | padding: 0; 12 | margin: -1px; 13 | overflow: hidden; 14 | clip: rect(0,0,0,0); 15 | border: 0; 16 | `; 17 | } 18 | 19 | // Use in conjunction with .sr-only to only display content when it's focused. 20 | // 21 | // Useful for 'Skip to main content' links; see https://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 22 | // 23 | // Credit: HTML5 Boilerplate 24 | 25 | /** 26 | * @public 27 | * @description Use in conjunction with .sr-only to only display content when it's focused. Useful for 'Skip to main content' links; see https://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 28 | * @returns {string} 29 | */ 30 | export function srOnlyFocusable() { 31 | return ` 32 | &:active, 33 | &:focus { 34 | position: static; 35 | width: auto; 36 | height: auto; 37 | margin: 0; 38 | overflow: visible; 39 | clip: auto; 40 | } 41 | `; 42 | } 43 | 44 | export default { 45 | srOnly, 46 | srOnlyFocusable, 47 | }; 48 | -------------------------------------------------------------------------------- /src/size.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @public 3 | * @decription Sets both width and height. 4 | * @param {string} width 5 | * @param {string} height If unspecified will use width value by default. 6 | * @returns {string} 7 | */ 8 | export function size(width, height = width) { 9 | return ` 10 | width: ${width}; 11 | height: ${height}; 12 | `; 13 | } 14 | 15 | export default { 16 | size, 17 | }; 18 | -------------------------------------------------------------------------------- /src/tab-focus.js: -------------------------------------------------------------------------------- 1 | // WebKit-style focus 2 | 3 | export function tabFocus() { 4 | return ` 5 | /* WebKit-specific. Other browsers will keep their default outline style. */ 6 | /* (Initially tried to also force default via 'outline: initial', */ 7 | /* but that seems to erroneously remove the outline in Firefox altogether.) */ 8 | outline: 5px auto -webkit-focus-ring-color; 9 | outline-offset: -2px; 10 | `; 11 | } 12 | 13 | export default { 14 | tabFocus, 15 | }; 16 | -------------------------------------------------------------------------------- /src/table-row.js: -------------------------------------------------------------------------------- 1 | import color from '@bootstrap-styled/color'; 2 | import { hover } from './hover'; 3 | 4 | // Tables 5 | export function tableRowVariant(state, background) { 6 | const hoverBackground = color(background).darken(0.05).toString(); 7 | return ` 8 | /* Exact selectors below required to override '.table-striped' and prevent */ 9 | /* inheritance to nested tables. */ 10 | & .table-${state} { 11 | &, 12 | > th, 13 | > td { 14 | background-color: ${background}; 15 | } 16 | } 17 | 18 | /* Hover states for '.table-hover' */ 19 | /* Note: this is not available for cells or rows within 'thead' or 'tfoot'. */ 20 | &.table-hover { 21 | 22 | .table-${state} { 23 | ${hover(` 24 | background-color: ${hoverBackground}; 25 | 26 | > td, 27 | > th { 28 | background-color: ${hoverBackground}; 29 | } 30 | `)} 31 | } 32 | } 33 | `; 34 | } 35 | 36 | export default { 37 | tableRowVariant, 38 | }; 39 | -------------------------------------------------------------------------------- /src/tests/MixinError.test.js: -------------------------------------------------------------------------------- 1 | import MixinError from '../MixinError'; 2 | 3 | describe('MixinError', () => { 4 | it('should be throwable', () => { 5 | expect(() => { throw new MixinError('error'); }).toThrowError(new MixinError('error')); 6 | }); 7 | it('should have message', () => { 8 | const err = new MixinError('error'); 9 | expect(err.message).toEqual('error'); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /src/tests/a.test.js: -------------------------------------------------------------------------------- 1 | import { a, defaultProps } from '../a'; 2 | 3 | describe('bootstrap a mixin', () => { 4 | it('should return a a mixin css', () => { 5 | const css = a( 6 | defaultProps['$link-color'], 7 | defaultProps['$link-decoration'], 8 | defaultProps['$link-hover-color'], 9 | defaultProps['$link-hover-decoration'], 10 | defaultProps['$enable-hover-media-query'], 11 | ); 12 | expect(css).toContain('color: #0275d8;'); 13 | expect(css).toContain('text-decoration: none;'); 14 | expect(css).toContain('background-color: transparent;'); 15 | expect(css).toContain('-webkit-text-decoration-skip: objects;'); 16 | expect(css).toContain('&:focus,'); 17 | expect(css).toContain('&.focus,'); 18 | expect(css).toContain('&:hover,'); 19 | expect(css).toContain('&.hover {'); 20 | expect(css).toContain('color: #014C8D;'); 21 | expect(css).toContain('text-decoration: underline;'); 22 | expect(css).toContain('&:focus {'); 23 | expect(css).toContain('outline: 5px auto -webkit-focus-ring-color;'); 24 | expect(css).toContain('outline-offset: -2px;'); 25 | expect(css).toContain('a:not([href]):not([tabindex]) {'); 26 | expect(css).toContain('color: inherit;'); 27 | expect(css).toContain('text-decoration: none;'); 28 | expect(css).toContain('&:focus,'); 29 | expect(css).toContain('&.focus,'); 30 | expect(css).toContain('&:hover,'); 31 | expect(css).toContain('&.hover {'); 32 | expect(css).toContain('color: inherit;'); 33 | expect(css).toContain('text-decoration: none;'); 34 | expect(css).toContain('&:focus {'); 35 | expect(css).toContain('outline: 0;'); 36 | }); 37 | it('should return a a utility css by default', () => { 38 | const css = a(); 39 | expect(css).toContain('color: #0275d8;'); 40 | expect(css).toContain('text-decoration: none;'); 41 | expect(css).toContain('background-color: transparent;'); 42 | expect(css).toContain('-webkit-text-decoration-skip: objects;'); 43 | expect(css).toContain('&:focus,'); 44 | expect(css).toContain('&.focus,'); 45 | expect(css).toContain('&:hover,'); 46 | expect(css).toContain('&.hover {'); 47 | expect(css).toContain('color: #014C8D;'); 48 | expect(css).toContain('text-decoration: underline;'); 49 | expect(css).toContain('&:focus {'); 50 | expect(css).toContain('outline: 5px auto -webkit-focus-ring-color;'); 51 | expect(css).toContain('outline-offset: -2px;'); 52 | expect(css).toContain('a:not([href]):not([tabindex]) {'); 53 | expect(css).toContain('color: inherit;'); 54 | expect(css).toContain('text-decoration: none;'); 55 | expect(css).toContain('&:focus,'); 56 | expect(css).toContain('&.focus,'); 57 | expect(css).toContain('&:hover,'); 58 | expect(css).toContain('&.hover {'); 59 | expect(css).toContain('color: inherit;'); 60 | expect(css).toContain('text-decoration: none;'); 61 | expect(css).toContain('&:focus {'); 62 | expect(css).toContain('outline: 0;'); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /src/tests/alert.test.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable'; 2 | import { alertVariant } from '../alert'; 3 | 4 | describe('bootstrap alert mixins', () => { 5 | it('alertVariant should return a css', () => { 6 | const css = alertVariant('#fff', '#f00', '#0f0'); 7 | expect(css).not.toContain('undefined'); 8 | expect(css).not.toContain('null'); 9 | expect(fromJS({ css }).hashCode()).toEqual(-743377560); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /src/tests/background-variant.test.js: -------------------------------------------------------------------------------- 1 | import { defaultProps, bgVariant } from '../background-variant'; 2 | 3 | describe('bootstrap background-variant mixins', () => { 4 | it('bgVariant should return a css', () => { 5 | const css = bgVariant(defaultProps['$enable-hover-media-query'], '.toto', '#f00'); 6 | expect(css).not.toContain('undefined'); 7 | expect(css).not.toContain('null'); 8 | expect(css).toContain('.toto'); 9 | expect(css).toContain('background-color: #f00 !important;'); 10 | expect(css).toContain('a.toto'); 11 | expect(css).toContain('&:focus,'); 12 | expect(css).toContain('&.focus,'); 13 | expect(css).toContain('&:hover,'); 14 | expect(css).toContain('&.hover'); 15 | expect(css).toContain('background-color: rgb(204, 0, 0) !important;'); 16 | }); 17 | it('bgVariant should have parameters', () => { 18 | const css = bgVariant(!defaultProps['$enable-hover-media-query'], undefined, undefined); 19 | expect(css).toContain('undefined'); 20 | expect(css).toContain('background-color: undefined !important;'); 21 | expect(css).toContain('aundefined'); 22 | expect(css).toContain('&:focus,'); 23 | expect(css).toContain('&.focus'); 24 | expect(css).toContain('&:hover,'); 25 | expect(css).toContain('&.hover'); 26 | expect(css).toContain('background-color: rgb(0, 0, 0) !important;'); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /src/tests/badge.test.js: -------------------------------------------------------------------------------- 1 | import { defaultProps, badgeVariant } from '../badge'; 2 | 3 | describe('bootstrap badge mixins', () => { 4 | it('badgeVariant should return css without hover media query ', () => { 5 | const css = badgeVariant(defaultProps['$enable-hover-mediaQuery'], '#f00'); 6 | expect(css).toContain('background-color: #f00;'); 7 | expect(css).toContain('&[href] {'); 8 | expect(css).toContain('&:focus,'); 9 | expect(css).toContain('&.focus,'); 10 | expect(css).toContain('&:hover,'); 11 | expect(css).toContain('&.hover {'); 12 | expect(css).toContain('background-color: hsl(0, 100%, 45%);'); 13 | }); 14 | it('badgeVariant should return css with hover media query', () => { 15 | const css = badgeVariant(!defaultProps['$enable-hover-mediaQuery'], '#f00'); 16 | expect(css).toContain('&[href] {'); 17 | expect(css).toContain('&:focus, &.focus { background-color: hsl(0, 100%, 45%); }'); 18 | expect(css).toContain('&:hover, &.hover { background-color: hsl(0, 100%, 45%); }'); 19 | expect(css).toContain('}'); 20 | }); 21 | it('badgeVariant should return css by default ', () => { 22 | const css = badgeVariant(); 23 | expect(css).toContain('&[href] {'); 24 | expect(css).toContain('&:focus,'); 25 | expect(css).toContain('&.focus,'); 26 | expect(css).toContain('&:hover,'); 27 | expect(css).toContain('&.hover {'); 28 | expect(css).toContain('background-color: hsl(0, 0%, 0%);'); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /src/tests/border-radius.test.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable'; 2 | 3 | import { 4 | defaultProps, 5 | borderRadius, 6 | borderTopRadius, 7 | borderRightRadius, 8 | borderBottomRadius, 9 | borderLeftRadius, 10 | } from '../border-radius'; 11 | 12 | describe('bootstrap border-radius mixins', () => { 13 | it('borderRadius should return a css', () => { 14 | const css = borderRadius(defaultProps['$enable-rounded'], defaultProps['$border-radius']); 15 | expect(css).not.toContain('undefined'); 16 | expect(css).not.toContain('null'); 17 | if (defaultProps['$enable-rounded']) { 18 | expect(css).toEqual('\n border-radius: .25rem;\n '); 19 | } else { 20 | expect(css).toEqual(''); 21 | } 22 | }); 23 | it('borderRadius should have arguments', () => { 24 | const css = borderRadius(); 25 | expect(fromJS({ css }).hashCode()).toEqual(412224342); 26 | }); 27 | it('borderTopRadius should return a css', () => { 28 | const css = borderTopRadius(defaultProps['$enable-rounded'], defaultProps['$border-radius']); 29 | expect(css).not.toContain('undefined'); 30 | expect(css).not.toContain('null'); 31 | if (defaultProps['$enable-rounded']) { 32 | expect(css).toEqual('\n border-top-right-radius: .25rem;\n border-top-left-radius: .25rem;\n '); 33 | } else { 34 | expect(css).toEqual(''); 35 | } 36 | }); 37 | it('borderTopRadius should return a css by default', () => { 38 | const css = borderTopRadius(); 39 | expect(fromJS({ css }).hashCode()).toEqual(-805177024); 40 | }); 41 | it('borderRightRadius should return a css', () => { 42 | const css = borderRightRadius(defaultProps['$enable-rounded'], defaultProps['$border-radius']); 43 | expect(css).not.toContain('undefined'); 44 | expect(css).not.toContain('null'); 45 | if (defaultProps['$enable-rounded']) { 46 | expect(css).toEqual('\n border-bottom-right-radius: .25rem;\n border-top-right-radius: .25rem;\n '); 47 | } else { 48 | expect(css).toEqual(''); 49 | } 50 | }); 51 | it('borderRightRadius should return a css by default', () => { 52 | const css = borderRightRadius(); 53 | expect(fromJS({ css }).hashCode()).toEqual(-48434351); 54 | }); 55 | it('borderBottomRadius should return a css', () => { 56 | const css = borderBottomRadius(defaultProps['$enable-rounded'], defaultProps['$border-radius']); 57 | expect(css).not.toContain('undefined'); 58 | expect(css).not.toContain('null'); 59 | if (defaultProps['$enable-rounded']) { 60 | expect(css).toEqual('\n border-bottom-right-radius: .25rem;\n border-bottom-left-radius: .25rem;\n '); 61 | } else { 62 | expect(css).toEqual(''); 63 | } 64 | }); 65 | it('borderBottomRadius should return a css by default', () => { 66 | const css = borderBottomRadius(); 67 | expect(fromJS({ css }).hashCode()).toEqual(688610612); 68 | }); 69 | it('borderLeftRadius should return a css', () => { 70 | const css = borderLeftRadius(defaultProps['$enable-rounded'], defaultProps['$border-radius']); 71 | expect(css).not.toContain('undefined'); 72 | expect(css).not.toContain('null'); 73 | if (defaultProps['$enable-rounded']) { 74 | expect(css).toEqual('\n border-bottom-left-radius: .25rem;\n border-top-left-radius: .25rem;\n '); 75 | } else { 76 | expect(css).toEqual(''); 77 | } 78 | }); 79 | it('borderLeftRadius should return a css by default', () => { 80 | const css = borderLeftRadius(); 81 | expect(fromJS({ css }).hashCode()).toEqual(-1049744082); 82 | }); 83 | }); 84 | -------------------------------------------------------------------------------- /src/tests/box-shadow.test.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable'; 2 | 3 | import { defaultProps, boxShadow } from '../box-shadow'; 4 | 5 | describe('bootstrap box-shadow mixins', () => { 6 | it('boxShadow should return disable css', () => { 7 | const css = boxShadow(defaultProps['$enable-shadows'], 'inset 0 1px 1px rgba(0,0,0,.075)'); 8 | expect(css).not.toContain('undefined'); 9 | expect(css).not.toContain('null'); 10 | expect(css).toEqual(''); 11 | }); 12 | it('boxShadow should return enable css', () => { 13 | const css = boxShadow(!defaultProps['$enable-shadows'], 'inset 0 1px 1px rgba(0,0,0,.075)'); 14 | expect(css).not.toContain('undefined'); 15 | expect(css).not.toContain('null'); 16 | expect(css).toEqual('\n box-shadow: inset 0 1px 1px rgba(0,0,0,.075);\n '); 17 | }); 18 | it('boxShadow should return a css by default', () => { 19 | const css = boxShadow(); 20 | expect(fromJS({ css }).hashCode()).toEqual(788434458); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /src/tests/breakpoints.test.js: -------------------------------------------------------------------------------- 1 | import { 2 | defaultProps, 3 | breakpointNext, 4 | breakpointMin, 5 | breakpointMax, 6 | breakpointInfix, 7 | mediaBreakpointUp, 8 | mediaBreakpointDown, 9 | mediaBreakpointBetween, 10 | mediaBreakpointOnly, 11 | } from '../breakpoints'; 12 | 13 | describe('bootstrap breakpoints mixins', () => { 14 | it('breakpointNext should return a css', () => { 15 | let breakpoint = breakpointNext('xs', defaultProps['$grid-breakpoints'], Object.keys(defaultProps['$grid-breakpoints'])); 16 | expect(breakpoint).toEqual('sm'); 17 | breakpoint = breakpointNext('sm', defaultProps['$grid-breakpoints'], Object.keys(defaultProps['$grid-breakpoints'])); 18 | expect(breakpoint).toEqual('md'); 19 | breakpoint = breakpointNext('md', defaultProps['$grid-breakpoints'], Object.keys(defaultProps['$grid-breakpoints'])); 20 | expect(breakpoint).toEqual('lg'); 21 | breakpoint = breakpointNext('lg', defaultProps['$grid-breakpoints'], Object.keys(defaultProps['$grid-breakpoints'])); 22 | expect(breakpoint).toEqual('xl'); 23 | }); 24 | it('breakpointNext should return null if not arguments are passed', () => { 25 | const css = breakpointNext(); 26 | expect(css).toBeNull(); 27 | }); 28 | it('breakpointMin should be null', () => { 29 | const css = breakpointMin('xs', defaultProps['$grid-breakpoints']); 30 | expect(css).toBeNull(); 31 | }); 32 | it('breakpointMin should be not null', () => { 33 | const css = breakpointMin('sm', defaultProps['$grid-breakpoints']); 34 | expect(css).toEqual('576px'); 35 | }); 36 | it('breakpointMin should return null if no arguments are passed', () => { 37 | const css = breakpointMin(); 38 | expect(css).toBeUndefined(); 39 | }); 40 | it('breakpointMax should be not null', () => { 41 | const css = breakpointMax('sm', defaultProps['$grid-breakpoints']); 42 | expect(css).toEqual('767px'); 43 | }); 44 | it('breakpointMax should be null', () => { 45 | const css = breakpointMax('xl', defaultProps['$grid-breakpoints']); 46 | expect(css).toBeNull(); 47 | }); 48 | it('breakpointMax should return null if no arguments are passed', () => { 49 | const css = breakpointMax(); 50 | expect(css).toBeNull(); 51 | }); 52 | it('mediaBreakpointInfix should return ""', () => { 53 | const css = breakpointInfix('xs', defaultProps['$grid-breakpoints']); 54 | expect(css).toEqual(''); 55 | }); 56 | it('mediaBreakpointInfix should return null', () => { 57 | const css = breakpointInfix('md', defaultProps['$grid-breakpoints']); 58 | expect(css).toEqual('-md'); 59 | }); 60 | it('breakpointInfix should return an empty string if no arguments are passed', () => { 61 | const css = breakpointInfix(); 62 | expect(css).toEqual(''); 63 | }); 64 | it('mediaBreakpointUp should return a media query', () => { 65 | const css = mediaBreakpointUp('md', defaultProps['$grid-breakpoints'], 'content: \'awesome!\';'); 66 | expect(css).toContain('@media (min-width: 768px) {'); 67 | expect(css).toContain('content: \'awesome!\';'); 68 | }); 69 | it('mediaBreakpointUp should return an empty string if no arguments are passed', () => { 70 | const css = mediaBreakpointUp(); 71 | expect(css).toEqual(''); 72 | }); 73 | it('mediaBreakpointDown should return a media query', () => { 74 | const css = mediaBreakpointDown('md', defaultProps['$grid-breakpoints'], 'content: \'awesome!\';'); 75 | expect(css).toContain('@media (max-width: 991px) {'); 76 | expect(css).toContain('content: \'awesome!\';'); 77 | }); 78 | it('mediaBreakpointDown should return null if no arguments are passed', () => { 79 | const css = mediaBreakpointDown(); 80 | expect(css).toBeUndefined(); 81 | }); 82 | it('mediaBreakpointBetween should return a media query', () => { 83 | const css = mediaBreakpointBetween('md', 'lg', defaultProps['$grid-breakpoints'], 'content: \'awesome!\';'); 84 | expect(css).toContain('@media (min-width: 768px) and (max-width: 1199px) {'); 85 | expect(css).toContain('content: \'awesome!\';'); 86 | }); 87 | it('mediaBreakpointBetween should return a max media query', () => { 88 | const css = mediaBreakpointBetween('xs', 'lg', defaultProps['$grid-breakpoints'], 'content: \'awesome!\';'); 89 | expect(css).toContain('@media (max-width: 1199px) {'); 90 | expect(css).toContain('content: \'awesome!\';'); 91 | }); 92 | it('mediaBreakpointBetween should return a min media query', () => { 93 | const css = mediaBreakpointBetween('md', 'xl', defaultProps['$grid-breakpoints'], 'content: \'awesome!\';'); 94 | expect(css).toContain('@media (min-width: 768px) {'); 95 | expect(css).toContain(' content: \'awesome!\';'); 96 | }); 97 | it('mediaBreakpointBetween should return null if no arguments are passed', () => { 98 | const css = mediaBreakpointBetween(); 99 | expect(css).toBeUndefined(); 100 | }); 101 | it('mediaBreakpointOnly should return a media query', () => { 102 | const css = mediaBreakpointOnly('md', defaultProps['$grid-breakpoints'], ` 103 | content: 'awesome!'; 104 | `); 105 | expect(css).toContain('@media (min-width: 768px) and (max-width: 991px) {'); 106 | expect(css).toContain(' content: \'awesome!\';'); 107 | }); 108 | it('mediaBreakpointOnly should return null if no arguments are passed', () => { 109 | const css = mediaBreakpointOnly(); 110 | expect(css).toBeUndefined(); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /src/tests/buttons.test.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable'; 2 | import { 3 | defaultProps, buttonVariant, buttonOutlineVariant, buttonSize, button, 4 | } from '../buttons'; 5 | 6 | describe('bootstrap button mixins', () => { 7 | it('buttonVariant should return a css without shadows', () => { 8 | const css = buttonVariant(defaultProps['$enable-shadows'], '#f00', '#0f0', '#0ff', defaultProps['$btn-active-box-shadow'], defaultProps['$btn-box-shadow']); 9 | expect(css).not.toContain('undefined'); 10 | expect(css).not.toContain('null'); 11 | expect(fromJS({ css }).hashCode()).toEqual(657616858); 12 | }); 13 | it('buttonVariant should return a css with shadows', () => { 14 | const css = buttonVariant(!defaultProps['$enable-shadows'], '#f00', '#0f0', '#0ff', defaultProps['$btn-active-box-shadow'], defaultProps['$btn-box-shadow']); 15 | expect(css).not.toContain('undefined'); 16 | expect(css).not.toContain('null'); 17 | expect(fromJS({ css }).hashCode()).toEqual(-276107851); 18 | }); 19 | it('buttonVariant should return a css with gradient colors', () => { 20 | const css = buttonVariant(!defaultProps['$enable-shadows'], '#f00', 'linear-gradient(#B21255, #790A68)', '#0ff', defaultProps['$btn-active-box-shadow'], false); 21 | expect(css).not.toContain('undefined'); 22 | expect(css).not.toContain('null'); 23 | expect(fromJS({ css }).hashCode()).toEqual(989192686); 24 | }); 25 | it('buttonVariant should return a css by default', () => { 26 | const css = buttonVariant(); 27 | expect(fromJS({ css }).hashCode()).toEqual(461863357); 28 | }); 29 | it('buttonOutlineVariant should return a css', () => { 30 | const css = buttonOutlineVariant('#f00', '#0f0'); 31 | expect(css).not.toContain('undefined'); 32 | expect(css).not.toContain('null'); 33 | expect(fromJS({ css }).hashCode()).toEqual(-580680997); 34 | }); 35 | it('buttonOutlineVariant should return a css by default', () => { 36 | const css = buttonOutlineVariant(); 37 | expect(fromJS({ css }).hashCode()).toEqual(57374718); 38 | }); 39 | it('buttonSize should return a css with rounded', () => { 40 | const css = buttonSize(defaultProps['$enable-rounded'], '#f00', '#00f', '#eee', '3px'); 41 | expect(css).not.toContain('undefined'); 42 | expect(css).not.toContain('null'); 43 | expect(fromJS({ css }).hashCode()).toEqual(-294360164); 44 | }); 45 | it('buttonSize should return a css without rounded', () => { 46 | const css = buttonSize(!defaultProps['$enable-rounded'], '#f00', '#00f', '#eee', '3px'); 47 | expect(css).not.toContain('undefined'); 48 | expect(css).not.toContain('null'); 49 | expect(fromJS({ css }).hashCode()).toEqual(-496542589); 50 | }); 51 | it('buttonSize should return a css by default', () => { 52 | const css = buttonSize(); 53 | expect(fromJS({ css }).hashCode()).toEqual(813225771); 54 | }); 55 | it('button should return a a css', () => { 56 | const css = button( 57 | defaultProps['$enable-shadows'], 58 | defaultProps['$enable-hover-media-query'], 59 | defaultProps['$enable-transitions'], 60 | defaultProps['$enable-rounded'], 61 | defaultProps['$btn-font-weight'], 62 | defaultProps['$btn-line-height'], 63 | defaultProps['$btn-transition'], 64 | defaultProps['$input-btn-border-width'], 65 | defaultProps['$btn-padding-x'], 66 | defaultProps['$btn-padding-y'], 67 | defaultProps['$font-size-base'], 68 | defaultProps['$btn-border-radius'], 69 | defaultProps['$btn-active-box-shadow'], 70 | defaultProps['$cursor-disabled'], 71 | defaultProps['$link-color'], 72 | defaultProps['$link-hover-color'], 73 | defaultProps['$link-hover-decoration'], 74 | defaultProps['$btn-link-disabled-color'], 75 | defaultProps['$btn-padding-x-lg'], 76 | defaultProps['$btn-padding-y-lg'], 77 | defaultProps['$font-size-lg'], 78 | defaultProps['$btn-border-radius-lg'], 79 | defaultProps['$btn-padding-x-sm'], 80 | defaultProps['$btn-padding-y-sm'], 81 | defaultProps['$font-size-sm'], 82 | defaultProps['$btn-border-radius-sm'], 83 | defaultProps['$btn-block-spacing-y'], 84 | defaultProps['$btn-primary-color'], 85 | defaultProps['$btn-primary-bg'], 86 | defaultProps['$btn-primary-border'], 87 | defaultProps['$btn-secondary-color'], 88 | defaultProps['$btn-secondary-bg'], 89 | defaultProps['$btn-secondary-border'], 90 | defaultProps['$btn-info-color'], 91 | defaultProps['$btn-info-bg'], 92 | defaultProps['$btn-info-border'], 93 | defaultProps['$btn-success-color'], 94 | defaultProps['$btn-success-bg'], 95 | defaultProps['$btn-success-border'], 96 | defaultProps['$btn-warning-color'], 97 | defaultProps['$btn-warning-bg'], 98 | defaultProps['$btn-warning-border'], 99 | defaultProps['$btn-danger-color'], 100 | defaultProps['$btn-danger-bg'], 101 | defaultProps['$btn-danger-border'], 102 | defaultProps['$btn-disabled-opacity'], 103 | ); 104 | expect(css).not.toContain('undefined'); 105 | expect(css).not.toContain('null'); 106 | expect(fromJS({ css }).hashCode()).toEqual(-323088384); 107 | }); 108 | it('button should return a button utility by default', () => { 109 | const css = button(); 110 | expect(css).not.toContain('undefined'); 111 | expect(css).not.toContain('null'); 112 | expect(fromJS({ css }).hashCode()).toEqual(-515297454); 113 | }); 114 | }); 115 | -------------------------------------------------------------------------------- /src/tests/cards.test.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable'; 2 | import { 3 | defaultProps, cardVariant, cardOutlineVariant, cardInverse, card, 4 | } from '../cards'; 5 | 6 | describe('bootstrap cards mixins', () => { 7 | it('cardVariant should return a css', () => { 8 | const css = cardVariant('#f00', '#0f0'); 9 | expect(css).not.toContain('undefined'); 10 | expect(css).not.toContain('null'); 11 | expect(fromJS({ css }).hashCode()).toEqual(-667338980); 12 | }); 13 | it('cardVariant should return a css by default', () => { 14 | const css = cardVariant(); 15 | expect(fromJS({ css }).hashCode()).toEqual(-29949046); 16 | }); 17 | it('cardOutlineVariant should return a css', () => { 18 | const css = cardOutlineVariant('#f00'); 19 | expect(css).not.toContain('undefined'); 20 | expect(css).not.toContain('null'); 21 | expect(fromJS({ css }).hashCode()).toEqual(712604835); 22 | }); 23 | it('cardOutlineVariant should return a css by default', () => { 24 | const css = cardOutlineVariant(); 25 | expect(fromJS({ css }).hashCode()).toEqual(1027644489); 26 | }); 27 | it('cardInverse should return a css without media query', () => { 28 | const css = cardInverse(defaultProps['$enable-hover-media-query'], defaultProps['$card-link-hover-color']); 29 | expect(css).not.toContain('undefined'); 30 | expect(css).not.toContain('null'); 31 | expect(fromJS({ css }).hashCode()).toEqual(-106907581); 32 | }); 33 | it('cardInverse should return a css with media query', () => { 34 | const css = cardInverse(!defaultProps['$enable-hover-media-query'], defaultProps['$card-link-hover-color']); 35 | expect(css).not.toContain('undefined'); 36 | expect(css).not.toContain('null'); 37 | expect(fromJS({ css }).hashCode()).toEqual(78996063); 38 | }); 39 | it('cardInverse should return a css by default', () => { 40 | const css = cardInverse(); 41 | expect(fromJS({ css }).hashCode()).toEqual(-106907581); 42 | }); 43 | it('card should return a css with media query', () => { 44 | const css = card( 45 | defaultProps['$enable-rounded'], 46 | defaultProps['$enable-hover-media-query'], 47 | defaultProps['$card-spacer-y'], 48 | defaultProps['$card-spacer-x'], 49 | defaultProps['$card-bg'], 50 | defaultProps['$card-border-width'], 51 | defaultProps['$card-border-color'], 52 | defaultProps['$card-border-radius'], 53 | defaultProps['$card-cap-bg'], 54 | defaultProps['$card-border-radius-inner'], 55 | defaultProps['$brand-primary'], 56 | defaultProps['$brand-success'], 57 | defaultProps['$brand-info'], 58 | defaultProps['$brand-warning'], 59 | defaultProps['$brand-danger'], 60 | defaultProps['$btn-primary-bg'], 61 | defaultProps['$btn-secondary-border'], 62 | defaultProps['$btn-info-bg'], 63 | defaultProps['$btn-success-bg'], 64 | defaultProps['$btn-warning-bg'], 65 | defaultProps['$btn-danger-bg'], 66 | defaultProps['$card-link-hover-color'], 67 | defaultProps['$card-img-overlay-padding'], 68 | ); 69 | expect(css).not.toContain('undefined'); 70 | expect(css).not.toContain('null'); 71 | expect(fromJS({ css }).hashCode()).toEqual(-324121775); 72 | }); 73 | it('card should return a css by default', () => { 74 | const css = card(); 75 | expect(fromJS({ css }).hashCode()).toEqual(-324121775); 76 | }); 77 | }); 78 | -------------------------------------------------------------------------------- /src/tests/clearfix.test.js: -------------------------------------------------------------------------------- 1 | import { clearfix } from '../clearfix'; 2 | 3 | describe('bootstrap clearfix mixins', () => { 4 | it('clearfix should return a css', () => { 5 | const css = clearfix(); 6 | expect(css).not.toContain('undefined'); 7 | expect(css).not.toContain('null'); 8 | expect(css).toEqual('\n &::after {\n content: "";\n display: table;\n clear: both;\n }\n '); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /src/tests/conditional.test.js: -------------------------------------------------------------------------------- 1 | import { ifElse, ifThen } from '../conditional'; 2 | 3 | describe('kopax conditional mixins', () => { 4 | it('ifElse should return the true value', () => { 5 | expect(ifElse(true, 'I am an hero', 'I am a zero')).toEqual('I am an hero'); 6 | }); 7 | it('ifElse should return the false value', () => { 8 | expect(ifElse(false, 'I am an hero', 'I am a zero')).toEqual('I am a zero'); 9 | }); 10 | it('ifThen should return the true value', () => { 11 | expect(ifThen(true, 'I am an hero')).toEqual('I am an hero'); 12 | }); 13 | it('ifThen should return the false value', () => { 14 | expect(ifThen(false, 'I am an hero')).toEqual(''); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/tests/customForm.test.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable'; 2 | import { defaultProps, customForms } from '../customForms'; 3 | 4 | describe('bootstrap customForms mixin', () => { 5 | it('customForms should return a list of css mixin', () => { 6 | const css = customForms( 7 | defaultProps['$enable-rounded'], 8 | defaultProps['$enable-shadows'], 9 | defaultProps['$custom-control-checked-indicator-box-shadow'], 10 | defaultProps['$custom-control-active-indicator-box-shadow'], 11 | defaultProps['$custom-control-indicator-box-shadow'], 12 | defaultProps['$custom-checkbox-indeterminate-box-shadow'], 13 | defaultProps['$custom-select-focus-box-shadow'], 14 | defaultProps['$custom-file-focus-box-shadow'], 15 | defaultProps['$custom-file-box-shadow'], 16 | defaultProps['$custom-select-border-radius'], 17 | defaultProps['$custom-file-border-radius'], 18 | defaultProps['$custom-checkbox-radius'], 19 | defaultProps['$input-bg'], 20 | defaultProps['$custom-select-line-height'], 21 | defaultProps['$line-height-base'], 22 | defaultProps['$custom-control-gutter'], 23 | defaultProps['$custom-control-spacer-x'], 24 | defaultProps['$custom-control-checked-indicator-color'], 25 | defaultProps['$custom-control-checked-indicator-bg'], 26 | defaultProps['$custom-control-focus-indicator-box-shadow'], 27 | defaultProps['$custom-control-active-indicator-color'], 28 | defaultProps['$custom-control-active-indicator-bg'], 29 | defaultProps['$custom-control-disabled-cursor'], 30 | defaultProps['$custom-control-disabled-indicator-bg'], 31 | defaultProps['$custom-control-disabled-description-color'], 32 | defaultProps['$custom-control-indicator-size'], 33 | defaultProps['$custom-control-indicator-bg'], 34 | defaultProps['$custom-control-indicator-bg-size'], 35 | defaultProps['$custom-checkbox-checked-icon'], 36 | defaultProps['$custom-checkbox-indeterminate-bg'], 37 | defaultProps['$custom-checkbox-indeterminate-icon'], 38 | defaultProps['$custom-radio-radius'], 39 | defaultProps['$custom-radio-checked-icon'], 40 | defaultProps['$custom-control-spacer-y'], 41 | defaultProps['$border-width'], 42 | defaultProps['$input-height'], 43 | defaultProps['$custom-select-padding-y'], 44 | defaultProps['$custom-select-padding-x'], 45 | defaultProps['$custom-select-indicator-padding'], 46 | defaultProps['$custom-select-color'], 47 | defaultProps['$custom-select-bg'], 48 | defaultProps['$custom-select-indicator'], 49 | defaultProps['$custom-select-bg-size'], 50 | defaultProps['$custom-select-border-width'], 51 | defaultProps['$custom-select-border-color'], 52 | defaultProps['$custom-select-focus-border-color'], 53 | defaultProps['$input-color'], 54 | defaultProps['$custom-select-disabled-color'], 55 | defaultProps['$cursor-disabled'], 56 | defaultProps['$custom-select-disabled-bg'], 57 | defaultProps['$custom-select-sm-font-size'], 58 | defaultProps['$custom-file-width'], 59 | defaultProps['$custom-file-height'], 60 | defaultProps['$custom-file-padding-x'], 61 | defaultProps['$custom-file-padding-y'], 62 | defaultProps['$custom-file-line-height'], 63 | defaultProps['$custom-file-color'], 64 | defaultProps['$custom-file-bg'], 65 | defaultProps['$custom-file-border-width'], 66 | defaultProps['$custom-file-border-color'], 67 | defaultProps['$custom-file-button-color'], 68 | defaultProps['$custom-file-button-bg'], 69 | defaultProps['$custom-file-text'], 70 | ); 71 | expect(css).not.toContain('undefined'); 72 | expect(css).not.toContain('null'); 73 | expect(fromJS({ css }).hashCode()).toEqual(-226306711); 74 | }); 75 | it('customForms should use default arguments', () => { 76 | const css = customForms(); 77 | expect(css).not.toContain('undefined'); 78 | expect(css).not.toContain('null'); 79 | expect(fromJS({ css }).hashCode()).toEqual(-226306711); 80 | }); 81 | }); 82 | -------------------------------------------------------------------------------- /src/tests/float.test.js: -------------------------------------------------------------------------------- 1 | import { floatLeft, floatRight, floatNone } from '../float'; 2 | 3 | describe('bootstrap float mixins', () => { 4 | it('floatLeft should return a css', () => { 5 | const css = floatLeft(); 6 | expect(css).not.toContain('undefined'); 7 | expect(css).not.toContain('null'); 8 | expect(css).toEqual('\n float: left !important;\n '); 9 | }); 10 | it('floatRight should return a css', () => { 11 | const css = floatRight(); 12 | expect(css).not.toContain('undefined'); 13 | expect(css).not.toContain('null'); 14 | expect(css).toEqual('\n float: right !important;\n '); 15 | }); 16 | it('floatNone should return a css', () => { 17 | const css = floatNone(); 18 | expect(css).not.toContain('undefined'); 19 | expect(css).not.toContain('null'); 20 | expect(css).toEqual('\n float: none !important;\n '); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /src/tests/forms.test.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable'; 2 | import { 3 | defaultProps, formControl, formControlValidation, formControlFocus, inputSize, 4 | } from '../forms'; 5 | 6 | describe('bootstrap forms mixins', () => { 7 | it('formControl should return a css without shadows', () => { 8 | const css = formControl( 9 | !defaultProps['$enable-rounded'], 10 | defaultProps['$enable-transitions'], 11 | defaultProps['$enable-shadows'], 12 | defaultProps['$input-height'], 13 | defaultProps['$input-padding-y'], 14 | defaultProps['$input-padding-x'], 15 | defaultProps['$font-size-base'], 16 | defaultProps['$input-line-height'], 17 | defaultProps['$input-color'], 18 | defaultProps['$input-bg'], 19 | defaultProps['$input-border-radius'], 20 | defaultProps['$input-btn-border-width'], 21 | defaultProps['$input-border-color'], 22 | defaultProps['$input-transition'], 23 | defaultProps['$input-box-shadow'], 24 | defaultProps['$input-color-focus'], 25 | defaultProps['$input-bg-focus'], 26 | defaultProps['$input-border-focus'], 27 | defaultProps['$input-box-shadow-focus'], 28 | defaultProps['$input-color-placeholder'], 29 | defaultProps['$input-bg-disabled'], 30 | defaultProps['$cursor-disabled'], 31 | ); 32 | expect(css).not.toContain('undefined'); 33 | expect(css).not.toContain('null'); 34 | expect(fromJS({ css }).hashCode()).toEqual(682780003); 35 | }); 36 | it('formControl should have parameters', () => { 37 | const css = formControl(); 38 | expect(fromJS({ css }).hashCode()).toEqual(715200646); 39 | }); 40 | it('formControlValidation should return a css without shadows', () => { 41 | const css = formControlValidation(defaultProps['$enable-shadows'], '#f00', defaultProps['$input-box-shadow']); 42 | expect(css).not.toContain('undefined'); 43 | expect(css).not.toContain('null'); 44 | expect(fromJS({ css }).hashCode()).toEqual(-756613172); 45 | }); 46 | it('formControlValidation should return a css with shadows', () => { 47 | const css = formControlValidation(!defaultProps['$enable-shadows'], '#f00', defaultProps['$input-box-shadow']); 48 | expect(css).not.toContain('undefined'); 49 | expect(css).not.toContain('null'); 50 | expect(fromJS({ css }).hashCode()).toEqual(493146580); 51 | }); 52 | it('formControlValidation should have arguments', () => { 53 | const css = formControlValidation(); 54 | expect(fromJS({ css }).hashCode()).toEqual(856583856); 55 | }); 56 | it('formControlFocus should return a css without shadows', () => { 57 | const css = formControlFocus(defaultProps['$enable-shadows'], defaultProps['$input-color-focus'], defaultProps['$input-bg-focus'], defaultProps['$input-border-focus'], defaultProps['$input-box-shadow-focus']); 58 | expect(css).not.toContain('undefined'); 59 | expect(css).not.toContain('null'); 60 | expect(fromJS({ css }).hashCode()).toEqual(978393919); 61 | }); 62 | it('formControlFocus should return a css with shadows', () => { 63 | const css = formControlFocus(!defaultProps['$enable-shadows'], defaultProps['$input-color-focus'], defaultProps['$input-bg-focus'], defaultProps['$input-border-focus'], defaultProps['$input-box-shadow-focus']); 64 | expect(css).not.toContain('undefined'); 65 | expect(css).not.toContain('null'); 66 | expect(fromJS({ css }).hashCode()).toEqual(-1064216138); 67 | }); 68 | it('formControlFocus should have arguments', () => { 69 | const css = formControlFocus(); 70 | expect(fromJS({ css }).hashCode()).toEqual(978393919); 71 | }); 72 | it('inputSize should return a css with rounded', () => { 73 | const css = inputSize(defaultProps['$enable-rounded'], '.toto', '3px', '1px', '1px', '14px', '14px', defaultProps['$input-border-radius']); 74 | expect(css).not.toContain('undefined'); 75 | expect(css).not.toContain('null'); 76 | expect(fromJS({ css }).hashCode()).toEqual(-397503813); 77 | }); 78 | it('inputSize should return a css without rounded', () => { 79 | const css = inputSize(!defaultProps['$enable-rounded'], '.toto', '3px', '1px', '1px', '14px', '14px', defaultProps['$input-border-radius']); 80 | expect(css).not.toContain('undefined'); 81 | expect(css).not.toContain('null'); 82 | expect(fromJS({ css }).hashCode()).toEqual(443519589); 83 | }); 84 | it('inputSize should have arguments', () => { 85 | const css = inputSize(); 86 | expect(fromJS({ css }).hashCode()).toEqual(731864093); 87 | }); 88 | }); 89 | -------------------------------------------------------------------------------- /src/tests/gradients.test.js: -------------------------------------------------------------------------------- 1 | import { 2 | gradientX, 3 | gradientY, 4 | gradientDirectional, 5 | gradientXThreeColors, 6 | gradientYThreeColors, 7 | gradientRadial, 8 | gradientStriped, 9 | } from '../gradients'; 10 | 11 | describe('bootstrap gradients mixins', () => { 12 | it('gradientX should return a css', () => { 13 | const css = gradientX(); 14 | expect(css).not.toContain('undefined'); 15 | expect(css).not.toContain('null'); 16 | expect(css).toEqual('\n background-image: linear-gradient(to right, #555 0%, #333 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=\'#{ie-hex-str(#555)}\', endColorstr=\'#{ie-hex-str(#333)}\', GradientType=1); // IE9\n '); // eslint-disable-line no-useless-escape 17 | }); 18 | it('gradientY should return a css', () => { 19 | const css = gradientY(); 20 | expect(css).not.toContain('undefined'); 21 | expect(css).not.toContain('null'); 22 | expect(css).toEqual('\n background-image: linear-gradient(to bottom, #555 0%, #333 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=\'#{ie-hex-str(#555)}\', endColorstr=\'#{ie-hex-str(#333)}\', GradientType=0); // IE9\n '); // eslint-disable-line no-useless-escape 23 | }); 24 | it('gradientDirectional should return a css', () => { 25 | const css = gradientDirectional(); 26 | expect(css).not.toContain('undefined'); 27 | expect(css).not.toContain('null'); 28 | expect(css).toEqual('\n background-repeat: repeat-x;\n background-image: linear-gradient(45deg, #555, #333);\n '); // eslint-disable-line no-useless-escape 29 | }); 30 | it('gradientXThreeColors should return a css', () => { 31 | const css = gradientXThreeColors(); 32 | expect(css).not.toContain('undefined'); 33 | expect(css).not.toContain('null'); 34 | expect(css).toEqual('\n background-image: linear-gradient(to right, #00b3ee, #7a43b6 50%, #c3325f);\n background-repeat: no-repeat;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=\'#{ie-hex-str(#00b3ee)}\', endColorstr=\'#{ie-hex-str(#c3325f)}\', GradientType=1); // IE9 gets no color-stop at all for proper fallback\n '); // eslint-disable-line no-useless-escape 35 | }); 36 | it('gradientYThreeColors should return a css', () => { 37 | const css = gradientYThreeColors(); 38 | expect(css).not.toContain('undefined'); 39 | expect(css).not.toContain('null'); 40 | expect(css).toEqual('\n background-image: linear-gradient(#00b3ee, #7a43b6 50%, #c3325f);\n background-repeat: no-repeat;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=\'#{ie-hex-str(#00b3ee)}\', endColorstr=\'#{ie-hex-str(#c3325f)}\', GradientType=0); // IE9 gets no color-stop at all for proper fallback\n '); // eslint-disable-line no-useless-escape 41 | }); 42 | it('gradientRadial should return a css', () => { 43 | const css = gradientRadial(); 44 | expect(css).not.toContain('undefined'); 45 | expect(css).not.toContain('null'); 46 | expect(css).toEqual('\n background-image: radial-gradient(circle, #555, #333);\n background-repeat: no-repeat;\n '); // eslint-disable-line no-useless-escape 47 | }); 48 | it('gradientStriped should return a css', () => { 49 | const css = gradientStriped(); 50 | expect(css).not.toContain('undefined'); 51 | expect(css).not.toContain('null'); 52 | expect(css).toEqual('\n background-image: linear-gradient(45deg, rgba(255,255,255,.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.15) 50%, rgba(255,255,255,.15) 75%, transparent 75%, transparent);\n '); // eslint-disable-line no-useless-escape 53 | }); 54 | }); 55 | -------------------------------------------------------------------------------- /src/tests/grid-framework.test.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable'; 2 | import { makeGridColumns } from '../grid-framework'; 3 | import { defaultProps } from '../grid'; 4 | 5 | describe('bootstrap grid-framework mixins', () => { 6 | it('makeGridColumns should return an empty css', () => { 7 | const css = makeGridColumns( 8 | !defaultProps['$enable-grid-classes'], 9 | defaultProps['$grid-columns'], 10 | defaultProps['$grid-gutter-width'], 11 | defaultProps['$grid-breakpoints'] 12 | ); 13 | expect(css).toEqual(''); 14 | }); 15 | it('makeGridColumns should return a css', () => { 16 | const css = makeGridColumns( 17 | defaultProps['$enable-grid-classes'], 18 | defaultProps['$grid-columns'], 19 | defaultProps['$grid-gutter-width'], 20 | defaultProps['$grid-breakpoints'] 21 | ); 22 | expect(css).not.toContain('undefined'); 23 | expect(css).not.toContain('null'); 24 | expect(fromJS({ css }).hashCode()).toEqual(-672260335); 25 | }); 26 | it('makeGridColumns should have arguments', () => { 27 | const css = makeGridColumns(); 28 | expect(css).not.toContain('undefined'); 29 | expect(css).not.toContain('null'); 30 | expect(fromJS({ css }).hashCode()).toEqual(-672260335); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /src/tests/grid.test.js: -------------------------------------------------------------------------------- 1 | import { 2 | defaultProps, 3 | makeContainer, 4 | makeContainerMaxWidths, 5 | makeRow, 6 | makeColReady, 7 | makeCol, 8 | makeColOffset, 9 | } from '../grid'; 10 | 11 | describe('bootstrap grid mixins', () => { 12 | it('makeContainer should return an empty css', () => { 13 | const css = makeContainer(!defaultProps['$enable-grid-classes'], defaultProps['$grid-gutter-width']); 14 | expect(css).toEqual(''); 15 | }); 16 | it('makeContainer should return a css', () => { 17 | const css = makeContainer(defaultProps['$enable-grid-classes'], defaultProps['$grid-gutter-width']); 18 | expect(css).toContain('width: 100%;'); 19 | expect(css).toContain('padding-right: calc(30px / 2);'); 20 | expect(css).toContain('padding-left: calc(30px / 2);'); 21 | expect(css).toContain('margin-right: auto;'); 22 | expect(css).toContain('margin-left: auto;'); 23 | }); 24 | it('makeContainer should have arguments', () => { 25 | const css = makeContainer(); 26 | expect(css).toContain('width: 100%;'); 27 | expect(css).toContain('padding-right: calc(30px / 2);'); 28 | expect(css).toContain('padding-left: calc(30px / 2);'); 29 | expect(css).toContain('margin-right: auto;'); 30 | expect(css).toContain('margin-left: auto;'); 31 | }); 32 | it('makeContainerMaxWidths should return a css', () => { 33 | const css = makeContainerMaxWidths(defaultProps['$enable-grid-classes'], defaultProps['$container-max-widths'], defaultProps['$grid-breakpoints']); 34 | expect(css).toContain('@media (min-width: 576px) {'); 35 | expect(css).toContain('max-width: 540px'); 36 | expect(css).toContain('@media (min-width: 768px) {'); 37 | expect(css).toContain('max-width: 720px'); 38 | expect(css).toContain('@media (min-width: 992px) {'); 39 | expect(css).toContain('max-width: 960px'); 40 | expect(css).toContain('@media (min-width: 1200px) {'); 41 | expect(css).toContain('max-width: 1140px'); 42 | }); 43 | it('makeContainerMaxWidths should return an empty css', () => { 44 | const css = makeContainerMaxWidths(!defaultProps['$enable-grid-classes'], defaultProps['$container-max-widths'], defaultProps['$grid-breakpoints']); 45 | expect(css).toEqual(''); 46 | }); 47 | it('makeContainerMaxWidths should work with default arguments', () => { 48 | const css = makeContainerMaxWidths(); 49 | expect(css).toContain('@media (min-width: 576px) {'); 50 | expect(css).toContain('max-width: 540px'); 51 | expect(css).toContain('@media (min-width: 768px) {'); 52 | expect(css).toContain('max-width: 720px'); 53 | expect(css).toContain('@media (min-width: 992px) {'); 54 | expect(css).toContain('max-width: 960px'); 55 | expect(css).toContain('@media (min-width: 1200px) {'); 56 | expect(css).toContain('max-width: 1140px'); 57 | }); 58 | it('makeRow should return an empty css', () => { 59 | const css = makeRow(!defaultProps['$enable-grid-classes'], defaultProps['$grid-gutter-width']); 60 | expect(css).toEqual(''); 61 | }); 62 | it('makeRow should return an empty css', () => { 63 | const css = makeRow(!defaultProps['$enable-grid-classes'], defaultProps['$grid-gutter-width']); 64 | expect(css).toEqual(''); 65 | }); 66 | it('makeRow should return a css ', () => { 67 | const css = makeRow(defaultProps['$enable-grid-classes'], defaultProps['$grid-gutter-width']); 68 | expect(css).toContain('display: flex;'); 69 | expect(css).toContain('flex-wrap: wrap;'); 70 | expect(css).toContain('margin-right: calc(30px / -2);'); 71 | expect(css).toContain('margin-left: calc(30px / -2);'); 72 | }); 73 | it('makeRow should have arguments', () => { 74 | const css = makeRow(); 75 | expect(css).toContain('display: flex;'); 76 | expect(css).toContain('flex-wrap: wrap;'); 77 | expect(css).toContain('margin-right: calc(30px / -2);'); 78 | expect(css).toContain('margin-left: calc(30px / -2);'); 79 | }); 80 | it('makeColReady should return a css', () => { 81 | const css = makeColReady(defaultProps['$grid-gutter-width']); 82 | expect(css).toContain('position: relative;'); 83 | expect(css).toContain('width: 100%;'); 84 | expect(css).toContain('min-height: 1px; // Prevent collapsing'); 85 | expect(css).toContain('padding-right: calc(30px / 2);'); 86 | expect(css).toContain('padding-left: calc(30px / 2);'); 87 | }); 88 | it('makeColReady should have arguments', () => { 89 | const css = makeColReady(); 90 | expect(css).toContain('position: relative;'); 91 | expect(css).toContain('width: 100%;'); 92 | expect(css).toContain('min-height: 1px;'); 93 | expect(css).toContain('padding-right: calc(30px / 2);'); 94 | expect(css).toContain('padding-left: calc(30px / 2);'); 95 | }); 96 | it('makeCol should return a css', () => { 97 | const css = makeCol(2, defaultProps['$grid-columns']); 98 | expect(css).toContain('flex: 0 0 16.66%;'); 99 | expect(css).toContain('max-width: 16.66%;'); 100 | }); 101 | it('makeCol should have arguments', () => { 102 | const css = makeCol(); 103 | expect(css).toContain('flex: 0 0 0%;'); 104 | expect(css).toContain('max-width: 0%;'); 105 | }); 106 | it('makeColOffset should return a css', () => { 107 | const css = makeColOffset(3, defaultProps['$grid-columns']); 108 | expect(css).toEqual('margin-left: 25%;'); 109 | }); 110 | it('makeColOffset should have arguments', () => { 111 | const css = makeColOffset(); 112 | expect(css).toEqual('margin-left: 0%;'); 113 | }); 114 | }); 115 | -------------------------------------------------------------------------------- /src/tests/hover.test.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable'; 2 | 3 | import { 4 | defaultProps, hover, hoverFocus, hoverFocusActive, plainHoverFocus, 5 | } from '../hover'; 6 | import MixinError from '../MixinError'; 7 | 8 | describe('bootstrap hover mixins', () => { 9 | it('hover should return a css', () => { 10 | const css = hover(` 11 | cursor: pointer; 12 | opacity: .5; 13 | `); 14 | expect(css).not.toContain('undefined'); 15 | expect(css).not.toContain('null'); 16 | expect(css).toContain('&:hover, &.hover { '); 17 | expect(css).toContain('cursor: pointer;'); 18 | expect(css).toContain('opacity: .5;'); 19 | expect(css).toContain('}'); 20 | }); 21 | it('hover should have arguments', () => { 22 | expect(hover).toThrowError(new MixinError('content is required')); 23 | }); 24 | it('hoverFocus should return a css without media query', () => { 25 | const css = hoverFocus( 26 | defaultProps['$enable-hover-media-query'], 27 | `cursor: pointer; 28 | opacity: .5;` 29 | ); 30 | expect(css).not.toContain('undefined'); 31 | expect(css).not.toContain('null'); 32 | expect(css).toContain('&:focus,'); 33 | expect(css).toContain('&.focus,'); 34 | expect(css).toContain('&:hover,'); 35 | expect(css).toContain('&.hover {'); 36 | expect(css).toContain('cursor: pointer;'); 37 | expect(css).toContain('opacity: .5;'); 38 | expect(css).toContain('}'); 39 | }); 40 | it('hoverFocus should return a css with media query', () => { 41 | const css = hoverFocus( 42 | !defaultProps['$enable-hover-media-query'], 43 | `cursor: pointer; 44 | opacity: .5;` 45 | ); 46 | expect(css).not.toContain('undefined'); 47 | expect(css).not.toContain('null'); 48 | expect(css).toContain('&:focus, &.focus { cursor: pointer;'); 49 | expect(css).toContain('opacity: .5; }'); 50 | expect(css).toContain('&:hover, &.hover { cursor: pointer;'); 51 | expect(css).toContain('opacity: .5; }'); 52 | }); 53 | it('hoverFocus should have arguments', () => { 54 | const css = hoverFocus(); 55 | expect(css).toContain('&:focus,'); 56 | expect(css).toContain('&.focus,'); 57 | expect(css).toContain('&:hover,'); 58 | expect(css).toContain('&.hover {'); 59 | expect(css).toContain('undefined'); 60 | expect(css).toContain('}'); 61 | }); 62 | it('hoverFocusActive should return a css without media query', () => { 63 | const css = hoverFocusActive( 64 | defaultProps['$enable-hover-media-query'], 65 | `cursor: pointer; 66 | opacity: .5;` 67 | ); 68 | expect(css).not.toContain('undefined'); 69 | expect(css).not.toContain('null'); 70 | expect(css).toContain('&:focus, '); 71 | expect(css).toContain('&.focus, '); 72 | expect(css).toContain('&:active, '); 73 | expect(css).toContain('&.active,'); 74 | expect(css).toContain('&:hover,'); 75 | expect(css).toContain('&.hover {'); 76 | expect(css).toContain('cursor: pointer;'); 77 | expect(css).toContain('opacity: .5;'); 78 | expect(css).toContain('}'); 79 | }); 80 | it('hoverFocusActive should return a css with media query', () => { 81 | const css = hoverFocusActive( 82 | !defaultProps['$enable-hover-media-query'], 83 | `cursor: pointer; 84 | opacity: .5;` 85 | ); 86 | expect(css).not.toContain('undefined'); 87 | expect(css).not.toContain('null'); 88 | expect(css).toContain('&:focus,'); 89 | expect(css).toContain('&.focus,'); 90 | expect(css).toContain('&:active,'); 91 | expect(css).toContain('&.active {'); 92 | expect(css).toContain('cursor: pointer;'); 93 | expect(css).toContain('opacity: .5;'); 94 | expect(css).toContain('}'); 95 | expect(css).toContain('&:hover, &.hover { cursor: pointer;'); 96 | expect(css).toContain('opacity: .5; }'); 97 | }); 98 | it('hoverFocusActive should have arguments', () => { 99 | const css = hoverFocusActive(); 100 | expect(css).toContain('&:focus, '); 101 | expect(css).toContain('&.focus, '); 102 | expect(css).toContain('&:active, '); 103 | expect(css).toContain('&.active,'); 104 | expect(css).toContain('&:hover,'); 105 | expect(css).toContain('&.hover {'); 106 | expect(css).toContain(' undefined'); 107 | expect(css).toContain('}'); 108 | }); 109 | it('plainHoverFocus should return a css without media query', () => { 110 | const css = plainHoverFocus( 111 | defaultProps['$enable-hover-media-query'], 112 | `cursor: pointer; 113 | opacity: .5;` 114 | ); 115 | expect(css).not.toContain('undefined'); 116 | expect(css).not.toContain('null'); 117 | expect(css).toContain('&,'); 118 | expect(css).toContain('&:focus, '); 119 | expect(css).toContain('&.focus, '); 120 | expect(css).toContain('&:hover, '); 121 | expect(css).toContain('&.hover {'); 122 | expect(css).toContain('cursor: pointer;'); 123 | expect(css).toContain('opacity: .5;'); 124 | expect(css).toContain('}'); 125 | }); 126 | it('plainHoverFocus should return a css with media query', () => { 127 | const css = plainHoverFocus( 128 | !defaultProps['$enable-hover-media-query'], 129 | `cursor: pointer; 130 | opacity: .5;` 131 | ); 132 | expect(css).not.toContain('undefined'); 133 | expect(css).not.toContain('null'); 134 | expect(css).toContain('&,'); 135 | expect(css).toContain('&:focus, '); 136 | expect(css).toContain('&.focus {'); 137 | expect(css).toContain('cursor: pointer;'); 138 | expect(css).toContain('opacity: .5;'); 139 | expect(css).toContain('}'); 140 | expect(css).toContain('&:hover, &.hover { cursor: pointer;'); 141 | expect(css).toContain('opacity: .5; }'); 142 | }); 143 | it('plainHoverFocus should have arguments', () => { 144 | const css = plainHoverFocus(); 145 | expect(fromJS({ css }).hashCode()).toEqual(-136472967); 146 | }); 147 | it('hover should have hoverFocus', () => { 148 | const css = hover.focus( 149 | defaultProps['$enable-hover-media-query'], 150 | `cursor: pointer; 151 | opacity: .5;` 152 | ); 153 | expect(fromJS({ css }).hashCode()).toEqual(1054832218); 154 | }); 155 | it('hover should have plainHoverFocus', () => { 156 | const css = hover.plainFocus( 157 | defaultProps['$enable-hover-media-query'], 158 | `cursor: pointer; 159 | opacity: .5;` 160 | ); 161 | expect(fromJS({ css }).hashCode()).toEqual(1058096530); 162 | }); 163 | it('hover should have hoverFocusActive', () => { 164 | const css = hover.activeFocus( 165 | defaultProps['$enable-hover-media-query'], 166 | `cursor: pointer; 167 | opacity: .5;` 168 | ); 169 | expect(fromJS({ css }).hashCode()).toEqual(268514486); 170 | }); 171 | }); 172 | -------------------------------------------------------------------------------- /src/tests/image.test.js: -------------------------------------------------------------------------------- 1 | import { imgFluid, imgRetina } from '../image'; 2 | 3 | describe('bootstrap image mixins', () => { 4 | it('imgFluid should return a css', () => { 5 | const css = imgFluid(); 6 | expect(css).not.toContain('undefined'); 7 | expect(css).not.toContain('null'); 8 | expect(css).toEqual('\n /* Part 1: Set a maximum relative to the parent */\n max-width: 100%;\n /* Part 2: Override the height to auto, otherwise images will be stretched */\n /* when setting a width and height attribute on the img element. */\n height: auto;\n '); 9 | }); 10 | it('imgRetina should return a css', () => { 11 | const css = imgRetina( 12 | 'https://www.google.com/images/logo.png', 13 | 'https://www.google.fr/images/logo.png', 14 | '1280px', 15 | '960px' 16 | ); 17 | expect(css).not.toContain('undefined'); 18 | expect(css).not.toContain('null'); 19 | expect(css).toEqual('\n background-image: url(https://www.google.com/images/logo.png);\n\n /* Autoprefixer takes care of adding -webkit-min-device-pixel-ratio and -o-min-device-pixel-ratio, */\n /* but doesn\'t convert dppx=>dpi. */\n /* There\'s no such thing as unprefixed min-device-pixel-ratio since it\'s nonstandard. */\n /* Compatibility info: http://caniuse.com/#feat=css-media-resolution */\n @media only screen and (min-resolution: 192dpi), /* IE9-11 don\'t support dppx */\n only screen and (min-resolution: 2dppx) { /* Standardized */\n background-image: url(https://www.google.fr/images/logo.png);\n background-size: 1280px 960px;\n }\n '); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /src/tests/index.test.js: -------------------------------------------------------------------------------- 1 | const exports = require('../index'); 2 | 3 | describe('exports', () => { 4 | Object.keys(exports).forEach((key) => { 5 | it(`${key} should be defined`, () => { 6 | expect(exports[key]).toBeDefined(); 7 | }); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /src/tests/list-group.test.js: -------------------------------------------------------------------------------- 1 | import { defaultProps, listGroupItemVariant } from '../list-group'; 2 | 3 | describe('bootstrap list-group mixins', () => { 4 | it('listGroupItemVariant should return a css without hover media query', () => { 5 | const css = listGroupItemVariant(defaultProps['$enable-hover-media-query'], 'success', '#f00', '#0f0'); 6 | expect(css).toContain('& .list-group-item-success {'); 7 | expect(css).toContain('color: #0f0;'); 8 | expect(css).toContain('background-color: #f00;'); 9 | expect(css).toContain('}'); 10 | expect(css).toContain('& a.list-group-item-success,'); 11 | expect(css).toContain('button.list-group-item-success {'); 12 | expect(css).toContain('color: #0f0;'); 13 | expect(css).toContain('.list-group-item-heading {'); 14 | expect(css).toContain('color: inherit;'); 15 | expect(css).toContain('&:focus,'); 16 | expect(css).toContain('&.focus,'); 17 | expect(css).toContain('&:hover,'); 18 | expect(css).toContain('&.hover {'); 19 | expect(css).toContain('color: #0f0;'); 20 | expect(css).toContain('background-color: hsl(0, 100%, 47.5%);'); 21 | expect(css).toContain('&.active {'); 22 | expect(css).toContain('&, '); 23 | expect(css).toContain('&:focus, '); 24 | expect(css).toContain('&.focus, '); 25 | expect(css).toContain('&:hover, '); 26 | expect(css).toContain('&.hover {'); 27 | expect(css).toContain('color: #fff;'); 28 | expect(css).toContain('background-color: #0f0;'); 29 | expect(css).toContain('border-color: #0f0;'); 30 | }); 31 | it('listGroupItemVariant should return a css with hover media query', () => { 32 | const css = listGroupItemVariant(!defaultProps['$enable-hover-media-query'], 'success', '#f00', '#0f0'); 33 | expect(css).toContain('& .list-group-item-success {'); 34 | expect(css).toContain('color: #0f0;'); 35 | expect(css).toContain('background-color: #f00;'); 36 | expect(css).toContain('& a.list-group-item-success,'); 37 | expect(css).toContain('button.list-group-item-success {'); 38 | expect(css).toContain('color: #0f0;'); 39 | expect(css).toContain('.list-group-item-heading {'); 40 | expect(css).toContain('color: inherit;'); 41 | expect(css).toContain('&:focus, &.focus { '); 42 | expect(css).toContain('color: #0f0;'); 43 | expect(css).toContain('background-color: hsl(0, 100%, 47.5%);'); 44 | expect(css).toContain('&:hover, &.hover { '); 45 | expect(css).toContain('color: #0f0;'); 46 | expect(css).toContain('background-color: hsl(0, 100%, 47.5%);'); 47 | expect(css).toContain('&.active {'); 48 | expect(css).toContain('&, '); 49 | expect(css).toContain('&:focus, '); 50 | expect(css).toContain('&.focus {'); 51 | expect(css).toContain('color: #fff;'); 52 | expect(css).toContain('background-color: #0f0;'); 53 | expect(css).toContain('border-color: #0f0;'); 54 | expect(css).toContain('&:hover, &.hover { '); 55 | expect(css).toContain('color: #fff;'); 56 | expect(css).toContain('background-color: #0f0;'); 57 | expect(css).toContain('border-color: #0f0;'); 58 | }); 59 | it('listGroupItemVariant should return a css with hover media query', () => { 60 | const css = listGroupItemVariant(undefined, undefined, undefined); 61 | expect(css).toContain('& .list-group-item-undefined {'); 62 | expect(css).toContain('color: undefined;'); 63 | expect(css).toContain('background-color: undefined;'); 64 | expect(css).toContain('}'); 65 | expect(css).toContain(''); 66 | expect(css).toContain('& a.list-group-item-undefined,'); 67 | expect(css).toContain('button.list-group-item-undefined {'); 68 | expect(css).toContain('color: undefined;'); 69 | expect(css).toContain(''); 70 | expect(css).toContain('.list-group-item-heading {'); 71 | expect(css).toContain('color: inherit;'); 72 | expect(css).toContain('}'); 73 | expect(css).toContain('&:focus,'); 74 | expect(css).toContain('&.focus,'); 75 | expect(css).toContain('&:hover,'); 76 | expect(css).toContain('&.hover {'); 77 | expect(css).toContain('color: undefined;'); 78 | expect(css).toContain('background-color: hsl(0, 0%, 0%);'); 79 | expect(css).toContain(''); 80 | expect(css).toContain('}'); 81 | expect(css).toContain('&.active {'); 82 | expect(css).toContain(''); 83 | expect(css).toContain('&, '); 84 | expect(css).toContain('&:focus, '); 85 | expect(css).toContain('&.focus, '); 86 | expect(css).toContain('&:hover, '); 87 | expect(css).toContain('&.hover {'); 88 | expect(css).toContain('color: #fff;'); 89 | expect(css).toContain('background-color: undefined;'); 90 | expect(css).toContain('border-color: undefined;'); 91 | }); 92 | }); 93 | -------------------------------------------------------------------------------- /src/tests/lists.test.js: -------------------------------------------------------------------------------- 1 | import { 2 | defaultProps, listUnstyled, listInlineItem, listInline, 3 | } from '../lists'; 4 | 5 | describe('bootstrap lists mixins', () => { 6 | it('listUnstyled should return a css', () => { 7 | const css = listUnstyled(); 8 | expect(css).not.toContain('undefined'); 9 | expect(css).not.toContain('null'); 10 | expect(css).toContain('padding-left: 0;'); 11 | expect(css).toContain('list-style: none;'); 12 | }); 13 | it('listInlineItem should return a css', () => { 14 | const css = listInlineItem(defaultProps['$list-inline-padding']); 15 | expect(css).not.toContain('undefined'); 16 | expect(css).not.toContain('null'); 17 | expect(css).toContain('display: inline-block;'); 18 | expect(css).toContain('&:not(:last-child) {'); 19 | expect(css).toContain('margin-right: 5px;'); 20 | }); 21 | it('listInlineItem should have arguments', () => { 22 | const css = listInlineItem(); 23 | expect(css).not.toContain('undefined'); 24 | expect(css).not.toContain('null'); 25 | expect(css).toContain('display: inline-block;'); 26 | expect(css).toContain('&:not(:last-child) {'); 27 | expect(css).toContain('margin-right: 5px'); 28 | }); 29 | it('listInline should return a css', () => { 30 | const css = listInline(); 31 | expect(css).not.toContain('undefined'); 32 | expect(css).not.toContain('null'); 33 | expect(css).toContain('padding-left: 0;'); 34 | expect(css).toContain('list-style: none;'); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /src/tests/media.test.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable'; 2 | import { media } from '../media'; 3 | 4 | describe('bootstrap media mixins', () => { 5 | it('media should return a css', () => { 6 | const css = media(); 7 | expect(css).not.toContain('undefined'); 8 | expect(css).not.toContain('null'); 9 | expect(fromJS({ css }).hashCode()).toEqual(-18337284); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /src/tests/nav-divider.test.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable'; 2 | import { defaultProps, navDivider } from '../nav-divider'; 3 | 4 | describe('bootstrap nav-divider mixins', () => { 5 | it('navDivider should return a css', () => { 6 | const css = navDivider(defaultProps['$spacer-y'], '#f0f'); 7 | expect(css).not.toContain('undefined'); 8 | expect(css).not.toContain('null'); 9 | expect(fromJS({ css }).hashCode()).toEqual(858038477); 10 | }); 11 | it('navDivider should have arguments', () => { 12 | const css = navDivider(); 13 | expect(fromJS({ css }).hashCode()).toEqual(-953521003); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /src/tests/navbar-align.test.js: -------------------------------------------------------------------------------- 1 | import { defaultProps, navbarVerticalAlign } from '../navbar-align'; 2 | 3 | describe('bootstrap navbar-align mixins', () => { 4 | it('navbarVerticalAlign should return a css', () => { 5 | const css = navbarVerticalAlign(defaultProps['$navbar-height'], '30px'); 6 | expect(css).not.toContain('undefined'); 7 | expect(css).not.toContain('null'); 8 | expect(css).toContain('margin-top: 10px;'); 9 | expect(css).toContain('margin-bottom: 10px;'); 10 | }); 11 | it('navbarVerticalAlign should return a css', () => { 12 | const css = navbarVerticalAlign(undefined, '30px'); 13 | expect(css).not.toContain('undefined'); 14 | expect(css).not.toContain('null'); 15 | expect(css).toContain('margin-top: 10px;'); 16 | expect(css).toContain('margin-bottom: 10px;'); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /src/tests/navbar-toggleable.test.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable'; 2 | import { defaultProps, navbarToggleable } from '../navbar-toggleable'; 3 | 4 | describe('bootstrap toggleable mixins', () => { 5 | it('navbarToggleable should return a css without grid-breakpoints', () => { 6 | const css = navbarToggleable(!defaultProps['$grid-breakpoints']); 7 | expect(css).not.toContain('undefined'); 8 | expect(css).not.toContain('null'); 9 | expect(fromJS({ css }).hashCode()).toEqual(421143662); 10 | }); 11 | it('navbarToggleable should return a css', () => { 12 | const css = navbarToggleable(defaultProps['$grid-breakpoints']); 13 | expect(css).not.toContain('undefined'); 14 | expect(css).not.toContain('null'); 15 | expect(fromJS({ css }).hashCode()).toEqual(-839184507); 16 | }); 17 | it('navbarToggleable should have arguments', () => { 18 | const css = navbarToggleable(); 19 | expect(fromJS({ css }).hashCode()).toEqual(-839184507); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /src/tests/navbar.test.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable'; 2 | import { defaultProps, navbar } from '../navbar'; 3 | 4 | describe('bootstrap navbar mixins', () => { 5 | it('navbar should return a css for navbar', () => { 6 | const css = navbar( 7 | defaultProps['$grid-breakpoints'], 8 | defaultProps['$enable-rounded'], 9 | defaultProps['$enable-hover-media-query'], 10 | defaultProps['$navbar-padding-y'], 11 | defaultProps['$navbar-padding-x'], 12 | defaultProps['$zindex-navbar'], 13 | defaultProps['$zindex-navbar-fixed'], 14 | defaultProps['$zindex-navbar-sticky'], 15 | defaultProps['$navbar-brand-padding-y'], 16 | defaultProps['$font-size-lg'], 17 | defaultProps['$navbar-divider-padding-y'], 18 | defaultProps['$navbar-toggler-padding-y'], 19 | defaultProps['$navbar-toggler-padding-x'], 20 | defaultProps['$navbar-toggler-font-size'], 21 | defaultProps['$border-width'], 22 | defaultProps['$navbar-toggler-border-radius'], 23 | defaultProps['$navbar-light-active-color'], 24 | defaultProps['$navbar-light-color'], 25 | defaultProps['$navbar-light-hover-color'], 26 | defaultProps['$navbar-light-toggler-bg'], 27 | defaultProps['$navbar-light-toggler-border'], 28 | defaultProps['$navbar-dark-active-color'], 29 | defaultProps['$navbar-dark-color'], 30 | defaultProps['$navbar-dark-hover-color'], 31 | defaultProps['$navbar-dark-toggler-bg'], 32 | defaultProps['$navbar-dark-toggler-border'], 33 | ); 34 | expect(css).not.toContain('undefined'); 35 | expect(css).not.toContain('null'); 36 | expect(fromJS({ css }).hashCode()).toEqual(-857655091); 37 | }); 38 | it('navbar should have arguments', () => { 39 | const css = navbar(); 40 | expect(fromJS({ css }).hashCode()).toEqual(130848996); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /src/tests/paginations.test.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable'; 2 | import { defaultProps, paginationSize, pagination } from '../paginations'; 3 | 4 | describe('bootstrap pagination mixins', () => { 5 | it('paginationSize should return a css with rounded', () => { 6 | const css = paginationSize( 7 | defaultProps['$enable-rounded'], 8 | '.75rem', 9 | '1.5rem', 10 | '1.25rem', 11 | '.25rem', 12 | ); 13 | expect(css).not.toContain('undefined'); 14 | expect(css).not.toContain('null'); 15 | expect(fromJS({ css }).hashCode()).toEqual(-949498531); 16 | }); 17 | it('paginationSize should return a css without rounded', () => { 18 | const css = paginationSize( 19 | !defaultProps['$enable-rounded'], 20 | '.75rem', 21 | '1.5rem', 22 | '1.25rem', 23 | '.25rem', 24 | ); 25 | expect(css).not.toContain('undefined'); 26 | expect(css).not.toContain('null'); 27 | expect(fromJS({ css }).hashCode()).toEqual(-955440062); 28 | }); 29 | it('paginationSize should have arguments', () => { 30 | const css = paginationSize(); 31 | expect(fromJS({ css }).hashCode()).toEqual(429136650); 32 | }); 33 | it('paginationSize should return a css with rounded', () => { 34 | const css = paginationSize( 35 | defaultProps['$enable-rounded'], 36 | '.75rem', 37 | '1.5rem', 38 | '1.25rem', 39 | (4 / 3).toString(), 40 | '.25rem', 41 | ); 42 | expect(css).not.toContain('undefined'); 43 | expect(css).not.toContain('null'); 44 | expect(fromJS({ css }).hashCode()).toEqual(-111634357); 45 | }); 46 | it('paginationSize should return a css without rounded', () => { 47 | const css = paginationSize( 48 | !defaultProps['$enable-rounded'], 49 | '.75rem', 50 | '1.5rem', 51 | '1.25rem', 52 | (4 / 3).toString(), 53 | '.25rem', 54 | ); 55 | expect(css).not.toContain('undefined'); 56 | expect(css).not.toContain('null'); 57 | expect(fromJS({ css }).hashCode()).toEqual(-955440062); 58 | }); 59 | it('pagination should return a nav utility css', () => { 60 | const css = pagination( 61 | defaultProps['$enable-rounded'], 62 | defaultProps['$enable-hover-media-query'], 63 | defaultProps['$border-radius'], 64 | defaultProps['$pagination-active-color'], 65 | defaultProps['$pagination-active-bg'], 66 | defaultProps['$pagination-active-border'], 67 | defaultProps['$pagination-disabled-color'], 68 | defaultProps['$cursor-disabled'], 69 | defaultProps['$pagination-disabled-bg'], 70 | defaultProps['$pagination-disabled-border'], 71 | defaultProps['$pagination-padding-y'], 72 | defaultProps['$pagination-padding-x'], 73 | defaultProps['$pagination-line-height'], 74 | defaultProps['$pagination-color'], 75 | defaultProps['$pagination-bg'], 76 | defaultProps['$pagination-border-width'], 77 | defaultProps['$pagination-border-color'], 78 | defaultProps['$pagination-hover-color'], 79 | defaultProps['$pagination-hover-bg'], 80 | defaultProps['$pagination-hover-border'], 81 | defaultProps['$pagination-padding-y-lg'], 82 | defaultProps['$pagination-padding-x-lg'], 83 | defaultProps['$font-size-lg'], 84 | defaultProps['$line-height-lg'], 85 | defaultProps['$border-radius-lg'], 86 | defaultProps['$pagination-padding-y-sm'], 87 | defaultProps['$pagination-padding-x-sm'], 88 | defaultProps['$font-size-sm'], 89 | defaultProps['$line-height-sm'], 90 | defaultProps['$border-radius-sm'], 91 | ); 92 | expect(css).not.toContain('undefined'); 93 | expect(css).not.toContain('null'); 94 | expect(fromJS({ css }).hashCode()).toEqual(288894014); 95 | }); 96 | it('pagination should parameters', () => { 97 | const css = pagination(); 98 | expect(fromJS({ css }).hashCode()).toEqual(288894014); 99 | }); 100 | }); 101 | -------------------------------------------------------------------------------- /src/tests/progress.test.js: -------------------------------------------------------------------------------- 1 | import { progressVariant } from '../progress'; 2 | 3 | describe('bootstrap progress mixins', () => { 4 | it('progressVariant should return a css', () => { 5 | const css = progressVariant('#f00'); 6 | expect(css).not.toContain('undefined'); 7 | expect(css).not.toContain('null'); 8 | expect(css).toEqual('\n &[value]::-webkit-progress-value {\n background-color: #f00;\n }\n \n &[value]::-moz-progress-bar {\n background-color: #f00;\n }\n \n /* IE10+, Microsoft Edge */\n &[value]::-ms-fill {\n background-color: #f00;\n }\n \n /* IE9 */\n @media screen and (min-width:0\\0) {\n .progress-bar {\n background-color: #f00;\n }\n }\n '); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /src/tests/regex.test.js: -------------------------------------------------------------------------------- 1 | import { linearGradientRe } from '../regex'; 2 | 3 | describe('utils/regex.js', () => { 4 | it('should get linear gradient valuees', () => { 5 | expect('linear-gradient(#ccc)'.match(linearGradientRe)[0]).toEqual('#ccc'); 6 | expect('linear-gradient(#ccc, #fff)'.match(linearGradientRe)[1]).toEqual('#fff'); 7 | expect('linear-gradient(#ccc, #fff, rgb(254, 211, 200))'.match(linearGradientRe)[2]).toEqual('rgb(254, 211, 200)'); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /src/tests/reset-filter.test.js: -------------------------------------------------------------------------------- 1 | import { resetFilter } from '../reset-filter'; 2 | 3 | describe('bootstrap reset-filter mixins', () => { 4 | it('resetFilter should return a css', () => { 5 | const css = resetFilter(); 6 | expect(css).not.toContain('undefined'); 7 | expect(css).not.toContain('null'); 8 | expect(css).toEqual('\n filter: "progid:DXImageTransform.Microsoft.gradient(enabled = false)";\n '); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /src/tests/reset-text.test.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable'; 2 | import { defaultProps, resetText } from '../reset-text'; 3 | 4 | describe('bootstrap reset-text mixins', () => { 5 | it('resetText should return a css', () => { 6 | const css = resetText( 7 | defaultProps['$font-family-base'], 8 | defaultProps['$font-weight-normal'], 9 | defaultProps['$line-height-base'] 10 | ); 11 | expect(css).not.toContain('undefined'); 12 | expect(css).not.toContain('null'); 13 | expect(css).toEqual('\n font-family: true;\n /* We deliberately do NOT reset font-size or word-wrap. */\n font-style: normal;\n font-weight: true;\n letter-spacing: normal;\n line-break: auto;\n line-height: true;\n text-align: left; /* Fallback for where \'start\' is not supported */\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n '); 14 | }); 15 | it('resetText should have arguments', () => { 16 | const css = resetText(); 17 | expect(fromJS({ css }).hashCode()).toEqual(-552236203); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /src/tests/resize.test.js: -------------------------------------------------------------------------------- 1 | import { resizable } from '../resize'; 2 | 3 | describe('bootstrap resize mixins', () => { 4 | it('resizable should return a css', () => { 5 | const css = resizable('horizontal'); 6 | expect(css).not.toContain('undefined'); 7 | expect(css).not.toContain('null'); 8 | expect(css).toEqual('\n resize: horizontal; /* Options: horizontal, vertical, both */\n overflow: auto; /* Per CSS3 UI, \'resize\' only applies when \'overflow\' isn\'t \'visible\' */\n '); 9 | }); 10 | it('should throw error if wrong arguments are passed', () => { 11 | function errorTesting() { 12 | resizable('test-function'); 13 | } 14 | expect(errorTesting).toThrowError('Wrong resize value. Available are horizontal,vertical,both'); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/tests/screen-reader.test.js: -------------------------------------------------------------------------------- 1 | import { srOnly, srOnlyFocusable } from '../screen-reader'; 2 | 3 | describe('bootstrap screen-reader mixins', () => { 4 | it('srOnly should return a css', () => { 5 | const css = srOnly(); 6 | expect(css).not.toContain('undefined'); 7 | expect(css).not.toContain('null'); 8 | expect(css).toEqual('\n position: absolute !important;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0,0,0,0);\n border: 0;\n '); 9 | }); 10 | it('srOnlyFocusable should return a css', () => { 11 | const css = srOnlyFocusable(); 12 | expect(css).not.toContain('undefined'); 13 | expect(css).not.toContain('null'); 14 | expect(css).toEqual('\n &:active,\n &:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n }\n '); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/tests/size.test.js: -------------------------------------------------------------------------------- 1 | import { size } from '../size'; 2 | 3 | describe('bootstrap size mixins', () => { 4 | it('size should return a css from a width', () => { 5 | const css = size('300px'); 6 | expect(css).not.toContain('undefined'); 7 | expect(css).not.toContain('null'); 8 | expect(css).toEqual('\n width: 300px;\n height: 300px;\n '); 9 | }); 10 | it('size should return a css from a width and height', () => { 11 | const css = size('300px', '600px'); 12 | expect(css).not.toContain('undefined'); 13 | expect(css).not.toContain('null'); 14 | expect(css).toEqual('\n width: 300px;\n height: 600px;\n '); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/tests/tab-focus.test.js: -------------------------------------------------------------------------------- 1 | import { tabFocus } from '../tab-focus'; 2 | 3 | describe('bootstrap tab-focus mixins', () => { 4 | it('tabFocus should return a css', () => { 5 | const css = tabFocus(); 6 | expect(css).not.toContain('undefined'); 7 | expect(css).not.toContain('null'); 8 | expect(css).toEqual('\n /* WebKit-specific. Other browsers will keep their default outline style. */\n /* (Initially tried to also force default via \'outline: initial\', */\n /* but that seems to erroneously remove the outline in Firefox altogether.) */\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n '); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /src/tests/table-row.test.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable'; 2 | import { tableRowVariant } from '../table-row'; 3 | 4 | describe('bootstrap table-row mixins', () => { 5 | it('tableRowVariant should return a css active variant', () => { 6 | const css = tableRowVariant('active', '#f00'); 7 | expect(css).not.toContain('undefined'); 8 | expect(css).not.toContain('null'); 9 | expect(fromJS({ css }).hashCode()).toEqual(-402095557); 10 | }); 11 | it('tableRowVariant should return a css success variant', () => { 12 | const css = tableRowVariant('success', '#f00'); 13 | expect(css).not.toContain('undefined'); 14 | expect(css).not.toContain('null'); 15 | expect(fromJS({ css }).hashCode()).toEqual(-249014422); 16 | }); 17 | it('tableRowVariant should return a css info variant', () => { 18 | const css = tableRowVariant('info', '#f00'); 19 | expect(css).not.toContain('undefined'); 20 | expect(css).not.toContain('null'); 21 | expect(fromJS({ css }).hashCode()).toEqual(-869814795); 22 | }); 23 | it('tableRowVariant should return a css warning variant', () => { 24 | const css = tableRowVariant('warning', '#f00'); 25 | expect(css).not.toContain('undefined'); 26 | expect(css).not.toContain('null'); 27 | expect(fromJS({ css }).hashCode()).toEqual(311874434); 28 | }); 29 | it('tableRowVariant should return a css danger variant', () => { 30 | const css = tableRowVariant('danger', '#f00'); 31 | expect(css).not.toContain('undefined'); 32 | expect(css).not.toContain('null'); 33 | expect(fromJS({ css }).hashCode()).toEqual(247827306); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /src/tests/text-emphasis.test.js: -------------------------------------------------------------------------------- 1 | import { defaultProps, textEmphasisVariant } from '../text-emphasis'; 2 | 3 | describe('bootstrap text-emphasis mixins', () => { 4 | it('textEmphasisVariant should return a css without hover media query', () => { 5 | const css = textEmphasisVariant(defaultProps['$enable-hover-media-query'], '.toto', '#f00'); 6 | expect(css).toContain('.toto {'); 7 | expect(css).toContain('color: #f00 !important;'); 8 | expect(css).toContain('}'); 9 | expect(css).toContain('a.toto {'); 10 | expect(css).toContain('&:focus,'); 11 | expect(css).toContain('&.focus,'); 12 | expect(css).toContain('&:hover,'); 13 | expect(css).toContain('&.hover {'); 14 | expect(css).toContain('color: rgb(204, 0, 0) !important;'); 15 | expect(css).toContain('}'); 16 | }); 17 | it('textEmphasisVariant should return a css with hover media query', () => { 18 | const css = textEmphasisVariant(!defaultProps['$enable-hover-media-query'], '.toto', '#f00'); 19 | expect(css).toContain('.toto {'); 20 | expect(css).toContain('color: #f00 !important;'); 21 | expect(css).toContain('a.toto {'); 22 | expect(css).toContain('&:focus, &.focus { color: rgb(204, 0, 0) !important; }'); 23 | expect(css).toContain('&:hover, &.hover { color: rgb(204, 0, 0) !important; }'); 24 | }); 25 | it('textEmphasisVariant should have arguments', () => { 26 | const css = textEmphasisVariant(undefined, undefined, undefined); 27 | expect(css).toContain('undefined {'); 28 | expect(css).toContain('color: undefined !important;'); 29 | expect(css).toContain('}'); 30 | expect(css).toContain('aundefined {'); 31 | expect(css).toContain('&:focus,'); 32 | expect(css).toContain('&.focus,'); 33 | expect(css).toContain('&:hover,'); 34 | expect(css).toContain('&.hover {'); 35 | expect(css).toContain('color: rgb(0, 0, 0) !important;'); 36 | expect(css).toContain('}'); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /src/tests/text-hide.test.js: -------------------------------------------------------------------------------- 1 | import { textHide } from '../text-hide'; 2 | 3 | describe('bootstrap text-hide mixins', () => { 4 | it('textHide should return a css', () => { 5 | const css = textHide(); 6 | expect(css).not.toContain('undefined'); 7 | expect(css).not.toContain('null'); 8 | expect(css).toEqual('\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n '); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /src/tests/text-truncate.test.js: -------------------------------------------------------------------------------- 1 | import { textTruncate } from '../text-truncate'; 2 | 3 | describe('bootstrap text-truncate mixins', () => { 4 | it('textTruncate should return a css', () => { 5 | const css = textTruncate(); 6 | expect(css).not.toContain('undefined'); 7 | expect(css).not.toContain('null'); 8 | expect(css).toEqual('\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n '); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /src/tests/transition.test.js: -------------------------------------------------------------------------------- 1 | import { transition } from '../transition'; 2 | 3 | describe('bootstrap transition mixins', () => { 4 | it('transition should return a css with transitions', () => { 5 | const enableTransitions = true; 6 | const css = transition(enableTransitions, 'all .2s ease-in-out'); 7 | expect(css).not.toContain('undefined'); 8 | expect(css).not.toContain('null'); 9 | expect(css).toEqual('\n transition: all .2s ease-in-out;\n '); 10 | }); 11 | it('transition should return a css without transitions', () => { 12 | const enableTransitions = false; 13 | const css = transition(enableTransitions, 'all .2s ease-in-out'); 14 | expect(css).not.toContain('undefined'); 15 | expect(css).not.toContain('null'); 16 | expect(css).toEqual(''); 17 | }); 18 | it('transition should have arguments', () => { 19 | const css = transition(); 20 | expect(css).toEqual(''); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /src/tests/typography.test.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable'; 2 | import { defaultProps, typography } from '../typography'; 3 | 4 | describe('bootstrap typography utility', () => { 5 | it('nav should return a typography utility css', () => { 6 | const css = typography( 7 | defaultProps['$headings-margin-bottom'], 8 | defaultProps['$headings-font-family'], 9 | defaultProps['$headings-font-weight'], 10 | defaultProps['$headings-line-height'], 11 | defaultProps['$headings-color'], 12 | defaultProps['$display1-size'], 13 | defaultProps['$display2-size'], 14 | defaultProps['$display3-size'], 15 | defaultProps['$display4-size'], 16 | defaultProps['$display1-weight'], 17 | defaultProps['$display2-weight'], 18 | defaultProps['$display3-weight'], 19 | defaultProps['$display4-weight'] 20 | ); 21 | expect(css).not.toContain('undefined'); 22 | expect(css).not.toContain('null'); 23 | expect(fromJS({ css }).hashCode()).toEqual(-187480347); 24 | }); 25 | it('nav should return a typography utility css with default', () => { 26 | const css = typography(); 27 | expect(css).not.toContain('undefined'); 28 | expect(css).not.toContain('null'); 29 | expect(fromJS({ css }).hashCode()).toEqual(-187480347); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /src/tests/utilities.test.js: -------------------------------------------------------------------------------- 1 | import { zip, generateUtility } from '../utilities'; 2 | 3 | describe('bootstrap utilities mixins', () => { 4 | describe('zip', () => { 5 | it('should zip', () => { 6 | expect(zip([ 7 | '10px', 8 | '50px', 9 | '100px', 10 | ], [ 11 | 'short', 12 | 'mid', 13 | 'long', 14 | ])).toEqual([ 15 | ['10px', 'short'], 16 | ['50px', 'mid'], 17 | ['100px', 'long'], 18 | ]); 19 | expect(zip([ 20 | '10px', 21 | '50px', 22 | '100px', 23 | ], [ 24 | 'short', 25 | 'mid', 26 | ])).toEqual([ 27 | ['10px', 'short'], 28 | ['50px', 'mid'], 29 | ]); 30 | expect(zip([ 31 | '10px', 32 | '50px', 33 | '100px', 34 | ], [ 35 | 'short', 36 | 'mid', 37 | 'long', 38 | ], [ 39 | 'north', 40 | 'est', 41 | ])).toEqual([ 42 | ['10px', 'short', 'north'], 43 | ['50px', 'mid', 'est'], 44 | ]); 45 | }); 46 | }); 47 | const utilities = new Map([ 48 | ['align', { 49 | property: 'vertical-align', 50 | class: 'align', 51 | values: [ 52 | 'baseline', 53 | 'top', 54 | 'middle', 55 | 'bottom', 56 | 'text-bottom', 57 | 'text-top', 58 | ], 59 | }], 60 | ['float', { 61 | responsive: true, 62 | property: 'float', 63 | values: [ 64 | 'left', 65 | 'right', 66 | 'none', 67 | ], 68 | }], 69 | ['width', { 70 | property: 'max-width', 71 | class: 'w', 72 | values: new Map([ 73 | [25, '25%'], 74 | [50, '50%'], 75 | [75, '75%'], 76 | [100, '100%'], 77 | ['auto', 'auto'], 78 | ]), 79 | }], 80 | ['max-width', { 81 | property: 'max-width', 82 | class: 'mw', 83 | values: new Map([ 84 | [100, '100%'], 85 | ]), 86 | }], 87 | ['shadow', { 88 | property: 'box-shadow', 89 | class: 'shadow', 90 | values: new Map([ 91 | ['sm', '3px'], 92 | [null, '4px'], 93 | ['lg', '5px'], 94 | ['none', 'none'], 95 | ]), 96 | }], 97 | ['rounded-top', { 98 | property: [ 99 | 'border-top-left-radius', 100 | 'border-top-right-radius', 101 | ], 102 | class: 'rounded-top', 103 | values: new Map([ 104 | [null, '4px'], 105 | ]), 106 | }], 107 | ['border', { 108 | property: 'border', 109 | values: new Map([ 110 | [null, '1px solid #dee2e6'], 111 | [0, 0], 112 | ]), 113 | }], 114 | ['border-top', { 115 | property: 'border-top', 116 | values: new Map([ 117 | [null, '1px solid #dee2e6'], 118 | [0, 0], 119 | ]), 120 | }], 121 | ['border-right', { 122 | property: 'border-right', 123 | values: new Map([ 124 | [null, '1px solid #dee2e6'], 125 | [0, 0], 126 | ]), 127 | }], 128 | ['border-bottom', { 129 | property: 'border-bottom', 130 | values: new Map([ 131 | [null, '1px solid #dee2e6'], 132 | [0, 0], 133 | ]), 134 | }], 135 | ['border-left', { 136 | property: 'border-left', 137 | values: new Map([ 138 | [null, '1px solid #dee2e6'], 139 | [0, 0], 140 | ]), 141 | }], 142 | ]); 143 | it('should generate align utility', () => { 144 | const css = generateUtility(utilities.get('align')); 145 | expect(css).toEqual(`.align-baseline { 146 | vertical-align: baseline !important; 147 | } 148 | .align-top { 149 | vertical-align: top !important; 150 | } 151 | .align-middle { 152 | vertical-align: middle !important; 153 | } 154 | .align-bottom { 155 | vertical-align: bottom !important; 156 | } 157 | .align-text-bottom { 158 | vertical-align: text-bottom !important; 159 | } 160 | .align-text-top { 161 | vertical-align: text-top !important; 162 | }`); 163 | }); 164 | it('should generate float utility', () => { 165 | const css = generateUtility(utilities.get('float'), '-sm'); 166 | expect(css).toEqual(`.float-sm-left { 167 | float: left !important; 168 | } 169 | .float-sm-right { 170 | float: right !important; 171 | } 172 | .float-sm-none { 173 | float: none !important; 174 | }`); 175 | }); 176 | it('should generate shadow utility', () => { 177 | const css = generateUtility(utilities.get('shadow')); 178 | expect(css).toEqual(`.shadow-sm { 179 | box-shadow: 3px !important; 180 | } 181 | .shadow { 182 | box-shadow: 4px !important; 183 | } 184 | .shadow-lg { 185 | box-shadow: 5px !important; 186 | } 187 | .shadow-none { 188 | box-shadow: none !important; 189 | }`); 190 | }); 191 | it('should generate rounded-top utility', () => { 192 | const css = generateUtility(utilities.get('rounded-top')); 193 | expect(css).toEqual(`.rounded-top { 194 | border-top-left-radius: 4px !important; 195 | border-top-right-radius: 4px !important; 196 | }`); 197 | }); 198 | it('should generate rounded-top utility with infix -print', () => { 199 | const css = generateUtility(utilities.get('rounded-top'), '-print'); 200 | expect(css).toEqual(`.rounded-top-print { 201 | border-top-left-radius: 4px !important; 202 | border-top-right-radius: 4px !important; 203 | }`); 204 | }); 205 | it('should generate border utility with infix -print', () => { 206 | const css = generateUtility(utilities.get('border'), '-print'); 207 | expect(css).toEqual(`.border-print { 208 | border: 1px solid #dee2e6 !important; 209 | } 210 | .border-print-0 { 211 | border: 0 !important; 212 | }`); 213 | }); 214 | }); 215 | -------------------------------------------------------------------------------- /src/tests/visibility.test.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable'; 2 | import { invisible } from '../visibility'; 3 | 4 | describe('bootstrap visibility mixins', () => { 5 | it('invisible should have arguments', () => { 6 | const css = invisible(); 7 | expect(fromJS({ css }).hashCode()).toEqual(-3936327); 8 | }); 9 | it('invisible should return a css', () => { 10 | const css = invisible('hidden'); 11 | expect(css).not.toContain('undefined'); 12 | expect(css).not.toContain('null'); 13 | expect(fromJS({ css }).hashCode()).toEqual(281334414); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /src/text-emphasis.js: -------------------------------------------------------------------------------- 1 | import color from '@bootstrap-styled/color'; 2 | import { hoverFocus } from './hover'; 3 | 4 | export const defaultProps = { 5 | '$enable-hover-media-query': false, 6 | }; 7 | 8 | /** 9 | * @public 10 | * @description Forces text color and hovering from a parent component. 11 | * @param {boolean} enableHoverMediaQuery 12 | * @param {string} parent 13 | * @param {string} textColor 14 | * @returns {string} 15 | */ 16 | export function textEmphasisVariant(enableHoverMediaQuery = defaultProps['$enable-hover-media-query'], parent, textColor) { 17 | return ` 18 | ${parent} { 19 | color: ${textColor} !important; 20 | } 21 | a${parent} { 22 | ${hoverFocus( 23 | enableHoverMediaQuery, 24 | `color: ${color(textColor).darken(0.20).rgb()} !important;` 25 | )} 26 | } 27 | `; 28 | } 29 | 30 | export default { 31 | defaultProps, 32 | textEmphasisVariant, 33 | }; 34 | -------------------------------------------------------------------------------- /src/text-hide.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @public 3 | * @description Hides text. 4 | * @returns {string} 5 | */ 6 | export function textHide() { 7 | return ` 8 | font: 0/0 a; 9 | color: transparent; 10 | text-shadow: none; 11 | background-color: transparent; 12 | border: 0; 13 | `; 14 | } 15 | 16 | export default { 17 | textHide, 18 | }; 19 | -------------------------------------------------------------------------------- /src/text-truncate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @public 3 | * @description Text truncate. Requires inline-block or block for proper styling. 4 | * @returns {string} 5 | */ 6 | export function textTruncate() { 7 | return ` 8 | overflow: hidden; 9 | text-overflow: ellipsis; 10 | white-space: nowrap; 11 | `; 12 | } 13 | 14 | export default { 15 | textTruncate, 16 | }; 17 | -------------------------------------------------------------------------------- /src/transition.js: -------------------------------------------------------------------------------- 1 | export const defaultProps = { 2 | '$enable-transitions': true, 3 | }; 4 | 5 | /** 6 | * @public 7 | * @description Enables transition if enableTransitions is true. 8 | * @param {boolean} enableTransitions 9 | * @param {array} args 10 | * @returns {string} 11 | */ 12 | // eslint-disable-next-line consistent-return 13 | export function transition(enableTransitions = defaultProps['$enable-transitions'], ...args) { 14 | if (enableTransitions && args.length) { 15 | return ` 16 | transition: ${args.join(' ')}; 17 | `; 18 | } 19 | return ''; 20 | } 21 | 22 | export default { 23 | transition, 24 | }; 25 | -------------------------------------------------------------------------------- /src/typography.js: -------------------------------------------------------------------------------- 1 | export const defaultProps = { 2 | '$headings-margin-bottom': '0.5rem', 3 | '$headings-font-family': 'inherit', 4 | '$headings-font-weight': '500', 5 | '$headings-line-height': '1.1', 6 | '$headings-color': 'inherit', 7 | '$display1-size': '6rem', 8 | '$display2-size': '5.5rem', 9 | '$display3-size': '4.5rem', 10 | '$display4-size': '3.5rem', 11 | '$display1-weight': '300', 12 | '$display2-weight': '300', 13 | '$display3-weight': '300', 14 | '$display4-weight': '300', 15 | }; 16 | 17 | export function typography( 18 | $headingsMarginBottom = defaultProps['$headings-margin-bottom'], 19 | $headingsFontFamily = defaultProps['$headings-font-family'], 20 | $headingsFontWeight = defaultProps['$headings-font-weight'], 21 | $headingsLineHeight = defaultProps['$headings-line-height'], 22 | $headingsColor = defaultProps['$headings-color'], 23 | $display1Size = defaultProps['$display1-size'], 24 | $display2Size = defaultProps['$display2-size'], 25 | $display3Size = defaultProps['$display3-size'], 26 | $display4Size = defaultProps['$display4-size'], 27 | $display1Weight = defaultProps['$display1-weight'], 28 | $display2Weight = defaultProps['$display2-weight'], 29 | $display3Weight = defaultProps['$display3-weight'], 30 | $display4Weight = defaultProps['$display4-weight'], 31 | ) { 32 | return ` 33 | margin-bottom: ${$headingsMarginBottom}; 34 | font-family: ${$headingsFontFamily}; 35 | font-weight: ${$headingsFontWeight}; 36 | line-height: ${$headingsLineHeight}; 37 | color: ${$headingsColor}; 38 | 39 | /* Type Scss */ 40 | 41 | &.display-1 { 42 | font-size: ${$display1Size}; 43 | font-weight: ${$display1Weight}; 44 | line-height: ${$headingsLineHeight}; 45 | 46 | } 47 | 48 | &.display-2 { 49 | font-size: ${$display2Size}; 50 | font-weight: ${$display2Weight}; 51 | line-height: ${$headingsLineHeight}; 52 | } 53 | 54 | &.display-3 { 55 | font-size: ${$display3Size}; 56 | font-weight: ${$display3Weight}; 57 | line-height: ${$headingsLineHeight}; 58 | } 59 | 60 | &.display-4 { 61 | font-size: ${$display4Size}; 62 | font-weight: ${$display4Weight}; 63 | line-height: ${$headingsLineHeight}; 64 | } 65 | `; 66 | } 67 | 68 | export default { 69 | defaultProps, 70 | typography, 71 | }; 72 | -------------------------------------------------------------------------------- /src/utilities.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Combines every list in $lists into a single list of sub-lists. 3 | * Each element in the returned list contains all the elements at that position in $lists. The returned list is as long as the shortest list in $lists. 4 | * The returned list is always comma-separated and the sub-lists are always space-separated. 5 | * This is a rewrite of zip scss function (see: https://sass-lang.com/documentation/modules/list#zip) 6 | * @param list 7 | * @returns {[]} 8 | * @example 9 | * zip(['10px', '50px', '100px'], ['short', 'mid']); // [['10px', 'short'], ['50px', 'mid']] 10 | */ 11 | export function zip(...list) { 12 | let shortest = 0; 13 | list.forEach((l) => { 14 | if (l instanceof Array) { 15 | if (!shortest || l.length < shortest) { 16 | shortest = l.length; 17 | } 18 | } 19 | }); 20 | const res = []; 21 | for (let i = 0; i < shortest; i += 1) { 22 | res[i] = []; 23 | let ind = 0; 24 | list.forEach((l) => { 25 | res[i][ind] = l[i]; 26 | ind += 1; 27 | }); 28 | } 29 | return res; 30 | } 31 | 32 | /** 33 | * Utility generator 34 | * Used to generate utilities & print utilities 35 | * @param {object} utility - an utility object to process 36 | * @param {string} [infix=""] - infix (eg: -media, -sm, -md, ...) 37 | * @returns {string} css - the css for utilities 38 | */ 39 | export function generateUtility( 40 | utility, 41 | infix = '', 42 | ) { 43 | let { values, property: properties } = utility; 44 | 45 | if (values instanceof Array) { 46 | values = zip(values, values); 47 | } 48 | 49 | // Multiple properties are possible, for example with vertical or horizontal margins or paddings 50 | if (typeof properties === 'string') { 51 | properties = [properties]; 52 | } 53 | 54 | const classList = []; 55 | // eslint-disable-next-line no-restricted-syntax 56 | for (const [key, value] of values) { 57 | let propertyClass = utility.hasOwnProperty('class') ? utility.class : properties[0]; 58 | propertyClass = !propertyClass ? '' : propertyClass; 59 | 60 | const infixFinal = propertyClass === '' && infix[0] === '-' ? infix.slice(1) : infix; 61 | 62 | 63 | // Don't prefix if value key is null (eg. with shadow class) 64 | // eslint-disable-next-line no-nested-ternary 65 | const propertyClassModifier = key !== null 66 | ? (propertyClass === '' && infixFinal === '' ? '' : '-') + key 67 | : ''; 68 | classList.push(`.${propertyClass}${infixFinal}${propertyClassModifier} { 69 | ${properties.map((property) => `${property}: ${value} !important;`).join('\n')} 70 | }`); 71 | } 72 | return classList.join('\n'); 73 | } 74 | -------------------------------------------------------------------------------- /src/visibility.js: -------------------------------------------------------------------------------- 1 | 2 | // Visibility 3 | 4 | /** 5 | * @public 6 | * @description Forces visibility value with !important 7 | * @param visibility 8 | * @returns {string} 9 | */ 10 | export function invisible(visibility) { 11 | return ` 12 | visibility: ${visibility} !important; 13 | `; 14 | } 15 | 16 | export default { 17 | invisible, 18 | }; 19 | -------------------------------------------------------------------------------- /styleguide.config.js: -------------------------------------------------------------------------------- 1 | const { createConfig } = require('@rollup-umd/documentation'); 2 | const config = createConfig({ 3 | pagePerSection: true, 4 | }); 5 | 6 | module.exports = config; 7 | -------------------------------------------------------------------------------- /styleguide/jsdoc.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | npm run jsdoc-documentation src/a.js docs/componentSpecific/a.md 4 | npm run jsdoc-documentation src/alert.js docs/componentSpecific/alert.md 5 | npm run jsdoc-documentation src/badge.js docs/componentSpecific/badge.md 6 | npm run jsdoc-documentation src/list-group.js docs/componentSpecific/list-group.md 7 | npm run jsdoc-documentation src/media.js docs/componentSpecific/media.md 8 | npm run jsdoc-documentation src/navbar-align.js docs/componentSpecific/navbar-align.md 9 | 10 | npm run jsdoc-documentation src/background-variant.js docs/cssHelpers/background-variant.md 11 | npm run jsdoc-documentation src/border-radius.js docs/cssHelpers/border-radius.md 12 | npm run jsdoc-documentation src/breakpoints.js docs/cssHelpers/breakpoints.md 13 | npm run jsdoc-documentation src/gridbreakpoints.js docs/cssHelpers/gridbreakpoints.md 14 | npm run jsdoc-documentation src/clearfix.js docs/cssHelpers/clearfix.md 15 | npm run jsdoc-documentation src/float.js docs/cssHelpers/float.md 16 | npm run jsdoc-documentation src/gradients.js docs/cssHelpers/gradients.md 17 | npm run jsdoc-documentation src/lists.js docs/cssHelpers/lists.md 18 | npm run jsdoc-documentation src/nav-divider.js docs/cssHelpers/nav-divider.md 19 | npm run jsdoc-documentation src/screen-reader.js docs/cssHelpers/screen-reader.md 20 | npm run jsdoc-documentation src/size.js docs/cssHelpers/size.md 21 | npm run jsdoc-documentation src/text-emphasis.js docs/cssHelpers/text-emphasis.md 22 | npm run jsdoc-documentation src/text-hide.js docs/cssHelpers/text-hide.md 23 | npm run jsdoc-documentation src/text-truncate.js docs/cssHelpers/text-truncate.md 24 | npm run jsdoc-documentation src/visibility.js docs/cssHelpers/visibility.md 25 | 26 | npm run jsdoc-documentation src/box-shadow.js docs/conditionals/box-shadow.md 27 | npm run jsdoc-documentation src/conditional.js docs/conditionals/conditional.md 28 | npm run jsdoc-documentation src/hover.js docs/conditionals/hover.md 29 | npm run jsdoc-documentation src/transition.js docs/conditionals/transition.md 30 | -------------------------------------------------------------------------------- /styleguide/prepare.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | npx @rollup-umd/documentation-cli variable \ 4 | PACKAGE_NAME=$(node -p "require('./package.json').name") \ 5 | PACKAGE_PEERS="$(npx rollup-umd-scripts peer npm-install-cmd)" \ 6 | PACKAGE_VERSION=$(node -p "require('./package.json').version") \ 7 | NODE_VERSION=$(node --version) \ 8 | NPM_VERSION=$(npm --version) \ 9 | CI_REPOSITORY_URL="https://github.com/${TRAVIS_REPO_SLUG}.git" \ 10 | CI_PROJECT_URL="https://github.com/${TRAVIS_REPO_SLUG}" \ 11 | CI_PROJECT_NAMESPACE=$(echo $TRAVIS_REPO_SLUG | awk -F / '{print $1}') \ 12 | CI_PROJECT_NAME=$(echo $TRAVIS_REPO_SLUG | awk -F / '{print $2}') \ 13 | DECLINATION_LIST="$(npx rollup-umd-scripts declination list --with-link)" \ 14 | IMG_SHIELD_PUBLISHING=$(npx rollup-umd-scripts publish status --badge) 15 | 16 | npx @rollup-umd/documentation-cli add-section -n 'Code of conduct' -a 'FAQ' -c 'CODE_OF_CONDUCT.md' --force 17 | npx @rollup-umd/documentation-cli add-section -n 'Changelog' -a 'Code of conduct' -c 'CHANGELOG.md' --force 18 | -------------------------------------------------------------------------------- /styleguide/setup.js: -------------------------------------------------------------------------------- 1 | /* Ignored components needed to be used in example */ 2 | -------------------------------------------------------------------------------- /styleguide/styleguide.ext.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": [ 3 | "**/__tests__/**", 4 | "**/*.test.{js,jsx,ts,tsx}", 5 | "**/*.spec.{js,jsx,ts,tsx}", 6 | "**/*.d.ts" 7 | ], 8 | "pagePerSection": true, 9 | "sections": [ 10 | { 11 | "name": "Introduction", 12 | "content": "docs/introduction.md" 13 | }, 14 | { 15 | "name": "Prerequisite", 16 | "content": "docs/prerequisite.md" 17 | }, 18 | { 19 | "name": "Getting started", 20 | "content": "docs/getting-started.md", 21 | "sections": [ 22 | { 23 | "name": "Installation", 24 | "content": "docs/installation.md" 25 | }, 26 | { 27 | "name": "Configuration", 28 | "content": "docs/configuration.md" 29 | } 30 | ] 31 | }, 32 | { 33 | "name": "Component specific", 34 | "sections": [ 35 | { 36 | "name": "Anchor", 37 | "content": "docs/componentSpecific/a.md" 38 | }, 39 | { 40 | "name": "Alert", 41 | "content": "docs/componentSpecific/alert.md" 42 | }, 43 | { 44 | "name": "Badge", 45 | "content": "docs/componentSpecific/badge.md" 46 | }, 47 | { 48 | "name": "ListGroup", 49 | "content": "docs/componentSpecific/list-group.md" 50 | }, 51 | { 52 | "name": "Media", 53 | "content": "docs/componentSpecific/media.md" 54 | }, 55 | { 56 | "name": "Navbar align", 57 | "content": "docs/componentSpecific/navbar-align.md" 58 | } 59 | ], 60 | "sectionDepth": 0 61 | }, 62 | { 63 | "name": "Css helpers", 64 | "sections": [ 65 | { 66 | "name": "Background-variant", 67 | "content": "docs/cssHelpers/background-variant.md" 68 | }, 69 | { 70 | "name": "Border-radius", 71 | "content": "docs/cssHelpers/border-radius.md" 72 | }, 73 | { 74 | "name": "Grid breakpoints", 75 | "content": "docs/cssHelpers/gridbreakpoints.md" 76 | }, 77 | { 78 | "name": "Clearfix", 79 | "content": "docs/cssHelpers/clearfix.md" 80 | }, 81 | { 82 | "name": "Float", 83 | "content": "docs/cssHelpers/float.md" 84 | }, 85 | { 86 | "name": "Gradients", 87 | "content": "docs/cssHelpers/gradients.md" 88 | }, 89 | { 90 | "name": "Lists", 91 | "content": "docs/cssHelpers/lists.md" 92 | }, 93 | { 94 | "name": "Nav divider", 95 | "content": "docs/cssHelpers/nav-divider.md" 96 | }, 97 | { 98 | "name": "Screen reader", 99 | "content": "docs/cssHelpers/screen-reader.md" 100 | }, 101 | { 102 | "name": "Size", 103 | "content": "docs/cssHelpers/size.md" 104 | }, 105 | { 106 | "name": "Text emphasis", 107 | "content": "docs/cssHelpers/text-emphasis.md" 108 | }, 109 | { 110 | "name": "Text hide", 111 | "content": "docs/cssHelpers/text-hide.md" 112 | }, 113 | { 114 | "name": "Text truncate", 115 | "content": "docs/cssHelpers/text-truncate.md" 116 | }, 117 | { 118 | "name": "Visibility", 119 | "content": "docs/cssHelpers/visibility.md" 120 | } 121 | ] 122 | }, 123 | { 124 | "name": "Conditionals", 125 | "sections": [ 126 | { 127 | "name": "Box-shadow", 128 | "content": "docs/conditionals/box-shadow.md" 129 | }, 130 | { 131 | "name": "Conditional", 132 | "content": "docs/conditionals/conditional.md" 133 | }, 134 | { 135 | "name": "Hover", 136 | "content": "docs/conditionals/hover.md" 137 | }, 138 | { 139 | "name": "Transition", 140 | "content": "docs/conditionals/transition.md" 141 | } 142 | ] 143 | }, 144 | { 145 | "name": "FAQ", 146 | "content": "docs/faq.md" 147 | }, 148 | { 149 | "name": "Contribute", 150 | "content": "docs/contribute.md", 151 | "sections": [ 152 | { 153 | "name": "Commands", 154 | "content": "docs/commands.md" 155 | }, 156 | { 157 | "name": "Branches", 158 | "content": "docs/branches.md" 159 | }, 160 | { 161 | "name": "Release", 162 | "content": "docs/release.md" 163 | } 164 | ] 165 | } 166 | ], 167 | "ribbon": { 168 | "url": "https://github.com/bootstrap-styled/css-mixins", 169 | "text": "Fork us on GitHub" 170 | } 171 | } 172 | --------------------------------------------------------------------------------