├── .editorconfig ├── .eslintignore ├── .gitignore ├── .ncurc.js ├── .npmignore ├── .npmrc ├── .travis.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── LICENSE.md ├── README.md ├── babel.config.js ├── declination.json ├── docs ├── branches.md ├── commands.md ├── configuration.md ├── contribute.md ├── faq.md ├── getting-started.md ├── installation.md ├── introduction.md ├── parseTransition.md ├── prerequisite.md ├── release.md ├── tools.md └── unitUtils.md ├── index.d.ts ├── package.json ├── rollup.config.js ├── sonar-project.properties ├── src ├── index.js ├── parseTransition.js ├── tests │ ├── index.test.js │ ├── parseTransition.test.js │ └── tools.test.js ├── tools.js └── unitUtils │ ├── index.js │ └── tests │ └── index.test.js ├── styleguide.config.js └── styleguide ├── favicon.ico ├── 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 | -------------------------------------------------------------------------------- /.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.config.js 7 | babel.ext.json 8 | .editorconfig 9 | .eslintignore 10 | bundle-stats.html 11 | CODE_OF_CONDUCT.md 12 | CHANGELOG.md 13 | README.md 14 | CONTRIBUTING.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 | index.d.ts 26 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: required 3 | dist: trusty 4 | 5 | # Blocklist 6 | branches: 7 | except: 8 | - gh-pages # will be deployed to, no need to build it 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 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [1.8.1](https://github.com/bootstrap-styled/utils/compare/v1.8.0...v1.8.1) (2019-09-26) 2 | 3 | 4 | ### Bug Fixes 5 | 6 | * **typescripts:** disable typescript due to https://github.com/bootstrap-styled/bootstrap-styled/issues/83#issuecomment-535666014 ([2779615](https://github.com/bootstrap-styled/utils/commit/2779615)), closes [/github.com/bootstrap-styled/bootstrap-styled/issues/83#issuecomment-535666014](https://github.com//github.com/bootstrap-styled/bootstrap-styled/issues/83/issues/issuecomment-535666014) 7 | 8 | # [1.8.0](https://github.com/bootstrap-styled/utils/compare/v1.7.1...v1.8.0) (2019-08-04) 9 | 10 | 11 | ### Features 12 | 13 | * **typescript:** added typescript definition ([31a719b](https://github.com/bootstrap-styled/utils/commit/31a719b)) 14 | 15 | ## [1.7.1](https://github.com/bootstrap-styled/utils/compare/v1.7.0...v1.7.1) (2018-12-16) 16 | 17 | 18 | ### Bug Fixes 19 | 20 | * **dependencies:** updated babel dependencies ([a89fb41](https://github.com/bootstrap-styled/utils/commit/a89fb41)) 21 | 22 | # [1.7.0](https://github.com/bootstrap-styled/utils/compare/v1.6.4...v1.7.0) (2018-12-16) 23 | 24 | 25 | ### Bug Fixes 26 | 27 | * **dependencies:** upgrade [@rollup-umd](https://github.com/rollup-umd)/documentation ([67edbce](https://github.com/bootstrap-styled/utils/commit/67edbce)) 28 | * **test:** fix test report path ([c6854db](https://github.com/bootstrap-styled/utils/commit/c6854db)) 29 | 30 | 31 | ### Features 32 | 33 | * **dependencies:** babel7, latest rollup, latest jest... ([0ff563d](https://github.com/bootstrap-styled/utils/commit/0ff563d)) 34 | 35 | ## [1.6.4](https://github.com/bootstrap-styled/utils/compare/v1.6.3...v1.6.4) (2018-12-05) 36 | 37 | 38 | ### Bug Fixes 39 | 40 | * **documentation:** corrected wrong exmaples and ribbon. ([6043b71](https://github.com/bootstrap-styled/utils/commit/6043b71)) 41 | 42 | ## [1.6.3](https://github.com/bootstrap-styled/utils/compare/v1.6.2...v1.6.3) (2018-12-05) 43 | 44 | 45 | ### Bug Fixes 46 | 47 | * **dependencies:** added missing webpack dependency. ([79d6927](https://github.com/bootstrap-styled/utils/commit/79d6927)) 48 | * **misc:** removed useless console.log(). ([843f939](https://github.com/bootstrap-styled/utils/commit/843f939)) 49 | 50 | ## [1.6.2](https://github.com/bootstrap-styled/utils/compare/v1.6.1...v1.6.2) (2018-12-05) 51 | 52 | 53 | ### Bug Fixes 54 | 55 | * **documentation:** added new [@rollup-umd](https://github.com/rollup-umd)/documentation. ([1270f84](https://github.com/bootstrap-styled/utils/commit/1270f84)) 56 | * **documentation:** added working documentation ([fc8d89f](https://github.com/bootstrap-styled/utils/commit/fc8d89f)) 57 | 58 | ## [1.6.1](https://github.com/bootstrap-styled/utils/compare/v1.6.0...v1.6.1) (2018-11-05) 59 | 60 | 61 | ### Bug Fixes 62 | 63 | * **release:** GitHub release https://github.com/bootstrap-styled/utils ([c6c9cbf](https://github.com/bootstrap-styled/utils/commit/c6c9cbf)) 64 | 65 | # [1.6.0](https://module.kopaxgroup.com/bootstrap-styled/utils/compare/v1.5.1...v1.6.0) (2018-11-05) 66 | 67 | 68 | ### Features 69 | 70 | * **gh:** release to GH ([0b2426e](https://module.kopaxgroup.com/bootstrap-styled/utils/commit/0b2426e)) 71 | 72 | ## [1.0.4](https://module.kopaxgroup.com/bootstrap-styled/utils/compare/v1.0.3...v1.0.4) (2018-10-02) 73 | 74 | 75 | ### Bug Fixes 76 | 77 | * **package.json:** corrected wrong configuration with publishConfig ([f099e0c](https://module.kopaxgroup.com/bootstrap-styled/utils/commit/f099e0c)) 78 | 79 | ## [1.0.3](https://module.kopaxgroup.com/bootstrap-styled/utils/compare/v1.0.2...v1.0.3) (2018-10-02) 80 | 81 | 82 | ### Bug Fixes 83 | 84 | * **package.json:** npm repo + rollup-umd-doc 2.3.19 ([e737c60](https://module.kopaxgroup.com/bootstrap-styled/utils/commit/e737c60)) 85 | 86 | ## [1.0.2](https://module.kopaxgroup.com/bootstrap-styled/utils/compare/v1.0.1...v1.0.2) (2018-09-26) 87 | 88 | 89 | ### Bug Fixes 90 | 91 | * **packge.json:** remnoved rollup-documentation ([26b15c7](https://module.kopaxgroup.com/bootstrap-styled/utils/commit/26b15c7)) 92 | 93 | ## [1.0.1](https://module.kopaxgroup.com/bootstrap-styled/utils/compare/v1.0.0...v1.0.1) (2018-09-17) 94 | 95 | 96 | ### Bug Fixes 97 | 98 | * **package.json:** added testUrl to jest config to fix localstorage bug ([c7d2c0e](https://module.kopaxgroup.com/bootstrap-styled/utils/commit/c7d2c0e)) 99 | 100 | # 1.0.0 (2018-09-17) 101 | 102 | 103 | ### Bug Fixes 104 | 105 | * **build:** repair release step. ([9884830](https://module.kopaxgroup.com/bootstrap-styled/utils/commit/9884830)) 106 | * **ci:** build ([448a33f](https://module.kopaxgroup.com/bootstrap-styled/utils/commit/448a33f)) 107 | * **deps:** remove devDeps ([4dc93a5](https://module.kopaxgroup.com/bootstrap-styled/utils/commit/4dc93a5)) 108 | * **deps:** remove devDeps ([84fb987](https://module.kopaxgroup.com/bootstrap-styled/utils/commit/84fb987)) 109 | * **gitignore:** added some of the new files ([26e1913](https://module.kopaxgroup.com/bootstrap-styled/utils/commit/26e1913)) 110 | * **package.json:** added missins scripts and corrected a wrong url. ([24bc60c](https://module.kopaxgroup.com/bootstrap-styled/utils/commit/24bc60c)) 111 | * **package.json:** changed authors to author and supplied string instead of array ([59959a9](https://module.kopaxgroup.com/bootstrap-styled/utils/commit/59959a9)) 112 | * **package.json:** Merge mistake ([816506b](https://module.kopaxgroup.com/bootstrap-styled/utils/commit/816506b)) 113 | * **package.json:** testing CI ([aeaee30](https://module.kopaxgroup.com/bootstrap-styled/utils/commit/aeaee30)) 114 | * **package.json:** testing release isue by settings version manuelly ([9526637](https://module.kopaxgroup.com/bootstrap-styled/utils/commit/9526637)) 115 | * **package.json:** version number to rectify previous bug.. ([4ae5f89](https://module.kopaxgroup.com/bootstrap-styled/utils/commit/4ae5f89)) 116 | * **url:** now using url .com for repo ([ec5513e](https://module.kopaxgroup.com/bootstrap-styled/utils/commit/ec5513e)) 117 | * README, docs and url ([f4152c3](https://module.kopaxgroup.com/bootstrap-styled/utils/commit/f4152c3)) 118 | 119 | # Changelog 120 | 121 | All notable changes to this project will be documented in this file. 122 | 123 | ## [?NEXT?] - ????-??-?? 124 | 125 | - TODO: write changelog before preparing next tag 126 | 127 | ## [v1.0.2] - 2018-09-17 128 | 129 | - Upgrade ci docker image. 130 | 131 | ## [v1.0.2] - 2018-04-16 132 | 133 | - Protected. 134 | - License MIT. 135 | - Add dependency [ci-publish](https://www.npmjs.com/package/ci-publish) ^1.3.1. 136 | 137 | ## [1.0.1] - 2019-01-30 138 | 139 | - Added function `createChainedFunction` which only create a new function if needed, otherwise will pass back existing functions or null. 140 | - Added function `pick` which returns a filtered copy of an object with only the specified keys. 141 | 142 | ## [1.0.0] - 2017-09-26 143 | 144 | - Release as v1, no change. 145 | 146 | ## [0.0.6] - 2017-09-25 147 | 148 | - Added dummy default export. 149 | 150 | ## [0.0.5] - 2017-09-25 151 | 152 | - Removed default exports for all exports. 153 | 154 | ## [0.0.4] - 2017-09-25 155 | 156 | - Using default exports for all exports. 157 | 158 | ## [0.0.3] - 2017-09-25 159 | 160 | - Using named export in `index.js`. 161 | 162 | ## [0.0.2] - 2017-09-25 163 | 164 | - Added `unitUtils`. 165 | 166 | ## [0.0.1] - 2017-09-25 167 | 168 | - First release. 169 | -------------------------------------------------------------------------------- /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 agd@kopaxgroup.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 | -------------------------------------------------------------------------------- /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 | # utils 2 | 3 | [![Build Status](https://travis-ci.org/bootstrap-styled/utils.svg?branch=master)](https://travis-ci.org/bootstrap-styled/utils) 4 | [![npm Version](https://img.shields.io/npm/v/@bootstrap-styled/utils.svg?style=flat)](https://www.npmjs.com/package/@bootstrap-styled/utils) 5 | [![License](https://img.shields.io/npm/l/@bootstrap-styled/utils.svg?style=flat)](https://www.npmjs.com/package/@bootstrap-styled/utils) 6 | [![NPM monthly downloads](https://img.shields.io/npm/dm/@bootstrap-styled/utils.svg?style=flat)](https://npmjs.org/package/@bootstrap-styled/utils) 7 | [![NPM total downloads](https://img.shields.io/npm/dt/@bootstrap-styled/utils.svg?style=flat)](https://npmjs.org/package/@bootstrap-styled/utils) 8 | [![npm Version](https://img.shields.io/node/v/@bootstrap-styled/utils.svg?style=flat)](https://www.npmjs.com/package/@bootstrap-styled/utils) 9 | [![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/utils) 10 | [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=com.github.bootstrap-styled.utils&metric=coverage)](https://sonarcloud.io/api/project_badges/measure?project=com.github.bootstrap-styled.utils&metric=coverage) 11 | [![Quality gate status](https://sonarcloud.io/api/project_badges/measure?project=com.github.bootstrap-styled.utils&metric=alert_status)](https://sonarcloud.io/api/project_badges/measure?project=com.github.bootstrap-styled.utils&metric=alert_status) 12 | [![gitter](https://badges.gitter.im/bootstrap-styled/bootstrap-styled.svg)](https://gitter.im/bootstrap-styled) 13 | [![Greenkeeper badge](https://badges.greenkeeper.io/bootstrap-styled/utils.svg)](https://greenkeeper.io/) 14 | 15 | UMD module for helper functions used as utilities for bootstrap-styled and other related modules 16 | 17 | 18 | ## Table of Contents 19 | 20 | - [Documentation](#documentation) 21 | - [Contributing](#contributing) 22 | - [License MIT](#license-mit) 23 | 24 | --- 25 | 26 | ## Documentation 27 | 28 | Read [utils documentation](https://bootstrap-styled.github.io/utils). 29 | 30 | 31 | ## Contributing 32 | 33 | If you want to contribute to utils please see our [contributing and community guidelines](https://github.com/bootstrap-styled/utils/blob/master/CONTRIBUTING.md), they\'ll help you get set up locally and explain the whole process. 34 | 35 | Please also note that all repositories under the bootstrap-styled organization follow our [Code of Conduct](https://github.com/bootstrap-styled/utils/blob/master/CODE_OF_CONDUCT.md), make sure to review and follow it. 36 | 37 | ## License MIT 38 | 39 | The MIT License 40 | 41 | Copyright (c) 2017-2018 Yeutech Company Limited. https://bootstrap-styled.yeutech.com 42 | 43 | Permission is hereby granted, free of charge, to any person obtaining a copy 44 | of this software and associated documentation files (the "Software"), to deal 45 | in the Software without restriction, including without limitation the rights 46 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 47 | copies of the Software, and to permit persons to whom the Software is 48 | furnished to do so, subject to the following conditions: 49 | 50 | The above copyright notice and this permission notice shall be included in 51 | all copies or substantial portions of the Software. 52 | 53 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 54 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 55 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 56 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 57 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 58 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 59 | THE SOFTWARE. 60 | 61 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | only: [ 3 | 'src', 4 | ], 5 | presets: [ 6 | [ 7 | '@babel/preset-env', 8 | { 9 | modules: false, 10 | }, 11 | ], 12 | ], 13 | plugins: [ 14 | 'array-includes', 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 | -------------------------------------------------------------------------------- /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/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/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 git+$CI_REPOSITORY_URL --save 3 | ``` 4 | -------------------------------------------------------------------------------- /docs/introduction.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/bootstrap-styled/utils.svg?branch=master)](https://travis-ci.org/bootstrap-styled/utils) 2 | [![npm Version](https://img.shields.io/npm/v/@bootstrap-styled/utils.svg?style=flat)](https://www.npmjs.com/package/@bootstrap-styled/utils) 3 | [![License](https://img.shields.io/npm/l/@bootstrap-styled/utils.svg?style=flat)](https://www.npmjs.com/package/@bootstrap-styled/utils) 4 | [![npm Version](https://img.shields.io/node/v/@bootstrap-styled/utils.svg?style=flat)](https://www.npmjs.com/package/@bootstrap-styled/utils) 5 | [![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/utils) 6 | 7 | UMD module for helper functions used as utilities for bootstrap-styled and other related modules 8 | -------------------------------------------------------------------------------- /docs/parseTransition.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## parseTransition 4 | 5 | Used to extract parameters from a css animation. Multiple transition can be declared with a comma separated list) 6 | 7 | ### Parameters 8 | 9 | - `transitions` **[String][1]** 10 | 11 | ### Examples 12 | 13 | ```javascript 14 | import parseTransition from '@bootstrap-styled/utils/lib/parseTransition'; 15 | 16 | const parsedTransition = parseTransition(['height .35s ease', 'fade .5 ease-out']); 17 | 18 | // OUTPUT [{ timingFunction: 'height', duration: '.35s', property: 'height'}, { timingFunction: 'ease-out', duration: '.5s', property: 'fade'}] 19 | ``` 20 | 21 | Returns **[Array][2]** will return an array of transition. 22 | 23 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 24 | 25 | [2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array 26 | -------------------------------------------------------------------------------- /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 | 3 | It will also prepare a next version in `dev`. 4 | 5 | Before each release, members should check the [Changelog](CHANGELOG.md) that it is well filled with all change. 6 | 7 | If the next version is a patch or major update, edit the version in `package.json` then merge your change into `master`. 8 | 9 | If the next version is a bug fix, just merge your change into `master`. 10 | -------------------------------------------------------------------------------- /docs/tools.md: -------------------------------------------------------------------------------- 1 | Different tools used for more specific cases or Components. 2 | 3 | 4 | #### Placement 5 | * getTetherAttachments() and tetherAttachements. 6 | 7 | Switch method that combines placements and array of placements. Mainly used for `Tooltip`. 8 | 9 | ```js static 10 | 11 | export const tetherAttachements = [ 12 | 'top', 13 | 'bottom', 14 | 'left', 15 | 'right', 16 | 'top left', 17 | 'top center', 18 | 'top right', 19 | 'right top', 20 | 'right middle', 21 | 'right bottom', 22 | 'bottom right', 23 | 'bottom center', 24 | 'bottom left', 25 | 'left top', 26 | 'left middle', 27 | 'left bottom', 28 | ]; 29 | 30 | ``` 31 | 32 | #### Scrollbar 33 | Used mainly for `Modal`. 34 | 35 | * getScrollbarWidth(). 36 | * setScrollbarWidth(). 37 | * isBodyOverflowing(). 38 | * getOriginalBodyPadding(). 39 | * conditionallyUpdateScrollbar(). 40 | 41 | #### Misc 42 | * toHashCode(). 43 | Generate a hash from a string. 44 | 45 | * createChainedFunction(). 46 | Will only create a new function if needed, 47 | otherwise will pass back existing functions or null. 48 | 49 | * pick(). 50 | Returns a filtered copy of an object with only the specified keys. 51 | -------------------------------------------------------------------------------- /docs/unitUtils.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## math 4 | 5 | Math operations accepting units value and return calculated result with unit. 6 | 7 | ### Examples 8 | 9 | ```javascript 10 | import unitUtils from '@bootstrap-styled/utils/lib/unitUtils'; 11 | 12 | const { math } = unitUtils; 13 | 14 | const add = math.addition('15px' + '23px'); 15 | // OUTPUT '38px'; 16 | const sub = math.substract('1.5em' + '2.3em'); 17 | // OUTPUT '3.8em'; 18 | const mult = math.multiply('15px' * 0.5); 19 | // OUTPUT '7.5px'; 20 | const div = math.divide('15px' / 5); 21 | // OUTPUT '3px'; 22 | ``` 23 | 24 | ## detectUnit 25 | 26 | Return the unit from a string by priority : px/rem/em/percent 27 | 28 | ### Parameters 29 | 30 | - `value` **[String][1]** 31 | 32 | ### Examples 33 | 34 | ```javascript 35 | import unitUtils from '@bootstrap-styled/utils/lib/unitUtils'; 36 | const { detectUnit } = unitUtils; 37 | 38 | const spacer = '1rem'; 39 | const detectedUnit = detectUnit(spacer); 40 | 41 | // OUTPUT 'rem' 42 | ``` 43 | 44 | Returns **[String][1]** a unit. 45 | 46 | ## rmUnit 47 | 48 | Convert a value string to float. If unit is undefined, it will try to guess it's value using {detectUnit} 49 | 50 | ### Parameters 51 | 52 | - `value` **[String][1]** 53 | - `unit` **[String][1]** 54 | 55 | ### Examples 56 | 57 | ```javascript 58 | import unitUtils from '@bootstrap-styled/utils/lib/unitUtils'; 59 | const { detectUnit, rmUnit } = unitUtils; 60 | 61 | const spacer = '1rem'; 62 | const spacerHalved' = rmUnit(spacer, detectedUnit) / 2 + detectedUnit); 63 | 64 | // OUTPUT '.5rem' 65 | ``` 66 | 67 | Returns **[Number][2]** without it's unit 68 | 69 | ## toPercent 70 | 71 | toPercent 72 | 73 | ### Parameters 74 | 75 | - `value` **[Number][2]** 76 | - `total` (optional, default `100`) 77 | - `decimal` **[Number][2]** (default: 2) (optional, default `2`) 78 | - `input` **[Number][2]** (optional, default `100`) 79 | 80 | ### Examples 81 | 82 | ```javascript 83 | import unitUtils from '@bootstrap-styled/utils/lib/unitUtils'; 84 | const { toPercent } = unitUtils; 85 | 86 | const percentage = toPercent(20, 100, 10); 87 | 88 | // OUTPUT '20%' 89 | ``` 90 | 91 | Returns **[string][1]** percentage value 92 | 93 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String 94 | 95 | [2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number 96 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | declare module '@bootstrap-styled/utils' { 2 | export function getTetherAttachments( 3 | placement: string 4 | ): { 5 | attachment: string; 6 | targetAttachment: string; 7 | }; 8 | 9 | export const tetherAttachements = [ 10 | 'top', 11 | 'bottom', 12 | 'left', 13 | 'right', 14 | 'top left', 15 | 'top center', 16 | 'top right', 17 | 'right top', 18 | 'right middle', 19 | 'right bottom', 20 | 'bottom right', 21 | 'bottom center', 22 | 'bottom left', 23 | 'left top', 24 | 'left middle', 25 | 'left bottom' 26 | ]; 27 | 28 | export function getScrollbarWidth(): number; 29 | export function setScrollbarWidth(padding: number): void; 30 | export function isBodyOverflowing(): boolean; 31 | export function getOriginalBodyPadding(): number; 32 | export function conditionallyUpdateScrollbar(): void; 33 | export function toHashCode(str: srting): string; 34 | export function createChainedFunction(...funcs: function[]): function; 35 | export function pick(obj: object, keys: string[]): object; 36 | 37 | export const parseTransition: ( 38 | transitions: string[] 39 | ) => ({ 40 | property: string; 41 | duration: string; 42 | timingFunction: string; 43 | delay: string; 44 | })[]; 45 | 46 | export class UnitUtils { 47 | public UNIT: { 48 | EM: 'em'; 49 | REM: 'rem'; 50 | PX: 'px'; 51 | PERCENT: '%'; 52 | }; 53 | 54 | public math: { 55 | addition: (a: string, b: string) => string; 56 | subtract: (a: string, b: string) => string; 57 | multiply: (a: string, b: string) => string; 58 | divide: (a: string, b: string) => string; 59 | }; 60 | 61 | public detectUnit: (value: string) => string; 62 | 63 | public rmUnit: (value: string, unit?: string) => number; 64 | 65 | public toPercent: ( 66 | value: number, 67 | total?: number, 68 | decimal?: number 69 | ) => string; 70 | } 71 | 72 | export const unitUtils: UnitUtils; 73 | } 74 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@bootstrap-styled/utils", 3 | "version": "1.8.1", 4 | "description": "UMD module for helper functions used as utilities for bootstrap-styled and other related modules", 5 | "main": "lib/index.js", 6 | "jsnext:main": "dist/@bootstrap-styled/utils.es.js", 7 | "module": "dist/@bootstrap-styled/utils.es.js", 8 | "homepage": "https://bootstrap-styled.github.io/utils", 9 | "engines": { 10 | "node": ">=8" 11 | }, 12 | "browserslist": [ 13 | "IE >= 9", 14 | "last 2 versions" 15 | ], 16 | "scripts": { 17 | "prebuild": "npm run build:clean", 18 | "build": "npm run build:lib", 19 | "prebuild:lib": "rimraf lib/*", 20 | "build:lib": "BABEL_ENV=production babel --out-dir lib src --copy-files", 21 | "build:clean": "rimraf lib/*", 22 | "build:readme": "toctoc README.md -w", 23 | "build:lib:watch": "npm run build:lib -- --watch", 24 | "test": "npm run lint && npm run test:web", 25 | "test:web": "NODE_ENV=test jest --coverage", 26 | "test:clean": "rimraf ./coverage", 27 | "test:watch": "npm run test -- --watch", 28 | "lint": "eslint src", 29 | "prepublish": "npm run build", 30 | "lint-staged": "lint-staged", 31 | "jsdoc-documentation": "jsdoc-documentation", 32 | "jsdoc": "jsdoc-documentation --file", 33 | "prestyleguide": "npm run jsdoc", 34 | "styleguide": "styleguidist server", 35 | "prestyleguide:build": "npm run jsdoc", 36 | "styleguide:build": "styleguidist build" 37 | }, 38 | "repository": { 39 | "type": "git", 40 | "url": "https://github.com/bootstrap-styled/utils.git" 41 | }, 42 | "bugs": { 43 | "url": "https://github.com/bootstrap-styled/utils/issues" 44 | }, 45 | "keywords": [ 46 | "styled-components", 47 | "bootstrap-styled", 48 | "react", 49 | "bootstrap", 50 | "styled" 51 | ], 52 | "author": "Dimitri Kopriwa ", 53 | "license": "MIT", 54 | "eslintConfig": { 55 | "parser": "babel-eslint", 56 | "extends": "airbnb-base", 57 | "env": { 58 | "browser": true, 59 | "node": true, 60 | "jest": true, 61 | "es6": true 62 | }, 63 | "parserOptions": { 64 | "ecmaVersion": 6, 65 | "sourceType": "module" 66 | }, 67 | "rules": { 68 | "arrow-parens": [ 69 | "error", 70 | "always" 71 | ], 72 | "arrow-body-style": [ 73 | 2, 74 | "as-needed" 75 | ], 76 | "comma-dangle": [ 77 | 2, 78 | "always-multiline" 79 | ], 80 | "import/imports-first": 0, 81 | "import/newline-after-import": 0, 82 | "import/no-dynamic-require": 0, 83 | "import/no-extraneous-dependencies": 0, 84 | "import/no-named-as-default": 0, 85 | "import/no-unresolved": 2, 86 | "import/prefer-default-export": 0, 87 | "indent": [ 88 | 2, 89 | 2, 90 | { 91 | "SwitchCase": 1 92 | } 93 | ], 94 | "max-len": 0, 95 | "newline-per-chained-call": 0, 96 | "no-confusing-arrow": 0, 97 | "no-console": 1, 98 | "no-use-before-define": 0, 99 | "prefer-template": 2, 100 | "class-methods-use-this": 0, 101 | "require-yield": 0 102 | } 103 | }, 104 | "devDependencies": { 105 | "@babel/cli": "^7.4.4", 106 | "@babel/core": "^7.4.5", 107 | "@babel/plugin-external-helpers": "^7.2.0", 108 | "@babel/plugin-proposal-class-properties": "^7.4.4", 109 | "@babel/plugin-proposal-decorators": "^7.4.4", 110 | "@babel/plugin-proposal-json-strings": "^7.2.0", 111 | "@babel/plugin-proposal-object-rest-spread": "^7.4.4", 112 | "@babel/plugin-syntax-dynamic-import": "^7.2.0", 113 | "@babel/plugin-syntax-import-meta": "^7.2.0", 114 | "@babel/plugin-transform-modules-commonjs": "^7.4.4", 115 | "@babel/preset-env": "^7.4.5", 116 | "@bootstrap-styled/documentation": "^2.0.0", 117 | "@rollup-umd/documentation": "^2.0.5", 118 | "@rollup-umd/ncu": "^1.0.9", 119 | "@rollup-umd/rollup": "^1.0.13", 120 | "@semantic-release/changelog": "^3.0.4", 121 | "@semantic-release/git": "^7.0.12", 122 | "@semantic-release/github": "^5.4.0", 123 | "@semantic-release/npm": "^5.1.9", 124 | "babel-eslint": "^10.0.2", 125 | "babel-jest": "^24.8.0", 126 | "babel-loader": "^8.0.6", 127 | "babel-plugin-add-module-exports": "^1.0.2", 128 | "babel-plugin-array-includes": "^2.0.3", 129 | "babel-plugin-dynamic-import-node": "^2.2.0", 130 | "eslint": "^5.10.0", 131 | "eslint-config-airbnb-base": "^13.1.0", 132 | "eslint-plugin-import": "^2.17.3", 133 | "jest-cli": "^24.8.0", 134 | "jest-sonar-reporter": "^2.0.0", 135 | "lint-staged": "^8.1.0", 136 | "pre-commit": "^1.2.2", 137 | "react-styleguidist": "^9.1.7", 138 | "rimraf": "^2.6.2", 139 | "rollup": "^1.15.6", 140 | "semantic-release": "^15.13.0", 141 | "toctoc": "^0.3.2", 142 | "webpack": "^4.27.1" 143 | }, 144 | "jest": { 145 | "roots": [ 146 | "/src/" 147 | ], 148 | "testURL": "http://localhost/", 149 | "transformIgnorePatterns": [ 150 | "/node_modules", 151 | "/internals" 152 | ], 153 | "testPathIgnorePatterns": [ 154 | "/dist/", 155 | "/lib/" 156 | ], 157 | "collectCoverageFrom": [ 158 | "src/**/*.{js,jsx}", 159 | "!src/**/*.test.{js,jsx}" 160 | ], 161 | "coverageThreshold": { 162 | "global": { 163 | "statements": 96, 164 | "branches": 84, 165 | "functions": 91, 166 | "lines": 96 167 | } 168 | }, 169 | "moduleDirectories": [ 170 | "node_modules", 171 | "src" 172 | ], 173 | "testRegex": "tests/.*\\.test\\.js$", 174 | "testResultsProcessor": "jest-sonar-reporter" 175 | }, 176 | "jestSonar": { 177 | "reportPath": "reports", 178 | "reportFile": "test-report.xml", 179 | "indent": 2 180 | }, 181 | "lint-staged": { 182 | "*.js": [ 183 | "eslint --fix", 184 | "git add" 185 | ] 186 | }, 187 | "pre-commit": [ 188 | "build:readme" 189 | ], 190 | "dependencies": {}, 191 | "peerDependencies": {}, 192 | "publishConfig": { 193 | "registry": "https://registry.npmjs.org", 194 | "tag": "latest", 195 | "access": "public" 196 | }, 197 | "release": { 198 | "branch": "master", 199 | "npmPublish": true, 200 | "verifyConditions": [ 201 | "@semantic-release/changelog", 202 | "@semantic-release/npm", 203 | "@semantic-release/git", 204 | "@semantic-release/github" 205 | ], 206 | "prepare": [ 207 | "@semantic-release/changelog", 208 | "@semantic-release/npm", 209 | { 210 | "path": "@semantic-release/git", 211 | "assets": [ 212 | "package.json", 213 | "src/**/*.js", 214 | "CHANGELOG.md", 215 | "README.md", 216 | "LICENSE.md" 217 | ] 218 | } 219 | ], 220 | "publish": [ 221 | "@semantic-release/npm", 222 | { 223 | "path": "@semantic-release/github", 224 | "assets": [ 225 | { 226 | "path": "package.json" 227 | }, 228 | { 229 | "path": "LICENSE.md" 230 | }, 231 | { 232 | "path": "CHANGELOG.md" 233 | }, 234 | { 235 | "path": "README.md" 236 | }, 237 | { 238 | "path": "dist/*.esm.js", 239 | "label": "ES module" 240 | }, 241 | { 242 | "path": "dist/*.esm.js.map", 243 | "label": "ES module source map" 244 | }, 245 | { 246 | "path": "dist/*.min.js", 247 | "label": "UMD compressed" 248 | }, 249 | { 250 | "path": "dist/*.min.js.map", 251 | "label": "UMD compressed source map" 252 | }, 253 | { 254 | "path": "dist/*.cjs.min.js", 255 | "label": "CJS compressed" 256 | }, 257 | { 258 | "path": "dist/*.cjs.min.js.map", 259 | "label": "CJS compressed source map" 260 | }, 261 | { 262 | "path": "lib/*.js", 263 | "label": "CJS folder" 264 | } 265 | ] 266 | } 267 | ] 268 | }, 269 | "config": { 270 | "commitizen": { 271 | "path": "./node_modules/cz-conventional-changelog" 272 | } 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /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.utils 3 | sonar.projectName=com.github.bootstrap-styled.utils 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/index.js: -------------------------------------------------------------------------------- 1 | export * from './tools'; 2 | export { default as parseTransition } from './parseTransition'; 3 | export { default as unitUtils } from './unitUtils'; 4 | -------------------------------------------------------------------------------- /src/parseTransition.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @public 3 | * @description Used to extract parameters from a css animation. Multiple transition can be declared with a comma separated list) 4 | * @param {String} transitions 5 | * @example 6 | * import parseTransition from '@bootstrap-styled/utils/lib/parseTransition'; 7 | * 8 | * const parsedTransition = parseTransition(['height .35s ease', 'fade .5 ease-out']); 9 | * 10 | * // OUTPUT [{ timingFunction: 'height', duration: '.35s', property: 'height'}, { timingFunction: 'ease-out', duration: '.5s', property: 'fade'}] 11 | * 12 | * @returns {Array} will return an array of transition. 13 | */ 14 | const parseTransition = (transitions) => { 15 | if (!transitions) { 16 | return []; 17 | } 18 | let sample = transitions; 19 | const RULE_DELIMITER = ','; 20 | const PROPERTY_DELIMITER = ' '; 21 | const MS_UNIT = 'ms'; 22 | const TMP_STR = 'TMP'; 23 | 24 | // these are default css value for each property 25 | const DEFAULT_PROPERTY = 'all'; 26 | const DEFAULT_DURATION = 0; 27 | const DEFAULT_TIMING_FUNCTION = 'ease'; 28 | const DEFAULT_DELAY = 0; 29 | 30 | // eslint-disable-next-line no-useless-escape 31 | const BEZIER_REGEX = /cubic-bezier\([^\)]+\)/gi; 32 | 33 | const cubicBezierList = transitions.match(BEZIER_REGEX); 34 | if (cubicBezierList) { 35 | sample = sample.replace(BEZIER_REGEX, TMP_STR); 36 | } 37 | 38 | const transitionList = sample.split(RULE_DELIMITER).map((rule) => { 39 | const properties = rule.trim().split(PROPERTY_DELIMITER); 40 | return { 41 | property: properties[0] || DEFAULT_PROPERTY, 42 | duration: properties[1] && !properties[1].includes(MS_UNIT) ? parseFloat(properties[1]) * 1000 : parseFloat(properties[1]) || DEFAULT_DURATION, 43 | timingFunction: properties[2] && properties[2] !== TMP_STR ? properties[2] : cubicBezierList ? cubicBezierList.shift() : DEFAULT_TIMING_FUNCTION, // eslint-disable-line no-nested-ternary 44 | delay: properties[3] && !properties[3].includes(MS_UNIT) ? parseFloat(properties[3]) * 1000 : parseFloat(properties[3]) || DEFAULT_DELAY, 45 | }; 46 | }); 47 | return transitionList; 48 | }; 49 | 50 | export default parseTransition; 51 | -------------------------------------------------------------------------------- /src/tests/index.test.js: -------------------------------------------------------------------------------- 1 | const exports = require('..'); 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/parseTransition.test.js: -------------------------------------------------------------------------------- 1 | import parseTransition from '../parseTransition'; 2 | 3 | describe('parseTransition utils', () => { 4 | it('parseTransition should return an object', () => { 5 | const objectTest = [{ 6 | delay: 350, 7 | duration: 350, 8 | property: 'height', 9 | timingFunction: 'ease', 10 | }]; 11 | const transitionList = parseTransition('height .35s ease .35s'); 12 | expect(transitionList).toEqual(objectTest); 13 | }); 14 | it('parseTransition should return a array list with string', () => { 15 | const transitionList = parseTransition('height .35s ease'); 16 | expect(transitionList[0].property).toEqual('height'); 17 | expect(transitionList[0].duration).toBe(350); 18 | expect(transitionList[0].timingFunction).toEqual('ease'); 19 | expect(transitionList[0].delay).toBe(0); 20 | }); 21 | it('should return an array with 3 transition meta data', () => { 22 | const transition = 'opacity .2s linear, display 500ms cubic-bezier(0.42, 0, 0.4, 1) .5s, background .3s cubic-bezier(0.42, 0, 1.0, 1.0) 200ms'; 23 | expect(parseTransition(transition)).toEqual([{ 24 | property: 'opacity', 25 | duration: 200, 26 | timingFunction: 'linear', 27 | delay: 0, 28 | }, { 29 | property: 'display', 30 | duration: 500, 31 | timingFunction: 'cubic-bezier(0.42, 0, 0.4, 1)', 32 | delay: 500, 33 | }, { 34 | property: 'background', 35 | duration: 300, 36 | timingFunction: 'cubic-bezier(0.42, 0, 1.0, 1.0)', 37 | delay: 200, 38 | }]); 39 | }); 40 | it('parseTransition should return an empty array', () => { 41 | expect(parseTransition().length).toBe(0); 42 | }); 43 | it('should add default value duration, timingFunction and delay', () => { 44 | const transition = 'opacity'; 45 | expect(parseTransition(transition)).toEqual([{ 46 | property: 'opacity', 47 | duration: 0, 48 | timingFunction: 'ease', 49 | delay: 0, 50 | }]); 51 | }); 52 | it('should add default value timingFunction and delay', () => { 53 | const transition = 'opacity 3s'; 54 | expect(parseTransition(transition)).toEqual([{ 55 | property: 'opacity', 56 | duration: 3000, 57 | timingFunction: 'ease', 58 | delay: 0, 59 | }]); 60 | }); 61 | it('should add default value delay', () => { 62 | const transition = 'opacity 3s cubic-bezier(1, 3, 3, 7)'; 63 | expect(parseTransition(transition)).toEqual([{ 64 | property: 'opacity', 65 | duration: 3000, 66 | timingFunction: 'cubic-bezier(1, 3, 3, 7)', 67 | delay: 0, 68 | }]); 69 | }); 70 | }); 71 | -------------------------------------------------------------------------------- /src/tests/tools.test.js: -------------------------------------------------------------------------------- 1 | import { 2 | toHashCode, 3 | setScrollbarWidth, 4 | isBodyOverflowing, 5 | getOriginalBodyPadding, 6 | conditionallyUpdateScrollbar, 7 | getTetherAttachments, 8 | getScrollbarWidth, 9 | createChainedFunction, 10 | pick, 11 | } from '../tools'; 12 | 13 | describe('tools', () => { 14 | describe('getTetherAttachments', () => { 15 | it('should returns a placement', () => { 16 | const getTetherAttachmentsTest = getTetherAttachments('top center'); 17 | expect(getTetherAttachmentsTest).toEqual({ 18 | attachment: 'bottom center', 19 | targetAttachment: 'top center', 20 | }); 21 | }); 22 | it('should returns a placement', () => { 23 | const getTetherAttachmentsTest = getTetherAttachments('bottom center'); 24 | expect(getTetherAttachmentsTest).toEqual({ 25 | attachment: 'top center', 26 | targetAttachment: 'bottom center', 27 | }); 28 | }); 29 | it('should returns a placement', () => { 30 | const getTetherAttachmentsTest = getTetherAttachments('left center'); 31 | expect(getTetherAttachmentsTest).toEqual({ 32 | attachment: 'middle right', 33 | targetAttachment: 'middle left', 34 | }); 35 | }); 36 | it('should returns a placement', () => { 37 | const getTetherAttachmentsTest = getTetherAttachments('right center'); 38 | expect(getTetherAttachmentsTest).toEqual({ 39 | attachment: 'middle left', 40 | targetAttachment: 'middle right', 41 | }); 42 | }); 43 | it('should returns a placement', () => { 44 | const getTetherAttachmentsTest = getTetherAttachments('top left'); 45 | expect(getTetherAttachmentsTest).toEqual({ 46 | attachment: 'bottom left', 47 | targetAttachment: 'top left', 48 | }); 49 | }); 50 | it('should returns a placement', () => { 51 | const getTetherAttachmentsTest = getTetherAttachments('top right'); 52 | expect(getTetherAttachmentsTest).toEqual({ 53 | attachment: 'bottom right', 54 | targetAttachment: 'top right', 55 | }); 56 | }); 57 | it('should returns a placement', () => { 58 | const getTetherAttachmentsTest = getTetherAttachments('bottom left'); 59 | expect(getTetherAttachmentsTest).toEqual({ 60 | attachment: 'top left', 61 | targetAttachment: 'bottom left', 62 | }); 63 | }); 64 | it('should returns a placement', () => { 65 | const getTetherAttachmentsTest = getTetherAttachments('bottom right'); 66 | expect(getTetherAttachmentsTest).toEqual({ 67 | attachment: 'top right', 68 | targetAttachment: 'bottom right', 69 | }); 70 | }); 71 | it('should returns a placement', () => { 72 | const getTetherAttachmentsTest = getTetherAttachments('right top'); 73 | expect(getTetherAttachmentsTest).toEqual({ 74 | attachment: 'top left', 75 | targetAttachment: 'top right', 76 | }); 77 | }); 78 | it('should returns a placement', () => { 79 | const getTetherAttachmentsTest = getTetherAttachments('right bottom'); 80 | expect(getTetherAttachmentsTest).toEqual({ 81 | attachment: 'bottom left', 82 | targetAttachment: 'bottom right', 83 | }); 84 | }); 85 | it('should returns a placement', () => { 86 | const getTetherAttachmentsTest = getTetherAttachments('left top'); 87 | expect(getTetherAttachmentsTest).toEqual({ 88 | attachment: 'top right', 89 | targetAttachment: 'top left', 90 | }); 91 | }); 92 | it('should returns a placement', () => { 93 | const getTetherAttachmentsTest = getTetherAttachments('left bottom'); 94 | expect(getTetherAttachmentsTest).toEqual({ 95 | attachment: 'bottom right', 96 | targetAttachment: 'bottom left', 97 | }); 98 | }); 99 | it('should returns a placement', () => { 100 | const getTetherAttachmentsTest = getTetherAttachments(); 101 | expect(getTetherAttachmentsTest).toEqual({ 102 | attachment: 'top center', 103 | targetAttachment: 'bottom center', 104 | }); 105 | }); 106 | }); 107 | describe('getScrollbarWidth', () => { 108 | it('should return scrollbar width equal to 0', () => { 109 | const scrollbarWidthTest = getScrollbarWidth(); 110 | expect(scrollbarWidthTest).toBe(0); 111 | }); 112 | }); 113 | 114 | describe('setScrollbarWidth', () => { 115 | it('should set document.body.style.paddingRight to null', () => { 116 | const paddingTest = 0; 117 | setScrollbarWidth(paddingTest); 118 | expect(document.body.style.paddingRight).toEqual(''); 119 | }); 120 | it('should set document.body.style.paddingRight to 10px', () => { 121 | const paddingTest = 10; 122 | setScrollbarWidth(paddingTest); 123 | expect(document.body.style.paddingRight).toEqual('10px'); 124 | }); 125 | }); 126 | 127 | describe('isBodyOverflowing', () => { 128 | it('should return true', () => { 129 | const isBodyOverflowingTest = isBodyOverflowing(); 130 | expect(isBodyOverflowingTest).toEqual(true); 131 | }); 132 | it('should return false', () => { 133 | window.innerWidth = 0; 134 | const isBodyOverflowingTest = isBodyOverflowing(); 135 | expect(isBodyOverflowingTest).toEqual(false); 136 | }); 137 | }); 138 | describe('getOriginalBodyPadding', () => { 139 | it('should return 10', () => { 140 | const originalBodyPadding = getOriginalBodyPadding(); 141 | expect(originalBodyPadding).toBe(10); 142 | }); 143 | }); 144 | 145 | describe('conditionallyUpdateScrollbar', () => { 146 | it('should return 5px', () => { 147 | const paddingTest = 5; 148 | setScrollbarWidth(paddingTest); 149 | conditionallyUpdateScrollbar(); 150 | expect(document.body.style.paddingRight).toEqual('5px'); 151 | }); 152 | }); 153 | 154 | describe('toHashCode', () => { 155 | it('toHashCode should generate an hashCode"', () => { 156 | const hash = toHashCode(JSON.stringify(getTetherAttachments())); 157 | expect(typeof hash).toEqual('number'); 158 | const hash2 = toHashCode(JSON.stringify(getTetherAttachments())); 159 | expect(hash).toEqual(hash2); 160 | }); 161 | }); 162 | 163 | describe('createChainedFunction', () => { 164 | it('createChainedFunction should return a new function', () => { 165 | let func1; 166 | func1 = (a, b) => a + b; 167 | const func2 = (a, b) => a - b; 168 | func1 = createChainedFunction(func2, func1); 169 | expect(typeof func1).toEqual('function'); 170 | }); 171 | }); 172 | 173 | describe('pick', () => { 174 | it('pick should be a function', () => { 175 | expect(typeof pick).toEqual('function'); 176 | }); 177 | it('pick should returna new object with the specified keys', () => { 178 | const obj = { a: 1, b: 2 }; 179 | expect(pick(obj, 'a')).toEqual({ a: 1 }); 180 | }); 181 | }); 182 | }); 183 | -------------------------------------------------------------------------------- /src/tools.js: -------------------------------------------------------------------------------- 1 | export function getTetherAttachments(placement) { 2 | switch (placement) { 3 | case 'top': 4 | case 'top center': 5 | return { 6 | attachment: 'bottom center', 7 | targetAttachment: 'top center', 8 | }; 9 | case 'bottom': 10 | case 'bottom center': 11 | return { 12 | attachment: 'top center', 13 | targetAttachment: 'bottom center', 14 | }; 15 | case 'left': 16 | case 'left center': 17 | return { 18 | attachment: 'middle right', 19 | targetAttachment: 'middle left', 20 | }; 21 | case 'right': 22 | case 'right center': 23 | return { 24 | attachment: 'middle left', 25 | targetAttachment: 'middle right', 26 | }; 27 | case 'top left': 28 | return { 29 | attachment: 'bottom left', 30 | targetAttachment: 'top left', 31 | }; 32 | case 'top right': 33 | return { 34 | attachment: 'bottom right', 35 | targetAttachment: 'top right', 36 | }; 37 | case 'bottom left': 38 | return { 39 | attachment: 'top left', 40 | targetAttachment: 'bottom left', 41 | }; 42 | case 'bottom right': 43 | return { 44 | attachment: 'top right', 45 | targetAttachment: 'bottom right', 46 | }; 47 | case 'right top': 48 | return { 49 | attachment: 'top left', 50 | targetAttachment: 'top right', 51 | }; 52 | case 'right bottom': 53 | return { 54 | attachment: 'bottom left', 55 | targetAttachment: 'bottom right', 56 | }; 57 | case 'left top': 58 | return { 59 | attachment: 'top right', 60 | targetAttachment: 'top left', 61 | }; 62 | case 'left bottom': 63 | return { 64 | attachment: 'bottom right', 65 | targetAttachment: 'bottom left', 66 | }; 67 | default: 68 | return { 69 | attachment: 'top center', 70 | targetAttachment: 'bottom center', 71 | }; 72 | } 73 | } 74 | 75 | export const tetherAttachements = [ 76 | 'top', 77 | 'bottom', 78 | 'left', 79 | 'right', 80 | 'top left', 81 | 'top center', 82 | 'top right', 83 | 'right top', 84 | 'right middle', 85 | 'right bottom', 86 | 'bottom right', 87 | 'bottom center', 88 | 'bottom left', 89 | 'left top', 90 | 'left middle', 91 | 'left bottom', 92 | ]; 93 | 94 | // https://github.com/twbs/bootstrap/blob/v4.0.0-alpha.4/js/src/modal.js#L436-L443 95 | export function getScrollbarWidth() { 96 | const scrollDiv = document.createElement('div'); 97 | // .modal-scrollbar-measure styles // https://github.com/twbs/bootstrap/blob/v4.0.0-alpha.4/scss/_modal.scss#L106-L113 98 | scrollDiv.style.position = 'absolute'; 99 | scrollDiv.style.top = '-9999px'; 100 | scrollDiv.style.width = '50px'; 101 | scrollDiv.style.height = '50px'; 102 | scrollDiv.style.overflow = 'scroll'; 103 | document.body.appendChild(scrollDiv); 104 | const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; 105 | document.body.removeChild(scrollDiv); 106 | return scrollbarWidth; 107 | } 108 | 109 | export function setScrollbarWidth(padding) { 110 | document.body.style.paddingRight = padding > 0 ? `${padding}px` : null; 111 | } 112 | 113 | export function isBodyOverflowing() { 114 | return document.body.clientWidth < window.innerWidth; 115 | } 116 | 117 | export function getOriginalBodyPadding() { 118 | return parseInt( 119 | window.getComputedStyle(document.body, null).getPropertyValue('padding-right') || 0, 120 | 10 121 | ); 122 | } 123 | 124 | export function conditionallyUpdateScrollbar() { 125 | const scrollbarWidth = getScrollbarWidth(); 126 | // https://github.com/twbs/bootstrap/blob/v4.0.0-alpha.4/js/src/modal.js#L420 127 | const fixedContent = document.querySelectorAll('.navbar-fixed-top, .navbar-fixed-bottom, .is-fixed')[0]; 128 | const bodyPadding = fixedContent ? parseInt( 129 | fixedContent.style.paddingRight || 0, 130 | 10 131 | ) : 0; 132 | if (isBodyOverflowing()) { 133 | setScrollbarWidth(bodyPadding + scrollbarWidth); 134 | } 135 | } 136 | 137 | /** 138 | * http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/ 139 | * generate a hash from a string 140 | * @param str 141 | * @returns {number} 142 | */ 143 | export function toHashCode(str) { 144 | let hash = 0; 145 | if (str.length === 0) { 146 | return hash; 147 | } 148 | for (let i = 0; i < str.length; i += 1) { 149 | const char = str.charCodeAt(i); 150 | hash = ((hash << 5) - hash) + char; // eslint-disable-line no-bitwise 151 | hash = hash & hash; // eslint-disable-line no-bitwise, operator-assignment 152 | } 153 | return hash; 154 | } 155 | 156 | /** 157 | * https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/utils/helpers.js 158 | * Safe chained function 159 | * 160 | * Will only create a new function if needed, 161 | * otherwise will pass back existing functions or null. 162 | * 163 | */ 164 | 165 | export function createChainedFunction(...funcs) { 166 | return funcs.filter((func) => func != null).reduce( 167 | (acc, func) => function chainedFunction(...args) { 168 | acc.apply(this, args); 169 | func.apply(this, args); 170 | }, 171 | () => {}, 172 | ); 173 | } 174 | 175 | /** 176 | * Returns a filtered copy of an object with only the specified keys. 177 | */ 178 | export function pick(obj, keys) { 179 | const pickKeys = Array.isArray(keys) ? keys : [keys]; 180 | let { length } = pickKeys; 181 | let key; 182 | const result = {}; 183 | 184 | while (length > 0) { 185 | length -= 1; 186 | key = pickKeys[length]; 187 | result[key] = obj[key]; 188 | } 189 | return result; 190 | } 191 | -------------------------------------------------------------------------------- /src/unitUtils/index.js: -------------------------------------------------------------------------------- 1 | class UnitUtils { 2 | constructor() { 3 | /** 4 | * Unit 5 | * @type {{EM: string, REM: string, PX: string, PERCENT: string}} 6 | */ 7 | this.UNIT = { 8 | EM: 'em', 9 | REM: 'rem', 10 | PX: 'px', 11 | PERCENT: '%', 12 | }; 13 | 14 | /** 15 | * @public 16 | * @description Math operations accepting units value and return calculated result with unit. 17 | * @example 18 | * import unitUtils from '@bootstrap-styled/utils/lib/unitUtils'; 19 | * 20 | * const { math } = unitUtils; 21 | * 22 | * const add = math.addition('15px' + '23px'); 23 | * // OUTPUT '38px'; 24 | * const sub = math.substract('1.5em' + '2.3em'); 25 | * // OUTPUT '3.8em'; 26 | * const mult = math.multiply('15px' * 0.5); 27 | * // OUTPUT '7.5px'; 28 | * const div = math.divide('15px' / 5); 29 | * // OUTPUT '3px'; 30 | */ 31 | this.math = { 32 | addition: function addition(a, b) { 33 | const unit = this.detectUnit(a) || this.detectUnit(b); 34 | return (this.rmUnit(a) + this.rmUnit(b)) + unit; 35 | }.bind(this), 36 | subtract: function subtract(a, b) { 37 | const unit = this.detectUnit(a) || this.detectUnit(b); 38 | return (this.rmUnit(a) - this.rmUnit(b)) + unit; 39 | }.bind(this), 40 | multiply: function multiply(a, b) { 41 | const unit = this.detectUnit(a) || this.detectUnit(b); 42 | return (this.rmUnit(a) * this.rmUnit(b)) + unit; 43 | }.bind(this), 44 | divide: function divide(a, b) { 45 | const unit = this.detectUnit(a) || this.detectUnit(b); 46 | return (this.rmUnit(a) / this.rmUnit(b)) + unit; 47 | }.bind(this), 48 | }; 49 | 50 | /** 51 | * @public 52 | * @description Return the unit from a string by priority : px/rem/em/percent 53 | * @param {String} value 54 | * @throw {Error} if unit can't be detected 55 | * @returns {String} a unit. 56 | * @example 57 | * import unitUtils from '@bootstrap-styled/utils/lib/unitUtils'; 58 | * const { detectUnit } = unitUtils; 59 | * 60 | * const spacer = '1rem'; 61 | * const detectedUnit = detectUnit(spacer); 62 | * 63 | * // OUTPUT 'rem' 64 | */ 65 | this.detectUnit = (value) => { 66 | let ext; 67 | const valueStr = value.toString(); 68 | if (valueStr.match(this.UNIT.PX)) { 69 | ext = this.UNIT.PX; 70 | } else if (valueStr.match(this.UNIT.REM)) { 71 | ext = this.UNIT.REM; 72 | } else if (valueStr.match(this.UNIT.EM)) { 73 | ext = this.UNIT.EM; 74 | } else if (valueStr.match(this.UNIT.PERCENT)) { 75 | ext = this.UNIT.PERCENT; 76 | } else if (!isNaN(value)) { // eslint-disable-line no-restricted-globals 77 | return null; 78 | } else { 79 | throw new Error(`detectUnit can't find unit for ${value}`); 80 | } 81 | return ext; 82 | }; 83 | 84 | /** 85 | * @public 86 | * @description Convert a value string to float. If unit is undefined, it will try to guess it's value using {detectUnit} 87 | * @param {String} value 88 | * @param {String} unit 89 | * @returns {Number} without it's unit 90 | * @example 91 | * import unitUtils from '@bootstrap-styled/utils/lib/unitUtils'; 92 | * const { detectUnit, rmUnit } = unitUtils; 93 | * 94 | * const spacer = '1rem'; 95 | * const spacerHalved' = rmUnit(spacer, detectedUnit) / 2 + detectedUnit); 96 | * 97 | * // OUTPUT '.5rem' 98 | */ 99 | this.rmUnit = (value, unit) => { 100 | const valueStr = value.toString(); 101 | const ext = unit || this.detectUnit(valueStr); 102 | const number = valueStr.replace(ext, ''); 103 | return parseFloat(number); 104 | }; 105 | 106 | /** 107 | * @public 108 | * @description toPercent 109 | * @param {Number} value 110 | * @param {Number} [input=100] 111 | * @param {Number} decimal (default: 2) 112 | * @returns {string} percentage value 113 | * @example 114 | * import unitUtils from '@bootstrap-styled/utils/lib/unitUtils'; 115 | * const { toPercent } = unitUtils; 116 | * 117 | * const percentage = toPercent(20, 100, 10); 118 | * 119 | * // OUTPUT '20%' 120 | */ 121 | this.toPercent = (value, total = 100, decimal = 2) => { // eslint-disable-line arrow-body-style 122 | return `${Math.floor((value / total * 100) * (10 ** decimal)) / (10 ** decimal)}${this.UNIT.PERCENT}`; // eslint-disable-line no-mixed-operators 123 | }; 124 | } 125 | } 126 | 127 | export default new UnitUtils(); 128 | -------------------------------------------------------------------------------- /src/unitUtils/tests/index.test.js: -------------------------------------------------------------------------------- 1 | import unitUtils from '../index'; 2 | 3 | const { 4 | math, 5 | rmUnit, 6 | toPercent, 7 | detectUnit, 8 | UNIT, 9 | } = unitUtils; 10 | 11 | describe('unitUtils', () => { 12 | it('UNIT.PX should be equal to "px"', () => { 13 | expect(UNIT.PX).toEqual('px'); 14 | }); 15 | it('UNIT.EM should be equal to "em"', () => { 16 | expect(UNIT.EM).toEqual('em'); 17 | }); 18 | it('UNIT.REM should be equal to "rem"', () => { 19 | expect(UNIT.REM).toEqual('rem'); 20 | }); 21 | it('rmUnit should return a value without it\'s px unit', () => { 22 | const value = rmUnit('12px', UNIT.PX); 23 | expect(value).toEqual(12); 24 | }); 25 | it('rmUnit should return a value without it\'s em unit', () => { 26 | const value = rmUnit('0.1em', UNIT.EM); 27 | expect(value).toEqual(0.1); 28 | }); 29 | it('rmUnit should return a value without it\'s rem unit', () => { 30 | const value = rmUnit('0.7rem', UNIT.REM); 31 | expect(value).toEqual(0.7); 32 | }); 33 | it('rmUnit should return a value without it\'s auto detected px unit', () => { 34 | const value = rmUnit('12px'); 35 | expect(value).toEqual(12); 36 | }); 37 | it('rmUnit should return a value without it\'s auto detected em unit', () => { 38 | const value = rmUnit('0.1em'); 39 | expect(value).toEqual(0.1); 40 | }); 41 | it('rmUnit should return a value without it\'s auto detected rem unit', () => { 42 | const value = rmUnit('0.7rem'); 43 | expect(value).toEqual(0.7); 44 | }); 45 | it('rmUnit should return a value without it\'s auto detected percent unit', () => { 46 | const value = rmUnit('10%'); 47 | expect(value).toEqual(10); 48 | }); 49 | it('detectUnit should return a px unit', () => { 50 | const value = detectUnit('12px'); 51 | expect(value).toEqual(UNIT.PX); 52 | }); 53 | it('detectUnit should return a em unit', () => { 54 | const value = detectUnit('0.7em'); 55 | expect(value).toEqual(UNIT.EM); 56 | }); 57 | it('detectUnit should return a rem unit', () => { 58 | const value = detectUnit('1rem'); 59 | expect(value).toEqual(UNIT.REM); 60 | }); 61 | it('detectUnit should return a percent unit', () => { 62 | const value = detectUnit('10%'); 63 | expect(value).toEqual(UNIT.PERCENT); 64 | }); 65 | it('toPercent should render a percentage', () => { 66 | const value = 5; 67 | const total = 20; 68 | const decimal = 3; 69 | expect(toPercent(value, total, decimal)).toEqual('25%'); 70 | }); 71 | it('toPercent should have arguments', () => { 72 | const css = toPercent(20, 100, 10); 73 | expect(css).toEqual('20%'); 74 | }); 75 | it('toPercent should have arguments with default args', () => { 76 | const css = toPercent(20); 77 | expect(css).toEqual('20%'); 78 | }); 79 | it('math should addition units', () => { 80 | const value = math.addition('10%', '15%'); 81 | expect(value).toEqual('25%'); 82 | }); 83 | it('math should addition units and detect unit on second parameter', () => { 84 | const value = math.addition('10', '15%'); 85 | expect(value).toEqual('25%'); 86 | }); 87 | it('math should subtract units', () => { 88 | const value = math.subtract('17px', '18px'); 89 | expect(value).toEqual('-1px'); 90 | }); 91 | it('math should subtract units and detect unit on second parameter', () => { 92 | const value = math.subtract('17', '18px'); 93 | expect(value).toEqual('-1px'); 94 | }); 95 | it('math should multiply units', () => { 96 | const value = math.multiply('15rem', '2'); 97 | expect(value).toEqual('30rem'); 98 | }); 99 | it('math should multiply units and detect unit on second parameter', () => { 100 | const value = math.multiply('15', '2rem'); 101 | expect(value).toEqual('30rem'); 102 | }); 103 | it('math should divide units', () => { 104 | const value = math.divide('0.1em', -2); 105 | expect(value).toEqual('-0.05em'); 106 | }); 107 | it('math should divide units and detect unit on second parameter', () => { 108 | const value = math.divide('0.1', '-2em'); 109 | expect(value).toEqual('-0.05em'); 110 | }); 111 | it('should throw error if wrong arguments are passed', () => { 112 | expect(() => detectUnit('test-function')).toThrowError("detectUnit can't find unit for test-function"); 113 | }); 114 | }); 115 | -------------------------------------------------------------------------------- /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/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bootstrap-styled/utils/7874ed924c4d27310a50975b808675e7a52fae3b/styleguide/favicon.ico -------------------------------------------------------------------------------- /styleguide/jsdoc.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | npm run jsdoc-documentation src/parseTransition.js docs/parseTransition.md 4 | npm run jsdoc-documentation src/unitUtils/index.js docs/unitUtils.md 5 | -------------------------------------------------------------------------------- /styleguide/prepare.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | npx rollup-umd-scripts doc 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-scripts doc add-section -n 'Code of conduct' -a 'FAQ' -c 'CODE_OF_CONDUCT.md' --force 17 | npx rollup-umd-scripts doc 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 | "sections": [ 9 | { 10 | "name": "Introduction", 11 | "content": "docs/introduction.md", 12 | "sections": [ 13 | { 14 | "name": "Prerequisite", 15 | "content": "docs/prerequisite.md" 16 | }, 17 | { 18 | "name": "Installation", 19 | "content": "docs/installation.md", 20 | "description": "Discover how to install `bootstrap-styled`" 21 | }, 22 | { 23 | "name": "Configuration", 24 | "content": "docs/configuration.md" 25 | } 26 | ] 27 | }, 28 | { 29 | "name": "Calculations", 30 | "content": "docs/unitUtils.md" 31 | }, 32 | { 33 | "name": "Parsing", 34 | "content": "docs/parseTransition.md" 35 | }, 36 | { 37 | "name": "tools", 38 | "content": "docs/tools.md" 39 | }, 40 | { 41 | "name": "FAQ", 42 | "content": "docs/faq.md" 43 | }, 44 | { 45 | "name": "Contribute", 46 | "content": "docs/contribute.md", 47 | "sections": [ 48 | { 49 | "name": "Commands", 50 | "content": "docs/commands.md" 51 | }, 52 | { 53 | "name": "Branches", 54 | "content": "docs/branches.md" 55 | }, 56 | { 57 | "name": "Release", 58 | "content": "docs/release.md" 59 | } 60 | ] 61 | } 62 | ], 63 | "ribbon": { 64 | "url": "https://github.com/bootstrap-styled/utils", 65 | "text": "Fork us on GitHub" 66 | } 67 | } 68 | --------------------------------------------------------------------------------