├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── questions.md ├── .gitignore ├── .gitmodules ├── .storybook ├── addons.js └── config.js ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── bili.config.js ├── docs ├── .nojekyll ├── README.md ├── _coverpage.md ├── _sidebar.md ├── assets │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon.png │ ├── browserconfig.xml │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── mstile-150x150.png │ ├── osiris.css │ ├── osiris.svg │ ├── safari-pinned-tab.svg │ └── site.webmanifest ├── button.md ├── checkbox.md ├── color.md ├── form.md ├── icon.md ├── index.html ├── input.md ├── layout.md ├── quick-start.md ├── radio.md └── typography.md ├── osiris.svg ├── out730 └── favicon.ico ├── package-lock.json ├── package.json └── src ├── __snapshots__ └── storyshots.spec.js.snap ├── button ├── __snapshots__ │ └── button.spec.js.snap ├── button.spec.js ├── button.stories.js ├── button.vue └── index.js ├── checkbox ├── checkbox.spec.js ├── checkbox.stories.js ├── checkbox.vue └── index.js ├── col ├── __snapshots__ │ └── col.spec.js.snap ├── col.spec.js ├── col.stories.js ├── col.vue └── index.js ├── form ├── form.stories.js ├── form.vue └── index.js ├── formItem ├── formItem.vue └── index.js ├── icons └── icons.stories.js ├── index.js ├── input ├── __snapshots__ │ └── input.spec.js.snap ├── index.js ├── input.spec.js ├── input.stories.js └── input.vue ├── mixins └── dispatch.js ├── radio ├── index.js ├── radio.spec.js ├── radio.stories.js └── radio.vue ├── row ├── __snapshots__ │ └── row.spec.js.snap ├── index.js ├── row.spec.js ├── row.stories.js └── row.vue ├── select ├── Select.vue ├── index.js ├── select.spec.js └── select.stories.js └── storyshots.spec.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["lodash"], 3 | "presets": [ 4 | ["env", { "modules": false }] 5 | ], 6 | "env": { 7 | "test": { 8 | "presets": [ 9 | ["env", { "targets": { "node": "current" }}] 10 | ] 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_size = 2 6 | indent_style = space 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /node_modules/* 2 | /src/osiris-style/* 3 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parserOptions: { 4 | parser: 'babel-eslint', 5 | }, 6 | env: { 7 | browser: true, 8 | node: true, 9 | jest: true, 10 | }, 11 | extends: [ 12 | 'plugin:vue/recommended', 13 | 'airbnb-base', 14 | ], 15 | // required to lint *.vue files 16 | plugins: [ 17 | 'vue', 18 | ], 19 | // add your custom rules here 20 | rules: { 21 | 'import/extensions': 0, 22 | 'global-require': 0, 23 | "no-param-reassign": 0, 24 | 'import/no-unresolved': 0, 25 | 'no-underscore-dangle': 0, 26 | 'no-array-constructor': 0, 27 | 'no-new-object': 0, 28 | 'func-names': 1, 29 | 'linebreak-style': 0, 30 | 'import/no-extraneous-dependencies': 0, 31 | 'vue/require-default-prop': 0, 32 | }, 33 | globals: {}, 34 | } 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 1. Go to '...' 13 | 2. Click on '....' 14 | 3. Scroll down to '....' 15 | 4. See error 16 | 17 | **Expected behavior** 18 | A clear and concise description of what you expected to happen. 19 | 20 | **Screenshots** 21 | If applicable, add screenshots to help explain your problem. 22 | 23 | **Desktop (please complete the following information):** 24 | - OS: [e.g. iOS] 25 | - Browser [e.g. chrome, safari] 26 | - Version [e.g. 22] 27 | 28 | **Smartphone (please complete the following information):** 29 | - Device: [e.g. iPhone6] 30 | - OS: [e.g. iOS8.1] 31 | - Browser [e.g. stock browser, safari] 32 | - Version [e.g. 22] 33 | 34 | **Additional context** 35 | Add any other context about the problem here. 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/questions.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Questions 3 | about: Ask any question 4 | 5 | --- 6 | 7 | 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | 63 | dist/ 64 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/osiris-style"] 2 | path = src/osiris-style 3 | url = https://github.com/osiris-ui/osiris-style.git 4 | branch = master 5 | -------------------------------------------------------------------------------- /.storybook/addons.js: -------------------------------------------------------------------------------- 1 | import '@storybook/addon-knobs/register'; 2 | -------------------------------------------------------------------------------- /.storybook/config.js: -------------------------------------------------------------------------------- 1 | import { configure } from '@storybook/vue'; 2 | import Vue from 'vue'; 3 | 4 | import '../src/osiris-style/dist/osiris-style.css'; 5 | 6 | // Import your custom components. 7 | 8 | // Install Vue plugins. 9 | // Vue.use(Vuex); 10 | 11 | function loadStories() { 12 | const req = require.context('../src', true, /\.stories\.js$/); 13 | req.keys().forEach(filename => req(filename)); 14 | } 15 | 16 | 17 | configure(loadStories, module); 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "lts/*" 4 | git: 5 | submodules: false 6 | cache: 7 | directories: 8 | "node_modules" 9 | before_script: 10 | - npm run build 11 | after_success: 12 | - bash <(curl -s https://codecov.io/bash) -e TRAVIS_NODE_VERSION 13 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Osiris UI Contributing Guide 2 | 3 | In order to maintain the lib organized, please follow this steps before send any pull requests. 4 | 5 | 1) Create an issue or grab an issue before send your PR's (for beginners see [good first issues](https://github.com/osiris-ui/osiris/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)). 6 | 2) Fork the repository to your Github's account. 7 | 3) Go to the repository folder and run `npm install`. 8 | 4) If your change's *doens't* envolve any css files, follow this commands: 9 | - Run these commands 10 | ```sh 11 | git submodule update --init --recursive 12 | ``` 13 | 5) If your change *envolves* any css file, please follow this commands 14 | - Fork the [osiris-style](https://github.com/osiris-ui/osiris-style) repo. 15 | - In the `osiris` repo, run these commands 16 | ```sh 17 | git submodule update --init --recursive 18 | ``` 19 | - Go to `src/osiris-style` 20 | - Run `git remote rename origin upstream` 21 | - Run `git remote add origin YOUR-FORK-GIT-LINK` 22 | - Run `npm install` 23 | - Run `npm run dev` 24 | - Modify the sass files (they will be compiled in real time) 25 | - Push the modifications to your fork (git push origin master) and open a PR 26 | 6) Run the project with `npm run dev`, the storybook will be available at `http://localhost:9001` 27 | 7) If you need to change any doc file and want to preview, you need `docsify` installed 28 | ``` 29 | 30 | If you have any question please, [open a issue](https://github.com/osiris-ui/osiris/issues)! 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Cotabox 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 |

13 | 14 | > A Vue.js 2.0 universal responsive UI component library.. 15 | 16 | ### 🚧 Only for study purposes, do not use in production 17 | 18 | ## Docs 19 | 20 | * [**Home Page**](https://osiris-ui.github.io/osiris/#/) 21 | * [**Storybook**](https://osiris.netlify.com/) 22 | 23 | ## Getting Started 24 | 25 | Check out the [Quick Start](https://osiris-ui.github.io/osiris/#/quick-start) documentation to get started. 26 | 27 | ## Contributing 28 | 29 | Check out the [Contributing Guide](CONTRIBUTING.md) for more details. 30 | 31 | ### Credits 32 | 33 | Osiris UI is a open source project that originally follow the free styleguide created by Wagner Ramos, that you can [see here](https://dribbble.com/shots/4828637--Osiris-UI-Kit-Free-Sketch-Resource), we also have inspiration in the [UIDE Kit](https://dribbble.com/shots/3366725-UIDE-Kit-Style-Guide-Template-FREEBIE), that is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). 34 | 35 | All modifications and new features does not need necessarely to follow one of theses two styleguides, they just inpired us to built a beauty UI lib. 36 | -------------------------------------------------------------------------------- /bili.config.js: -------------------------------------------------------------------------------- 1 | const vue = require('rollup-plugin-vue'); 2 | 3 | module.exports = { 4 | outDir: 'dist', 5 | babel: { 6 | babelrc: false, 7 | }, 8 | 9 | formats: ['es', 'umd', 'umd-min'], 10 | 11 | banner: true, 12 | css: true, 13 | 14 | plugins: [ 15 | vue({ css: true }), 16 | ], 17 | }; 18 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/osiris-ui/osiris/503636369aaaa41c11d74dda93248b81ed6bc59b/docs/.nojekyll -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Osiris UI 2 | 3 | > A Vue.js 2.0 universal responsive UI component library 4 | 5 | ### 🚧 Under development, we working to release 1.0.0 very soon :fire: 6 | 7 | ## Docs 8 | 9 | * [**Home Page**](https://osiris-ui.github.io/osiris/#/) 10 | * [**Storybook**](https://osiris.netlify.com/) 11 | 12 | ## Getting Started 13 | 14 | Check out the [Quick Start](quick-start.md) documentation to get started. 15 | 16 | ## Contributing 17 | 18 | Check out the [Contributing Guide](https://github.com/osiris-ui/osiris/blob/master/CONTRIBUTING.md) for more details. 19 | 20 | ### Credits 21 | 22 | Osiris UI is a open source project that originally follow the free styleguide created by Wagner Ramos, that you can [see here](https://dribbble.com/shots/4828637--Osiris-UI-Kit-Free-Sketch-Resource), we also have inspiration in the [UIDE Kit](https://dribbble.com/shots/3366725-UIDE-Kit-Style-Guide-Template-FREEBIE), that is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). 23 | 24 | All modifications and new features does not need necessarely to follow one of theses two styleguides, they just inpired us to built a beauty UI lib. 25 | -------------------------------------------------------------------------------- /docs/_coverpage.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 |

5 | 6 | > A Vue.js 2.0 universal responsive UI component library. 7 | 8 |

9 | 10 | 11 | 12 | 13 | 14 | 15 |

16 | 17 | [Github](https://github.com/osiris-ui/osiris) 18 | [Get Started](README.md) 19 | 20 | 21 | ![color](#ffffff) 22 | -------------------------------------------------------------------------------- /docs/_sidebar.md: -------------------------------------------------------------------------------- 1 | - Getting Started 2 | - [Overview](README.md) 3 | - [Quick Start](quick-start.md) 4 | 5 | - Basic 6 | - [Layout](layout.md) 7 | - [Color](color.md) 8 | - [Typography](typography.md) 9 | - [Button](button.md) 10 | - [Icon](icon.md) 11 | 12 | - Form 13 | - [Form](form.md) 14 | - [Input](input.md) 15 | - [Radio](radio.md) 16 | - [Checkbox](checkbox.md) 17 | 18 | - [Contributing](CONTRIBUTING.md) 19 | -------------------------------------------------------------------------------- /docs/assets/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/osiris-ui/osiris/503636369aaaa41c11d74dda93248b81ed6bc59b/docs/assets/android-chrome-192x192.png -------------------------------------------------------------------------------- /docs/assets/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/osiris-ui/osiris/503636369aaaa41c11d74dda93248b81ed6bc59b/docs/assets/android-chrome-512x512.png -------------------------------------------------------------------------------- /docs/assets/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/osiris-ui/osiris/503636369aaaa41c11d74dda93248b81ed6bc59b/docs/assets/apple-touch-icon.png -------------------------------------------------------------------------------- /docs/assets/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #ff2f54 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/assets/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/osiris-ui/osiris/503636369aaaa41c11d74dda93248b81ed6bc59b/docs/assets/favicon-16x16.png -------------------------------------------------------------------------------- /docs/assets/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/osiris-ui/osiris/503636369aaaa41c11d74dda93248b81ed6bc59b/docs/assets/favicon-32x32.png -------------------------------------------------------------------------------- /docs/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/osiris-ui/osiris/503636369aaaa41c11d74dda93248b81ed6bc59b/docs/assets/favicon.ico -------------------------------------------------------------------------------- /docs/assets/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/osiris-ui/osiris/503636369aaaa41c11d74dda93248b81ed6bc59b/docs/assets/mstile-150x150.png -------------------------------------------------------------------------------- /docs/assets/osiris.css: -------------------------------------------------------------------------------- 1 | /* LAYOUT CLASSES */ 2 | 3 | .box-1, .box-2 { 4 | padding: 10px 0; 5 | margin-bottom: 5px; 6 | width: 100%; 7 | border-radius: 5px; 8 | } 9 | 10 | .box-1 { 11 | background-color: rgba(0, 153, 249, .5); 12 | } 13 | 14 | .box-2 { 15 | background-color: rgba(38, 93, 127, .5); 16 | } 17 | 18 | 19 | /* COLORS CLASSES */ 20 | 21 | .color-demobox { 22 | padding: 10px; 23 | text-align: center; 24 | display: inline-block; 25 | margin-right: 5px; 26 | vertical-align: top; 27 | width: 102px; 28 | border: 1px solid #dfe6ee; 29 | } 30 | 31 | .color-demobox .box { 32 | width: 80px; 33 | height: 80px; 34 | margin-bottom: 5px; 35 | } 36 | 37 | .color-demobox p { 38 | margin: 0; 39 | /*color: #313541;*/ 40 | } 41 | 42 | /* ICONS CLASSES */ 43 | 44 | .icon-demobox { 45 | padding: 10px; 46 | text-align: center; 47 | margin-right: 5px; 48 | vertical-align: top; 49 | border: 1px solid #dfe6ee; 50 | width: 24%; 51 | box-sizing: border-box; 52 | margin-top: 10px; 53 | } 54 | 55 | .icon-demobox .box { 56 | margin-bottom: 5px; 57 | } 58 | 59 | .icon-demobox p { 60 | margin: 0; 61 | /*color: #313541;*/ 62 | } 63 | -------------------------------------------------------------------------------- /docs/assets/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.11, written by Peter Selinger 2001-2013 9 | 10 | 12 | 166 | 168 | 170 | 172 | 174 | 176 | 178 | 180 | 182 | 184 | 186 | 188 | 190 | 193 | 196 | 199 | 202 | 205 | 208 | 210 | 212 | 213 | 214 | -------------------------------------------------------------------------------- /docs/assets/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /docs/button.md: -------------------------------------------------------------------------------- 1 | # Button 2 | 3 | | Attribute | Description | Type | Accepted Value | Default | 4 | |--|--|--|--|--| 5 | | size | size of button | String | large/normal/small/mini | normal | 6 | | type | button visual type | String | default/primary/secondary/tertiary
/success/warning/danger/text | default | 7 | | plain | whether a plain button | Boolean | true/false | false | 8 | | round | whether a round button | Boolean | true/false | false | 9 | | circle | whether a circle button | Boolean | true/false | false | 10 | | disabled | if button is disabled | Boolean | true/false | false | 11 | | nativeType | same as native button type | String | button/submit | button | 12 | 13 | ## Types 14 | ```html 15 | /*vue*/ 16 | 17 | 31 | 32 | 35 | ``` 36 | 37 | ## Plain 38 | ```html 39 | /*vue*/ 40 | 41 | 54 | 55 | 58 | ``` 59 | 60 | ## Disabled 61 | ```html 62 | /*vue*/ 63 | 64 | 92 | 93 | 96 | ``` 97 | 98 | ## Sizes 99 | ```html 100 | /*vue*/ 101 | 102 | 154 | 155 | 158 | ``` 159 | ## Round 160 | ```html 161 | /*vue*/ 162 | 163 | 176 | 177 | 180 | ``` 181 | 182 | ## Circle 183 | 184 | ```html 185 | /*vue*/ 186 | 187 | 198 | 199 | 202 | ``` 203 | -------------------------------------------------------------------------------- /docs/checkbox.md: -------------------------------------------------------------------------------- 1 | # Checkbox 2 | 3 | ## Basic Usage 4 | ```html 5 | /*vue*/ 6 | 7 | 13 | 14 | 23 | ``` 24 | 25 | ## Disabled 26 | 27 | ```html 28 | /*vue*/ 29 | 30 | 36 | 37 | 46 | ``` 47 | -------------------------------------------------------------------------------- /docs/color.md: -------------------------------------------------------------------------------- 1 | # Color 2 | 3 | This are the set of colors used in all Atlas components. 4 | 5 | ## Main Color 6 | 7 |
8 |
9 | Primary 10 |

#FF2F54

11 |
12 | 13 |
14 |
15 | Secondary 16 |

#141334

17 |
18 | 19 | ## Additional 20 | 21 |
22 |
23 | Info 24 |

#2B9FEA

25 |
26 | 27 | 28 |
29 |
30 | Success 31 |

#17C671

32 |
33 | 34 | 35 |
36 |
37 | Warning 38 |

#FFB400

39 |
40 | 41 | 42 |
43 |
44 | Danger 45 |

#C4183C

46 |
47 | 48 | ## Lines, borders and shadows 49 | 50 |
51 |
52 |

#F4F7FA

53 |
54 | 55 |
56 |
57 |

#DFE6EE

58 |
59 | 60 |
61 |
62 |

#B0BAC5

63 |
64 | 65 |
66 |
67 |

#8091A5

68 |
69 | 70 |
71 |
72 |

#667588

73 |
74 | 75 | ## Text colors 76 | 77 |
78 |
79 |

#313541

80 |
81 | 82 |
83 |
84 |

#16181E

85 |
86 | 87 | 88 | -------------------------------------------------------------------------------- /docs/form.md: -------------------------------------------------------------------------------- 1 | # Form 2 | 3 | We created a integrated form validation system, heavily inspired on [Element](https://element.eleme.io) validation. The validation system works on top of [Validate.js](https://validatejs.org), a free and open source validation library. 4 | 5 | ## Basic Usage 6 | 7 | ```html 8 | /* vue */ 9 | 10 | 49 | 50 | 114 | ``` 115 | 116 | ## Form Attrs 117 | 118 | | Attribute | Description | Type | Accepted Value | Default | 119 | |--|--|--|--|--| 120 | | model | The form object from data | type Object | | | 121 | | rules | Global rules usage | Object | | | 122 | | labelPosition | position of label | String | top/left/right | top | 123 | | labelWitdh | width of label | String | | 100px | 124 | | width | form width | String | | 100% | 125 | 126 | 127 | ## Form Item Attrs 128 | 129 | | Attribute | Description | Type | Accepted Value | Default | 130 | |--|--|--|--|--| 131 | | label | Label content | String | | | 132 | | prop | A key property from form model | String | | | 133 | | rules | Rules for this formItem (if not provided in the main form) | | | | | 134 | 135 | 136 | ## Form Events 137 | 138 | | Event Name | Description | Params | 139 | | -- | -- | -- | 140 | | submit | same as native submit | | | 141 | 142 | ## Form Methods 143 | 144 | | Method Name | Description | Params | 145 | | -- | -- | -- | 146 | | validate | Trigger this method to validate all fields | | | 147 | 148 | ## FormItem Methods 149 | | Method Name | Description | Params | 150 | | -- | -- | -- | 151 | | validate | Trigger this method to validate the Form Item content | value (non required) | 152 | -------------------------------------------------------------------------------- /docs/icon.md: -------------------------------------------------------------------------------- 1 | # Icon 2 | 3 | For icons we choose a free open source solution called [Feather Icons](https://feathericons.com/) through a fork from [AT-UI](https://github.com/AT-UI/feather-font). 4 | 5 | ## Basic Usage 6 | ```html 7 | /*vue*/ 8 | 9 | 15 | 16 | 19 | ``` 20 | 21 | ## Full list 22 | 23 | ```html 24 | /*vue*/ 25 | 26 | 48 | 49 | 308 | ``` 309 | 310 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Osiris - A Vue.js 2.0 universal responsive UI component library 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /docs/input.md: -------------------------------------------------------------------------------- 1 | ## Input 2 | 3 | | Attribute | Description | Type | Accepted Value | Default | 4 | |--|--|--|--|--| 5 | | width | width of input | String | | '300px' | 6 | | prefixIcon | wheather has a prefix icon | String | | | 7 | | suffixIcon | wheather has a suffix icon | String | | | 8 | | size | size of input | String | large/normal/small/mini | normal | 9 | | readonly | whether is a readonly input | Boolean | true/false | false | 10 | | disabled | if input is disabled | Boolean | true/false | false | 11 | | isSuccess | whether has a success status | Boolean | true/false | false | 12 | | isError | whether has a error status | Boolean | true/false | false | 13 | | name | same as native name attr | String | | | 14 | | placeholder | same as native placeholder attr | String | | | 15 | | type | same as native type attr | String | | text | 16 | 17 | ## Basic Usage 18 | 19 | ```html 20 | /*vue*/ 21 | 22 | 25 | 26 | 29 | ``` 30 | 31 | ## Custom width 32 | 33 | ```html 34 | /*vue*/ 35 | 36 | 39 | 40 | 43 | ``` 44 | 45 | ## With icon 46 | 47 | ```html 48 | /*vue*/ 49 | 50 | 56 | 57 | 60 | ``` 61 | 62 | ## With status 63 | 64 | ```html 65 | /*vue*/ 66 | 67 | 73 | 74 | 77 | ``` 78 | 79 | ## Sizes 80 | 81 | ```html 82 | /*vue*/ 83 | 84 | 96 | 97 | 100 | ``` 101 | 102 | 103 | ## Disabled 104 | 105 | ```html 106 | /*vue*/ 107 | 108 | 111 | 112 | 115 | ``` 116 | 117 | ## Readonly 118 | 119 | ```html 120 | /*vue*/ 121 | 122 | 125 | 126 | 129 | ``` 130 | 131 | -------------------------------------------------------------------------------- /docs/layout.md: -------------------------------------------------------------------------------- 1 | # Layout 2 | 3 | We use a flex based grid system with 24 columns with a 20px gutter by default. 4 | 5 | ### Row Attributes 6 | 7 | | Attribute | Description | Type | Accepted Value | Default | 8 | |--|--|--|--|--| 9 | | gutter | grid spacing | number | - | 20 | 10 | | direction | direction of layout | string | row/row-reverse/column/column-reverse | row | 11 | | wrap | how content will wrap | string | wrap/nowrap/wrap-reverse | wrap | 12 | | justify | horizontal alignment | string | flex-start/flex-end/center/space-around/space-between/space-evenly | flex-start | 13 | | align | vertical alignment | string | flex-start/flex-end/center/baseline/stretch | flex-start | 14 | | content | content alignment | string | flex-start/flex-end/center/space-between/space-around/stretch | flex-start | 15 | 16 | 17 | ### Col Attributes 18 | 19 | | Attribute | Description | Type | Accepted Value | Default | 20 | |--|--|--|--|--| 21 | | span | column width | number | 0-24 | 24 | 22 | | offset | column spacing | number | 0-24 | 0 | 23 | | xs | column width for `<768px` | number/object (e.g { span: 4, offset: 4 }) | 0-24/object | - | 24 | | sm | column width for `≥768px` | number/object (e.g { span: 4, offset: 4 }) | 0-24/object | - | 25 | | md | column width for `≥992px` | number/object (e.g { span: 4, offset: 4 }) | 0-24/object | - | 26 | | lg | column width for `≥1200px` | number/object (e.g { span: 4, offset: 4 }) | 0-24/object | - | 27 | | xl | column width for `≥1920px` | number/object (e.g { span: 4, offset: 4 }) | 0-24/object | - | 28 | 29 | ## Basic Usage 30 | 31 | ```html 32 | /*vue*/ 33 | 67 | 68 | 71 | ``` 72 | -------------------------------------------------------------------------------- /docs/quick-start.md: -------------------------------------------------------------------------------- 1 | # Quick Start 2 | 3 | To get started with Osiris UI is pretty simple, the only dependency is `vue`, we always recommend use in the newest version possible. 4 | 5 | ## Installation 6 | 7 | There are many ways on how to use Osiris UI, follow those who better fits your need's. 8 | 9 | ### CDN 10 | 11 | ```html 12 | 13 | 14 | 15 | 16 | 17 | ``` 18 | 19 | 20 | ### ES Module 21 | 22 | There's a few ways on how to use in a node.js project 23 | 24 | #### Using as plugin 25 | 26 | ``` js 27 | import Vue from 'vue'; 28 | import Osiris from '@osiris-ui/osiris'; 29 | 30 | Vue.use(Osiris); 31 | ``` 32 | 33 | #### Using as component 34 | 35 | ``` js 36 | import { button as OButton } from '@osiris-ui/osiris'; 37 | ``` 38 | 39 | #### Importing globally only few components 40 | ```js 41 | import Vue from 'vue'; 42 | import { button, input } from '@osiris-ui/osiris'; 43 | 44 | Vue.component(button.name, button); 45 | Vue.component(input.name, input); 46 | ``` 47 | 48 | *Don't forget to include the Osiris css theme* 49 | 50 | 51 | ## Custom Theme 52 | 53 | Osiris theme use sass as pre-processor. To customize themes and colors, you gonna need follow this steps: 54 | 55 | - Install the Osiris Theme running: `npm install --save @osiris-ui/style` 56 | - Install `node-sass` and `sass-loader`: `npm install --save node-sass sass-loader` 57 | - Create two files: `app.scss` and `variables.scss` (You can set any name and put these files in any folder that you find better). 58 | - In `variables.scss`, copy all the content from `@osiris-ui/style/src/variables.scss`, this is the main file you need to customize with the colors and others visual things. 59 | - In `app.scss`, copy all the content from `@osiris-ui/style/src/index.scss`, and replace the path to the respective destination in your `node_modules`, like: 60 | 61 | ```scss 62 | @import '../node_modules/@osiris-ui/style/src/reset'; 63 | @import '../node_modules/@osiris-ui/style/src/icons'; 64 | @import '../node_modules/@osiris-ui/style/src/row'; 65 | @import '../node_modules/@osiris-ui/style/src/col'; 66 | @import '../node_modules/@osiris-ui/style/src/button'; 67 | @import '../node_modules/@osiris-ui/style/src/input'; 68 | @import '../node_modules/@osiris-ui/style/src/radio'; 69 | @import '../node_modules/@osiris-ui/style/src/form'; 70 | /* ETC... */ 71 | ``` 72 | - Finally, you can import the `app.scss` in your application 73 | - If you use a CDN project, you need to compile the scss files to a css file, create a simple project that has node-sass and sass-loader as dependencies and finally create a script that run node-sass, like this: `node-sass --include-path $PATH $PATH/app.scss dist/osiris-style.css --output-style compressed` 74 | 75 | In the future we plan to create a more easily tool for customizing all variables, colors and other stuffs of Osiris UI. 76 | -------------------------------------------------------------------------------- /docs/radio.md: -------------------------------------------------------------------------------- 1 | # Radio 2 | 3 | ## Basic Usage 4 | ```html 5 | /*vue*/ 6 | 7 | 13 | 14 | 23 | ``` 24 | 25 | ## Disabled 26 | 27 | ```html 28 | /*vue*/ 29 | 30 | 36 | 37 | 46 | ``` 47 | -------------------------------------------------------------------------------- /docs/typography.md: -------------------------------------------------------------------------------- 1 | # Typography 2 | 3 | The font chosen was Lato, which is avaiable at [Google Fonts](https://fonts.google.com/specimen/Lato). Check out the application and sizes: 4 | 5 | 6 | ## Headings 7 | 8 | > H1 9 | 10 |

We used to look up at the sky and wonder at our place in the stars. Now we just look down, and worry about our place in the dirt.

11 | 12 | > H2 13 | 14 |

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Rem nam expedita dolorum doloribus voluptatum quia ea, natus non earum sequi.

15 | 16 | > H3 17 | 18 |

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Rem nam expedita dolorum doloribus voluptatum quia ea, natus non earum sequi.

19 | 20 | > H4 21 | 22 |

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Rem nam expedita dolorum doloribus voluptatum quia ea, natus non earum sequi.

23 | 24 | > H5 25 | 26 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Rem nam expedita dolorum doloribus voluptatum quia ea, natus non earum sequi.
27 | 28 | > H6 29 | 30 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Rem nam expedita dolorum doloribus voluptatum quia ea, natus non earum sequi.
31 | 32 | ## Paragraphs 33 | 34 | > p 35 | 36 |

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Recusandae ut facere rerum, asperiores debitis, culpa blanditiis ratione at tempora beatae eaque maxime magni reprehenderit! Voluptates in, amet consectetur dignissimos natus suscipit veniam, possimus qui excepturi impedit sapiente illo. Quae ab voluptatibus nulla ratione. Nulla doloribus animi similique libero mollitia maxime!

37 | 38 | > p.small 39 | 40 |

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consectetur quos sunt soluta odit magni fugiat libero quasi optio dolor ut minima iure, fugit voluptatum eum debitis reiciendis ad accusantium. Minus nam eos officia iure dicta provident est dolores accusamus obcaecati pariatur ratione, sed, quas nulla ad voluptatum aliquam veniam ex?

41 | 42 | > small 43 | 44 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugit, quo! 45 | 46 | > small.small 47 | 48 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugit, quo! 49 | -------------------------------------------------------------------------------- /out730/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/osiris-ui/osiris/503636369aaaa41c11d74dda93248b81ed6bc59b/out730/favicon.ico -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@osiris-ui/osiris", 3 | "version": "0.9.0", 4 | "description": "A Vue.js 2.0 universal responsive UI component library", 5 | "main": "dist/osiris.js", 6 | "module": "dist/osiris.es.js", 7 | "unpkg": "dist/osiris.min.js", 8 | "files": [ 9 | "dist" 10 | ], 11 | "scripts": { 12 | "dev": "start-storybook -p 9001 -c .storybook", 13 | "deploy-storybook": "storybook-to-ghpages", 14 | "build": "rm -rf ./dist && bili", 15 | "tdd": "jest --watch", 16 | "test": "jest", 17 | "coverage": "codecov", 18 | "test:newsnapshot": "npm run test -- -u", 19 | "lint": "eslint --ext .vue --ext .js src/", 20 | "lint:fix": "npm run lint --fix" 21 | }, 22 | "repository": { 23 | "type": "git", 24 | "url": "git+https://github.com/osiris-ui/osiris.git" 25 | }, 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/osiris-ui/osiris/issues" 29 | }, 30 | "homepage": "https://github.com/osiris-ui/osiris#readme", 31 | "devDependencies": { 32 | "@storybook/addon-knobs": "^3.4.10", 33 | "@storybook/addon-storyshots": "^3.4.10", 34 | "@storybook/addon-storysource": "^3.4.8", 35 | "@storybook/storybook-deployer": "^2.3.0", 36 | "@storybook/vue": "^3.4.8", 37 | "@vue/test-utils": "^1.0.0-beta.24", 38 | "babel-core": "^6.26.3", 39 | "babel-eslint": "^8.2.6", 40 | "babel-jest": "^23.4.2", 41 | "babel-plugin-lodash": "^3.3.4", 42 | "babel-preset-env": "^1.7.0", 43 | "bili": "^3.1.2", 44 | "css-loader": "^1.0.0", 45 | "eslint": "^4.19.1", 46 | "eslint-config-airbnb": "^17.0.0", 47 | "eslint-config-airbnb-base": "^13.0.0", 48 | "eslint-config-postcss": "^3.0.3", 49 | "eslint-friendly-formatter": "^4.0.1", 50 | "eslint-loader": "^2.1.0", 51 | "eslint-plugin-import": "^2.13.0", 52 | "eslint-plugin-vue": "^4.7.1", 53 | "file-loader": "^1.1.11", 54 | "husky": "^1.0.0-rc.13", 55 | "identity-obj-proxy": "^3.0.0", 56 | "jest": "^23.4.2", 57 | "jest-serializer-vue": "^2.0.2", 58 | "rollup-plugin-vue": "^3.0.0", 59 | "vue-jest": "^2.6.0", 60 | "vue-loader": "^14.2.2", 61 | "vue-template-compiler": "^2.5.16" 62 | }, 63 | "dependencies": { 64 | "codecov": "^3.0.4", 65 | "lodash": "^4.17.10", 66 | "popper.js": "^1.14.4", 67 | "validate.js": "^0.12.0", 68 | "vue": "^2.5.16", 69 | "vue-click-outside": "^1.0.7", 70 | "vue2-transitions": "^0.2.3" 71 | }, 72 | "jest": { 73 | "verbose": true, 74 | "testURL": "http://localhost/", 75 | "collectCoverage": true, 76 | "coverageDirectory": "./coverage/", 77 | "collectCoverageFrom": [ 78 | "src/**/*.{js,vue}", 79 | "!**/node_modules/**" 80 | ], 81 | "moduleFileExtensions": [ 82 | "js", 83 | "json", 84 | "vue" 85 | ], 86 | "transform": { 87 | ".*\\.(vue)$": "vue-jest", 88 | "^.+\\.js$": "/node_modules/babel-jest" 89 | }, 90 | "snapshotSerializers": [ 91 | "/node_modules/jest-serializer-vue" 92 | ], 93 | "testMatch": [ 94 | "/(src/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx))" 95 | ], 96 | "transformIgnorePatterns": [ 97 | "/node_modules/(?!(@storybook/.*\\.vue$))" 98 | ], 99 | "moduleNameMapper": { 100 | "\\.(css|less|scss|sass)$": "identity-obj-proxy" 101 | } 102 | }, 103 | "husky": { 104 | "hooks": { 105 | "pre-push": "npm run lint && npm test" 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/button/__snapshots__/button.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Button should be a circle button 1`] = ``; 4 | 5 | exports[`Button should be a danger button 1`] = ``; 6 | 7 | exports[`Button should be a default button at startup 1`] = ``; 8 | 9 | exports[`Button should be a info button 1`] = ``; 10 | 11 | exports[`Button should be a large button 1`] = ``; 12 | 13 | exports[`Button should be a mini button 1`] = ``; 14 | 15 | exports[`Button should be a normal button 1`] = ``; 16 | 17 | exports[`Button should be a plain button 1`] = ``; 18 | 19 | exports[`Button should be a primary button 1`] = ``; 20 | 21 | exports[`Button should be a round button 1`] = ``; 22 | 23 | exports[`Button should be a secondary button 1`] = ``; 24 | 25 | exports[`Button should be a small button 1`] = ``; 26 | 27 | exports[`Button should be a success button 1`] = ``; 28 | 29 | exports[`Button should be a text button 1`] = ``; 30 | 31 | exports[`Button should be a warning button 1`] = ``; 32 | 33 | exports[`Button should be disabled 1`] = ``; 34 | 35 | exports[`Button should have a nativeType submit 1`] = ``; 36 | -------------------------------------------------------------------------------- /src/button/button.spec.js: -------------------------------------------------------------------------------- 1 | import { mount } from '@vue/test-utils'; 2 | import Button from './button.vue'; 3 | 4 | describe('Button', () => { 5 | let wrapper; 6 | 7 | const reset = () => wrapper.setProps({ 8 | type: 'default', 9 | nativeType: 'button', 10 | size: 'normal', 11 | round: false, 12 | circle: false, 13 | disabled: false, 14 | }); 15 | 16 | beforeAll(() => { 17 | wrapper = mount(Button); 18 | }); 19 | 20 | afterEach(reset); 21 | 22 | it('should be a default button at startup', () => { 23 | const defaultClasses = ['o-button', 'o-button--default', 'o-button--normal']; 24 | 25 | expect(wrapper.html()).toMatchSnapshot(); 26 | expect(wrapper.classes()).toEqual(defaultClasses); 27 | }); 28 | 29 | it('should be a primary button', () => { 30 | wrapper.setProps({ 31 | type: 'primary', 32 | }); 33 | 34 | expect(wrapper.html()).toMatchSnapshot(); 35 | expect(wrapper.classes()).toContain('o-button--primary'); 36 | }); 37 | 38 | it('should be a secondary button', () => { 39 | wrapper.setProps({ 40 | type: 'secondary', 41 | }); 42 | 43 | expect(wrapper.html()).toMatchSnapshot(); 44 | expect(wrapper.classes()).toContain('o-button--secondary'); 45 | }); 46 | 47 | it('should be a info button', () => { 48 | wrapper.setProps({ 49 | type: 'info', 50 | }); 51 | 52 | expect(wrapper.html()).toMatchSnapshot(); 53 | expect(wrapper.classes()).toContain('o-button--info'); 54 | }); 55 | 56 | it('should be a success button', () => { 57 | wrapper.setProps({ 58 | type: 'success', 59 | }); 60 | 61 | expect(wrapper.html()).toMatchSnapshot(); 62 | expect(wrapper.classes()).toContain('o-button--success'); 63 | }); 64 | 65 | it('should be a warning button', () => { 66 | wrapper.setProps({ 67 | type: 'warning', 68 | }); 69 | 70 | expect(wrapper.html()).toMatchSnapshot(); 71 | expect(wrapper.classes()).toContain('o-button--warning'); 72 | }); 73 | 74 | it('should be a danger button', () => { 75 | wrapper.setProps({ 76 | type: 'danger', 77 | }); 78 | 79 | expect(wrapper.html()).toMatchSnapshot(); 80 | expect(wrapper.classes()).toContain('o-button--danger'); 81 | }); 82 | 83 | it('should be a text button', () => { 84 | wrapper.setProps({ 85 | type: 'text', 86 | }); 87 | 88 | expect(wrapper.html()).toMatchSnapshot(); 89 | expect(wrapper.classes()).toContain('o-button--text'); 90 | }); 91 | 92 | it('should be a mini button', () => { 93 | wrapper.setProps({ 94 | size: 'mini', 95 | }); 96 | 97 | expect(wrapper.html()).toMatchSnapshot(); 98 | expect(wrapper.classes()).toContain('o-button--mini'); 99 | }); 100 | 101 | it('should be a small button', () => { 102 | wrapper.setProps({ 103 | size: 'small', 104 | }); 105 | 106 | expect(wrapper.html()).toMatchSnapshot(); 107 | expect(wrapper.classes()).toContain('o-button--small'); 108 | }); 109 | 110 | it('should be a normal button', () => { 111 | wrapper.setProps({ 112 | size: 'normal', 113 | }); 114 | 115 | expect(wrapper.html()).toMatchSnapshot(); 116 | expect(wrapper.classes()).toContain('o-button--normal'); 117 | }); 118 | 119 | it('should be a large button', () => { 120 | wrapper.setProps({ 121 | size: 'large', 122 | }); 123 | 124 | expect(wrapper.html()).toMatchSnapshot(); 125 | expect(wrapper.classes()).toContain('o-button--large'); 126 | }); 127 | 128 | it('should be a round button', () => { 129 | wrapper.setProps({ 130 | round: true, 131 | }); 132 | 133 | expect(wrapper.html()).toMatchSnapshot(); 134 | expect(wrapper.classes()).toContain('is-round'); 135 | }); 136 | 137 | it('should be a circle button', () => { 138 | wrapper.setProps({ 139 | circle: true, 140 | }); 141 | 142 | expect(wrapper.html()).toMatchSnapshot(); 143 | expect(wrapper.classes()).toContain('is-circle'); 144 | }); 145 | 146 | it('should be a plain button', () => { 147 | wrapper.setProps({ 148 | plain: true, 149 | }); 150 | 151 | expect(wrapper.html()).toMatchSnapshot(); 152 | expect(wrapper.classes()).toContain('is-plain'); 153 | }); 154 | 155 | it('should have a nativeType submit', () => { 156 | wrapper.setProps({ 157 | nativeType: 'submit', 158 | }); 159 | 160 | expect(wrapper.html()).toMatchSnapshot(); 161 | expect(wrapper.attributes().type).toBe('submit'); 162 | }); 163 | 164 | it('should be disabled', () => { 165 | wrapper.setProps({ 166 | disabled: true, 167 | }); 168 | 169 | expect(wrapper.html()).toMatchSnapshot(); 170 | expect(wrapper.attributes().disabled).toBeTruthy(); 171 | }); 172 | 173 | it('should emit click event', () => { 174 | wrapper.findAll('button').trigger('click'); 175 | expect(wrapper.emitted().click).toBeTruthy(); 176 | }); 177 | 178 | it('should render default slot', () => { 179 | wrapper = mount(Button, { 180 | slots: { 181 | default: 'Default Button', 182 | }, 183 | }); 184 | 185 | expect(wrapper.text()).toBe('Default Button'); 186 | }); 187 | }); 188 | -------------------------------------------------------------------------------- /src/button/button.stories.js: -------------------------------------------------------------------------------- 1 | import { storiesOf } from '@storybook/vue'; 2 | 3 | import OButton from './button.vue'; 4 | 5 | storiesOf('Button', module) 6 | // .add('default', () => 'simple row'); 7 | .add('types', () => ({ 8 | components: { OButton }, 9 | template: ` 10 |
11 | Default 12 | Primary 13 | Secondary 14 | Info 15 | Success 16 | Warning 17 |
18 | Danger 19 | Text 20 |
21 |
22 | `, 23 | })) 24 | .add('plain', () => ({ 25 | components: { OButton }, 26 | template: ` 27 |
28 | Default 29 | Primary 30 | Secondary 31 | Info 32 | Success 33 | Warning 34 |
35 | Danger 36 |
37 |
38 | `, 39 | })) 40 | .add('disabled', () => ({ 41 | components: { OButton }, 42 | template: ` 43 |
44 |
45 | Default 46 | Primary 47 | Secondary 48 | Info 49 | Success 50 | Warning 51 |
52 | Danger 53 | Text 54 |
55 |
56 |
57 | Default 58 | Primary 59 | Secondary 60 | Info 61 | Success 62 | Warning 63 |
64 | Danger 65 | Text 66 |
67 |
68 |
69 | `, 70 | })) 71 | .add('sizes', () => ({ 72 | components: { OButton }, 73 | template: ` 74 |
75 |
76 | Default Large 77 | Default Normal 78 | Default Small 79 | Default Mini 80 |
81 |
82 | Primary Large 83 | Primary Normal 84 | Primary Small 85 | Primary Mini 86 |
87 |
88 | Secondary Large 89 | Secondary Normal 90 | Secondary Small 91 | Secondary Mini 92 |
93 |
94 | Info Large 95 | Info Normal 96 | Info Small 97 | Info Mini 98 |
99 |
100 | Success Large 101 | Success Normal 102 | Success Small 103 | Success Mini 104 |
105 |
106 | Warning Large 107 | Warning Normal 108 | Warning Small 109 | Warning Mini 110 |
111 |
112 | Danger Large 113 | Danger Normal 114 | Danger Small 115 | Danger Mini 116 |
117 |
118 | Text Large 119 | Text Normal 120 | Text Small 121 | Text Mini 122 |
123 |
124 | `, 125 | })) 126 | .add('round', () => ({ 127 | components: { OButton }, 128 | template: ` 129 |
130 | Default 131 | Primary 132 | Secondary 133 | Info 134 | Success 135 | Warning 136 |
137 | Danger 138 |
139 |
140 | `, 141 | })) 142 | .add('circle', () => ({ 143 | components: { OButton }, 144 | template: ` 145 |
146 | D 147 | P 148 | S 149 | I 150 | SC 151 | W 152 | D 153 |
154 | `, 155 | })); 156 | -------------------------------------------------------------------------------- /src/button/button.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 69 | -------------------------------------------------------------------------------- /src/button/index.js: -------------------------------------------------------------------------------- 1 | import button from './button.vue'; 2 | 3 | export default button; 4 | -------------------------------------------------------------------------------- /src/checkbox/checkbox.spec.js: -------------------------------------------------------------------------------- 1 | import { mount } from '@vue/test-utils'; 2 | import checkbox from './checkbox.vue'; 3 | 4 | describe('checkbox', () => { 5 | let wrapper; 6 | 7 | beforeEach(() => { 8 | wrapper = mount(checkbox); 9 | wrapper.setProps({ 10 | size: 'medium', 11 | }); 12 | }); 13 | 14 | describe('when is default', () => { 15 | it('should have expected classes', () => { 16 | expect(wrapper.classes()) 17 | .toEqual(['o-checkbox', 'o-checkbox--medium']); 18 | }); 19 | }); 20 | 21 | describe('when have default params filled', () => { 22 | beforeEach(() => { 23 | wrapper.setProps({ 24 | value: '1', 25 | modelValue: '1', 26 | label: 'label', 27 | name: 'name', 28 | }); 29 | }); 30 | 31 | it('should have a name attr', () => { 32 | const { name } = wrapper.find('input') 33 | .attributes(); 34 | expect(name).toEqual('name'); 35 | }); 36 | 37 | it('should have a value attr', () => { 38 | const input = wrapper.find('input'); 39 | const { value } = input.attributes(); 40 | expect(value).toEqual('1'); 41 | }); 42 | 43 | it('should have a label', () => { 44 | const label = wrapper.find('.o-checkbox__label'); 45 | expect(label.text()).toEqual('label'); 46 | }); 47 | }); 48 | 49 | describe('when is disabled', () => { 50 | beforeEach(() => { 51 | wrapper.setProps({ 52 | disabled: true, 53 | }); 54 | }); 55 | 56 | it('should have is-disabled class', () => { 57 | expect(wrapper.classes()) 58 | .toEqual(expect.arrayContaining(['is-disabled'])); 59 | }); 60 | }); 61 | 62 | describe('when is checked', () => { 63 | beforeEach(() => { 64 | wrapper.setProps({ 65 | modelValue: '1', 66 | value: '1', 67 | }); 68 | }); 69 | 70 | it('should have is-checked class', () => { 71 | expect(wrapper.classes()) 72 | .toEqual(expect.arrayContaining(['is-checked'])); 73 | }); 74 | }); 75 | 76 | describe('when have another size', () => { 77 | beforeEach(() => { 78 | wrapper.setProps({ 79 | size: 'large', 80 | }); 81 | }); 82 | 83 | it('should have o-checkbox--large class', () => { 84 | expect(wrapper.classes()) 85 | .toEqual(expect.arrayContaining(['o-checkbox', 'o-checkbox--large'])); 86 | }); 87 | }); 88 | }); 89 | -------------------------------------------------------------------------------- /src/checkbox/checkbox.stories.js: -------------------------------------------------------------------------------- 1 | import { storiesOf } from '@storybook/vue'; 2 | import OCheckbox from './checkbox.vue'; 3 | 4 | storiesOf('Checkbox', module) 5 | .add('default', () => ({ 6 | components: { OCheckbox }, 7 | data() { 8 | return { 9 | modelValue: 1, 10 | }; 11 | }, 12 | template: ` 13 |
14 |

Selected Value: {{modelValue}}

15 | 16 |
17 | `, 18 | })) 19 | .add('with a disabled', () => ({ 20 | components: { 21 | OCheckbox, 22 | }, 23 | data() { 24 | return { 25 | modelValue: 2, 26 | }; 27 | }, 28 | template: ` 29 | 36 | `, 37 | })) 38 | .add('with model being an array', () => ({ 39 | components: { 40 | OCheckbox, 41 | }, 42 | data() { 43 | return { 44 | modelValue: [], 45 | }; 46 | }, 47 | template: ` 48 |
49 |

Model Value: {{modelValue}}

50 | 56 | 62 |
63 | `, 64 | })); 65 | -------------------------------------------------------------------------------- /src/checkbox/checkbox.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 96 | -------------------------------------------------------------------------------- /src/checkbox/index.js: -------------------------------------------------------------------------------- 1 | import Checkbox from './checkbox.vue'; 2 | 3 | export default Checkbox; 4 | -------------------------------------------------------------------------------- /src/col/__snapshots__/col.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Col when pass no prop should match with the snapshot 1`] = `
`; 4 | 5 | exports[`Col when pass some props and the props are {"span":1,"xs":2,"sm":3,"md":4,"lg":5,"xl":6,"offset":7} should match with the snapshot 1`] = `
`; 6 | 7 | exports[`Col when pass some props and the props are another tag like section should match with the snapshot 1`] = `
`; 8 | -------------------------------------------------------------------------------- /src/col/col.spec.js: -------------------------------------------------------------------------------- 1 | import { shallowMount } from '@vue/test-utils'; 2 | import Col from './col.vue'; 3 | 4 | describe('Col', () => { 5 | let wrapper; 6 | describe('when pass no prop', () => { 7 | beforeEach(() => { 8 | wrapper = shallowMount(Col); 9 | }); 10 | 11 | it('should match with the snapshot', () => { 12 | expect(wrapper.html()).toMatchSnapshot(); 13 | }); 14 | 15 | it('should have default classList', () => { 16 | const expected = ['o-col-24', 'o-col-offset-0']; 17 | expect(wrapper.vm.classList).toEqual(expected); 18 | }); 19 | }); 20 | 21 | describe('when pass some props', () => { 22 | const props = { 23 | span: 1, 24 | xs: 2, 25 | sm: 3, 26 | md: 4, 27 | lg: 5, 28 | xl: 6, 29 | offset: 7, 30 | }; 31 | 32 | describe(`and the props are ${JSON.stringify(props)}`, () => { 33 | beforeEach(() => { 34 | wrapper = shallowMount(Col, { 35 | propsData: { 36 | ...props, 37 | }, 38 | }); 39 | }); 40 | 41 | it('should match with the snapshot', () => { 42 | expect(wrapper.html()).toMatchSnapshot(); 43 | }); 44 | 45 | it('should have exactly expected classList', () => { 46 | const expected = [ 47 | 'o-col-1', 48 | 'o-col-offset-7', 49 | 'o-col-xs-2', 50 | 'o-col-sm-3', 51 | 'o-col-md-4', 52 | 'o-col-lg-5', 53 | 'o-col-xl-6', 54 | ]; 55 | 56 | expect(wrapper.vm.classList).toEqual(expected); 57 | }); 58 | }); 59 | 60 | describe('and the props are another tag like section', () => { 61 | beforeEach(() => { 62 | wrapper = shallowMount(Col, { 63 | propsData: { 64 | tag: 'section', 65 | }, 66 | }); 67 | }); 68 | 69 | it('should match with the snapshot', () => { 70 | expect(wrapper.html()).toMatchSnapshot(); 71 | }); 72 | }); 73 | }); 74 | }); 75 | -------------------------------------------------------------------------------- /src/col/col.stories.js: -------------------------------------------------------------------------------- 1 | import { storiesOf } from '@storybook/vue'; 2 | 3 | import ORow from '../row/row.vue'; 4 | import OCol from './col.vue'; 5 | 6 | storiesOf('Col', module) 7 | // .add('default', () => 'simple row'); 8 | .add('default', () => ({ 9 | components: { ORow, OCol }, 10 | template: ` 11 | a 12 | b 13 | c 14 | d 15 | e 16 | f 17 | `, 18 | })) 19 | .add('offset', () => ({ 20 | components: { ORow, OCol }, 21 | template: ` 22 | a 23 | b 24 | c 25 | d 26 | e 27 | f 28 | `, 29 | })) 30 | .add('responsive', () => ({ 31 | components: { ORow, OCol }, 32 | template: ` 33 | a 34 | a 35 | a 36 | a 37 | a 38 | a 39 | `, 40 | })); 41 | -------------------------------------------------------------------------------- /src/col/col.vue: -------------------------------------------------------------------------------- 1 | 93 | -------------------------------------------------------------------------------- /src/col/index.js: -------------------------------------------------------------------------------- 1 | import col from './col.vue'; 2 | 3 | export default col; 4 | -------------------------------------------------------------------------------- /src/form/form.stories.js: -------------------------------------------------------------------------------- 1 | import { storiesOf } from '@storybook/vue'; 2 | import { 3 | withKnobs, 4 | select, 5 | text, 6 | } from '@storybook/addon-knobs/vue'; 7 | 8 | import OForm from './form.vue'; 9 | import OFormItem from '../formItem'; 10 | import OInput from '../input'; 11 | import OButton from '../button'; 12 | import ORadio from '../radio'; 13 | import OCheckbox from '../checkbox'; 14 | import OSelect from '../select'; 15 | 16 | const POSITION = { 17 | top: 'top', 18 | left: 'left', 19 | right: 'right', 20 | }; 21 | 22 | storiesOf('Form', module) 23 | // .add('default', () => 'simple row'); 24 | .addDecorator(withKnobs) 25 | .add('basic usage', () => ({ 26 | components: { 27 | OForm, 28 | OFormItem, 29 | OInput, 30 | OButton, 31 | ORadio, 32 | OCheckbox, 33 | OSelect, 34 | }, 35 | data() { 36 | return { 37 | form: { 38 | name: '', 39 | email: '', 40 | isReal: '', 41 | country: '', 42 | cities: [], 43 | languages: [], 44 | }, 45 | 46 | rules: { 47 | name: { 48 | presence: { 49 | allowEmpty: false, 50 | message: 'Please, tell us your name', 51 | }, 52 | trigger: 'blur', 53 | }, 54 | 55 | email: { 56 | email: { 57 | message: 'This is not a valid email', 58 | }, 59 | trigger: 'blur', 60 | }, 61 | 62 | isReal: { 63 | presence: { 64 | message: 'Are you really a real person?', 65 | }, 66 | 67 | validator(value) { 68 | if (value !== true) return 'You must be a real person'; 69 | 70 | return undefined; 71 | }, 72 | 73 | trigger: 'change', 74 | }, 75 | 76 | languages: { 77 | presence: { 78 | allowEmpty: false, 79 | message: 'Please, select a least one', 80 | }, 81 | 82 | trigger: 'change', 83 | }, 84 | 85 | country: { 86 | presence: { 87 | allowEmpty: false, 88 | message: 'Please, select your country', 89 | }, 90 | 91 | trigger: 'change', 92 | }, 93 | 94 | cities: { 95 | presence: { 96 | allowEmpty: false, 97 | message: 'Please, select at least 1 city', 98 | }, 99 | 100 | trigger: 'change', 101 | }, 102 | }, 103 | }; 104 | }, 105 | 106 | methods: { 107 | validate() { 108 | return this.$refs.form.validate(); 109 | }, 110 | 111 | clearValidation() { 112 | return this.$refs.form.clearValidation(); 113 | }, 114 | }, 115 | 116 | template: ` 117 | 124 | 125 | 128 | 129 | 130 | 131 | 134 | 135 | 136 | 137 | 140 | Yes 141 | No 142 | 143 | 144 | 147 | Javascript 148 | PHP 149 | Python 150 | Ruby 151 | 152 | 153 | 156 | 185 | 186 | 187 | 188 | 191 | 225 | 226 | 227 | 228 | Validate 229 | Clear validation 230 | 231 | `, 232 | })); 233 | -------------------------------------------------------------------------------- /src/form/form.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 82 | -------------------------------------------------------------------------------- /src/form/index.js: -------------------------------------------------------------------------------- 1 | import form from './form.vue'; 2 | 3 | export default form; 4 | -------------------------------------------------------------------------------- /src/formItem/formItem.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 165 | -------------------------------------------------------------------------------- /src/formItem/index.js: -------------------------------------------------------------------------------- 1 | import formItem from './formItem.vue'; 2 | 3 | export default formItem; 4 | -------------------------------------------------------------------------------- /src/icons/icons.stories.js: -------------------------------------------------------------------------------- 1 | import { storiesOf } from '@storybook/vue'; 2 | 3 | storiesOf('Icons', module) 4 | // .add('default', () => 'simple row'); 5 | .add('default', () => ({ 6 | template: `
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 |
236 | `, 237 | })); 238 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import Row from './row'; 2 | import Col from './col'; 3 | import Button from './button'; 4 | import Input from './input'; 5 | import Radio from './radio'; 6 | import Form from './form'; 7 | import FormItem from './formItem'; 8 | import Checkbox from './checkbox'; 9 | import Select from './select'; 10 | 11 | const components = [ 12 | Row, 13 | Col, 14 | Button, 15 | Input, 16 | Radio, 17 | Form, 18 | FormItem, 19 | Checkbox, 20 | Select, 21 | ]; 22 | 23 | function install(Vue) { 24 | components.forEach((component) => { 25 | Vue.component(component.name, component); 26 | }); 27 | } 28 | 29 | if (typeof window !== 'undefined' && window.Vue) { 30 | install(window.Vue); 31 | } 32 | 33 | export default { 34 | install, 35 | Row, 36 | Col, 37 | Button, 38 | Input, 39 | Radio, 40 | Form, 41 | FormItem, 42 | Checkbox, 43 | Select, 44 | }; 45 | -------------------------------------------------------------------------------- /src/input/__snapshots__/input.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Input should be a default input at startup 1`] = ` 4 |
5 | 6 | 7 | 8 |
9 | `; 10 | 11 | exports[`Input should be a large input 1`] = ` 12 |
13 | 14 | 15 | 16 |
17 | `; 18 | 19 | exports[`Input should be a mini input 1`] = ` 20 |
21 | 22 | 23 | 24 |
25 | `; 26 | 27 | exports[`Input should be a small input 1`] = ` 28 |
29 | 30 | 31 | 32 |
33 | `; 34 | 35 | exports[`Input should be disabled 1`] = ` 36 |
37 | 38 | 39 | 40 |
41 | `; 42 | 43 | exports[`Input should be readonly 1`] = ` 44 |
45 | 46 | 47 | 48 |
49 | `; 50 | 51 | exports[`Input should have a error status 1`] = ` 52 |
53 | 54 | 55 | 56 |
57 | `; 58 | 59 | exports[`Input should have a prefix icon through slot 1`] = ` 60 |
61 | 62 | 63 | 64 | 65 |
66 | `; 67 | 68 | exports[`Input should have a prefixIcon 1`] = ` 69 |
70 | 71 | 72 | 73 |
74 | `; 75 | 76 | exports[`Input should have a success status 1`] = ` 77 |
78 | 79 | 80 | 81 |
82 | `; 83 | 84 | exports[`Input should have a suffix icon through slot 1`] = ` 85 |
86 | 87 | 88 | 89 | 90 |
91 | `; 92 | 93 | exports[`Input should have a suffixIcon 1`] = ` 94 |
95 | 96 | 97 | 98 |
99 | `; 100 | -------------------------------------------------------------------------------- /src/input/index.js: -------------------------------------------------------------------------------- 1 | import input from './input.vue'; 2 | 3 | export default input; 4 | -------------------------------------------------------------------------------- /src/input/input.spec.js: -------------------------------------------------------------------------------- 1 | import { mount } from '@vue/test-utils'; 2 | import Input from './input.vue'; 3 | 4 | describe('Input', () => { 5 | let wrapper; 6 | 7 | const reset = () => wrapper.setProps({ 8 | name: '', 9 | placeholder: '', 10 | width: '300px', 11 | type: 'text', 12 | size: 'normal', 13 | value: '', 14 | readonly: false, 15 | autofocus: false, 16 | disabled: false, 17 | maxlength: Infinity, 18 | minlength: 0, 19 | max: Infinity, 20 | min: 0, 21 | prefixIcon: '', 22 | suffixIcon: '', 23 | isSuccess: false, 24 | isError: false, 25 | }); 26 | 27 | beforeAll(() => { 28 | wrapper = mount(Input); 29 | }); 30 | 31 | afterEach(reset); 32 | 33 | it('should be a default input at startup', () => { 34 | const defaultClasses = ['o-input', 'o-input--normal']; 35 | 36 | expect(wrapper.html()).toMatchSnapshot(); 37 | expect(wrapper.classes()).toEqual(defaultClasses); 38 | }); 39 | 40 | it('should be a large input', () => { 41 | wrapper.setProps({ 42 | size: 'large', 43 | }); 44 | 45 | expect(wrapper.html()).toMatchSnapshot(); 46 | expect(wrapper.classes()).toContain('o-input--large'); 47 | }); 48 | 49 | it('should be a small input', () => { 50 | wrapper.setProps({ 51 | size: 'small', 52 | }); 53 | 54 | expect(wrapper.html()).toMatchSnapshot(); 55 | expect(wrapper.classes()).toContain('o-input--small'); 56 | }); 57 | 58 | it('should be a mini input', () => { 59 | wrapper.setProps({ 60 | size: 'mini', 61 | }); 62 | 63 | expect(wrapper.html()).toMatchSnapshot(); 64 | expect(wrapper.classes()).toContain('o-input--mini'); 65 | }); 66 | 67 | it('should be disabled', () => { 68 | wrapper.setProps({ 69 | disabled: true, 70 | }); 71 | 72 | expect(wrapper.html()).toMatchSnapshot(); 73 | expect(wrapper.classes()).toContain('is-disabled'); 74 | expect(wrapper.html()).toContain('disabled='); 75 | }); 76 | 77 | it('should be readonly', () => { 78 | wrapper.setProps({ 79 | readonly: true, 80 | }); 81 | 82 | expect(wrapper.html()).toMatchSnapshot(); 83 | expect(wrapper.html()).toContain('readonly='); 84 | }); 85 | 86 | it('should have a prefixIcon', () => { 87 | wrapper.setProps({ 88 | prefixIcon: 'o-icon o-icon-search', 89 | }); 90 | 91 | expect(wrapper.html()).toMatchSnapshot(); 92 | expect(wrapper.html()).toContain('o-input__prefix'); 93 | expect(wrapper.html()).toContain(' { 97 | wrapper.setProps({ 98 | suffixIcon: 'o-icon o-icon-search', 99 | }); 100 | 101 | expect(wrapper.html()).toMatchSnapshot(); 102 | expect(wrapper.classes()).toContain('o-input__suffix'); 103 | expect(wrapper.html()).toContain(' { 107 | wrapper.setProps({ 108 | isSuccess: true, 109 | }); 110 | 111 | expect(wrapper.html()).toMatchSnapshot(); 112 | expect(wrapper.classes()).toContain('is-success'); 113 | expect(wrapper.html()).toContain(' { 117 | wrapper.setProps({ 118 | isError: true, 119 | }); 120 | 121 | expect(wrapper.html()).toMatchSnapshot(); 122 | expect(wrapper.classes()).toContain('is-error'); 123 | expect(wrapper.html()).toContain(' { 127 | wrapper.findAll('input').trigger('focus'); 128 | 129 | expect(wrapper.emitted().focus).toBeTruthy(); 130 | }); 131 | 132 | it('should emit a blur event', () => { 133 | wrapper.findAll('input').trigger('blur'); 134 | 135 | expect(wrapper.emitted().blur).toBeTruthy(); 136 | }); 137 | 138 | it('should emit a input event', () => { 139 | wrapper.setProps({ 140 | value: 'abc', 141 | }); 142 | wrapper.findAll('input').trigger('input'); 143 | 144 | expect(wrapper.vm.$data.currentValue).toBe('abc'); 145 | expect(wrapper.emitted().input).toBeTruthy(); 146 | }); 147 | 148 | it('should have a suffix icon through slot', () => { 149 | wrapper = mount(Input, { 150 | slots: { 151 | suffix: '', 152 | }, 153 | }); 154 | 155 | expect(wrapper.html()).toMatchSnapshot(); 156 | expect(wrapper.classes()).toContain('o-input__suffix'); 157 | expect(wrapper.html()).toContain(' { 161 | wrapper = mount(Input, { 162 | slots: { 163 | prefix: '', 164 | }, 165 | }); 166 | 167 | expect(wrapper.html()).toMatchSnapshot(); 168 | expect(wrapper.classes()).toContain('o-input__prefix'); 169 | expect(wrapper.html()).toContain(' 'simple row'); 7 | .add('default', () => ({ 8 | components: { OInput }, 9 | template: '', 10 | })) 11 | .add('with icon', () => ({ 12 | components: { OInput }, 13 | template: ` 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | `, 28 | })) 29 | .add('with status', () => ({ 30 | components: { OInput }, 31 | template: ` 32 |
33 | 34 | 35 |
36 | `, 37 | })) 38 | .add('sizes', () => ({ 39 | components: { OInput }, 40 | template: ` 41 |
42 | 43 | 44 | 45 | 46 |
47 | `, 48 | })) 49 | .add('disabled', () => ({ 50 | components: { OInput }, 51 | template: '', 52 | })) 53 | .add('readonly', () => ({ 54 | components: { OInput }, 55 | template: '', 56 | })); 57 | -------------------------------------------------------------------------------- /src/input/input.vue: -------------------------------------------------------------------------------- 1 | 45 | 46 | 211 | -------------------------------------------------------------------------------- /src/mixins/dispatch.js: -------------------------------------------------------------------------------- 1 | export default { 2 | methods: { 3 | dispatch(componentName, eventName, data) { 4 | let parent = this.$parent || this.$root; 5 | let { name } = parent.$options; 6 | 7 | while (parent && (!name || name !== componentName)) { 8 | parent = parent.$parent; 9 | 10 | if (parent) { 11 | const newName = parent.$options.name; 12 | name = newName; 13 | } 14 | } 15 | 16 | if (parent) { 17 | parent.$emit(eventName, data); 18 | } 19 | }, 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /src/radio/index.js: -------------------------------------------------------------------------------- 1 | import Radio from './radio.vue'; 2 | 3 | export default Radio; 4 | -------------------------------------------------------------------------------- /src/radio/radio.spec.js: -------------------------------------------------------------------------------- 1 | import { mount } from '@vue/test-utils'; 2 | import Radio from './radio.vue'; 3 | 4 | describe('Radio', () => { 5 | let wrapper; 6 | 7 | beforeEach(() => { 8 | wrapper = mount(Radio); 9 | wrapper.setProps({ 10 | size: 'medium', 11 | }); 12 | }); 13 | 14 | describe('when is default', () => { 15 | it('should have expected classes', () => { 16 | expect(wrapper.classes()).toEqual(['o-radio', 'o-radio--medium']); 17 | }); 18 | }); 19 | 20 | describe('when have default params filled', () => { 21 | beforeEach(() => { 22 | wrapper.setProps({ 23 | value: '1', 24 | modelValue: '1', 25 | label: 'label', 26 | name: 'name', 27 | }); 28 | }); 29 | 30 | it('should have a name attr', () => { 31 | const { name } = wrapper.find('input') 32 | .attributes(); 33 | expect(name).toEqual('name'); 34 | }); 35 | 36 | it('should have a value attr', () => { 37 | const input = wrapper.find('input'); 38 | const { value } = input.attributes(); 39 | expect(value).toEqual('1'); 40 | }); 41 | 42 | it('should have a label', () => { 43 | const label = wrapper.find('.o-radio__label'); 44 | expect(label.text()).toEqual('label'); 45 | }); 46 | }); 47 | 48 | describe('when is clicked', () => { 49 | beforeEach(() => { 50 | wrapper.setProps({ 51 | modelValue: '0', 52 | value: '1', 53 | }); 54 | }); 55 | 56 | it('should change isChecked to true', () => { 57 | wrapper.find('input').trigger('change'); 58 | wrapper.vm.$nextTick(() => { 59 | expect(wrapper.vm.isChecked).toBeTruthy(); 60 | }); 61 | }); 62 | }); 63 | 64 | describe('when is disabled', () => { 65 | beforeEach(() => { 66 | wrapper.setProps({ 67 | disabled: true, 68 | }); 69 | }); 70 | 71 | it('should have is-disabled class', () => { 72 | expect(wrapper.classes()) 73 | .toEqual(expect.arrayContaining(['is-disabled'])); 74 | }); 75 | }); 76 | 77 | describe('when is checked', () => { 78 | beforeEach(() => { 79 | wrapper.setProps({ 80 | modelValue: '1', 81 | value: '1', 82 | }); 83 | }); 84 | 85 | it('should have is-checked class', () => { 86 | expect(wrapper.classes()) 87 | .toEqual(expect.arrayContaining(['is-checked'])); 88 | }); 89 | }); 90 | 91 | describe('when have another size', () => { 92 | beforeEach(() => { 93 | wrapper.setProps({ 94 | size: 'large', 95 | }); 96 | }); 97 | 98 | it('should have o-radio--large class', () => { 99 | expect(wrapper.classes()) 100 | .toEqual(expect.arrayContaining(['o-radio', 'o-radio--large'])); 101 | }); 102 | }); 103 | }); 104 | -------------------------------------------------------------------------------- /src/radio/radio.stories.js: -------------------------------------------------------------------------------- 1 | import { storiesOf } from '@storybook/vue'; 2 | import { 3 | withKnobs, 4 | select, 5 | } from '@storybook/addon-knobs/vue'; 6 | 7 | import ORadio from './radio.vue'; 8 | 9 | const SIZES = { 10 | small: 'small', 11 | medium: 'medium', 12 | large: 'large', 13 | }; 14 | 15 | storiesOf('Radio', module) 16 | .add('default', () => ({ 17 | components: { ORadio }, 18 | data() { 19 | return { 20 | modelValue: 1, 21 | }; 22 | }, 23 | template: ` 24 |
25 |

Selected Value: {{modelValue}}

26 | 27 | 28 |
29 | `, 30 | })) 31 | .add('with a disabled', () => ({ 32 | components: { 33 | ORadio, 34 | }, 35 | data() { 36 | return { 37 | modelValue: 2, 38 | }; 39 | }, 40 | template: ` 41 |
42 |

Selected Value: {{modelValue}}

43 | 44 | 45 |
46 | `, 47 | })) 48 | .addDecorator(withKnobs) 49 | .add('with editable size', () => ({ 50 | components: { 51 | ORadio, 52 | }, 53 | template: ` 54 | `, 60 | })); 61 | -------------------------------------------------------------------------------- /src/radio/radio.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 67 | -------------------------------------------------------------------------------- /src/row/__snapshots__/row.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Row when pass no props should match with the snapshot 1`] = `
`; 4 | 5 | exports[`Row when pass some props and the prop is another tag like section should match with the snapshot 1`] = `
`; 6 | 7 | exports[`Row when pass some props and the props are {"justify":"flex-end","align":"flex-end","content":"center","direction":"column","wrap":"no-wrap"} should match with the snapshot 1`] = `
`; 8 | -------------------------------------------------------------------------------- /src/row/index.js: -------------------------------------------------------------------------------- 1 | import row from './row.vue'; 2 | 3 | export default row; 4 | -------------------------------------------------------------------------------- /src/row/row.spec.js: -------------------------------------------------------------------------------- 1 | import { shallowMount } from '@vue/test-utils'; 2 | import Row from './row.vue'; 3 | 4 | describe('Row', () => { 5 | let wrapper; 6 | 7 | describe('when pass no props', () => { 8 | beforeEach(() => { 9 | wrapper = shallowMount(Row); 10 | }); 11 | 12 | it('should match with the snapshot', () => { 13 | expect(wrapper.html()).toMatchSnapshot(); 14 | }); 15 | 16 | it('should have expected classList', () => { 17 | const expected = [ 18 | 'o-row', 19 | 'is-justify-flex-start', 20 | 'is-align-flex-start', 21 | 'is-content-flex-start', 22 | 'is-direction-row', 23 | 'is-wrap', 24 | ]; 25 | expect(wrapper.vm.classList).toEqual(expected); 26 | }); 27 | }); 28 | 29 | describe('when pass some props', () => { 30 | const props = { 31 | justify: 'flex-end', 32 | align: 'flex-end', 33 | content: 'center', 34 | direction: 'column', 35 | wrap: 'no-wrap', 36 | }; 37 | 38 | describe(`and the props are ${JSON.stringify(props)}`, () => { 39 | beforeEach(() => { 40 | wrapper = shallowMount(Row, { 41 | propsData: props, 42 | }); 43 | }); 44 | 45 | it('should match with the snapshot', () => { 46 | expect(wrapper.html()).toMatchSnapshot(); 47 | }); 48 | 49 | it('should have an expected classList', () => { 50 | const expected = [ 51 | 'o-row', 52 | 'is-justify-flex-end', 53 | 'is-align-flex-end', 54 | 'is-content-center', 55 | 'is-direction-column', 56 | 'is-no-wrap', 57 | ]; 58 | 59 | expect(wrapper.vm.classList).toEqual(expected); 60 | }); 61 | }); 62 | 63 | describe('and the prop is another tag like section', () => { 64 | beforeEach(() => { 65 | wrapper = shallowMount(Row, { 66 | propsData: { tag: 'section' }, 67 | }); 68 | }); 69 | 70 | it('should match with the snapshot', () => { 71 | expect(wrapper.html()).toMatchSnapshot(); 72 | }); 73 | }); 74 | }); 75 | }); 76 | -------------------------------------------------------------------------------- /src/row/row.stories.js: -------------------------------------------------------------------------------- 1 | import { storiesOf } from '@storybook/vue'; 2 | import { 3 | withKnobs, 4 | text, 5 | number, 6 | select, 7 | } from '@storybook/addon-knobs/vue'; 8 | 9 | import ORow from './row.vue'; 10 | 11 | const justifyOptions = { 12 | center: 'center', 13 | flexStart: 'flex-start', 14 | flexEnd: 'flex-end', 15 | baseline: 'baseline', 16 | }; 17 | 18 | const alignOptions = { 19 | center: 'center', 20 | flexStart: 'flex-start', 21 | flexEnd: 'flex-end', 22 | }; 23 | 24 | storiesOf('Row', module) 25 | .addDecorator(withKnobs) 26 | .add('default', () => ({ 27 | components: { ORow }, 28 | template: `${text('text', 'simple row')}`, 29 | })) 30 | .add('justify center', () => ({ 31 | components: { ORow }, 32 | template: ` 34 | ${text('text', 'simple row')} 35 | `, 36 | })) 37 | .add('justify and align center', () => ({ 38 | components: { ORow }, 39 | template: ` 42 |
43 | ${text('box1 text', 'box 1')} 44 |
45 |
46 | ${text('box2 text', 'box 2')} 47 |
48 |
`, 49 | })); 50 | -------------------------------------------------------------------------------- /src/row/row.vue: -------------------------------------------------------------------------------- 1 | 70 | -------------------------------------------------------------------------------- /src/select/Select.vue: -------------------------------------------------------------------------------- 1 | 149 | 150 | 405 | -------------------------------------------------------------------------------- /src/select/index.js: -------------------------------------------------------------------------------- 1 | import Select from './Select.vue'; 2 | 3 | export default Select; 4 | -------------------------------------------------------------------------------- /src/select/select.spec.js: -------------------------------------------------------------------------------- 1 | import { mount } from '@vue/test-utils'; 2 | import Select from './Select.vue'; 3 | 4 | describe('Select', () => { 5 | let wrapper; 6 | 7 | const reset = () => { 8 | wrapper.setProps({ 9 | options: [ 10 | { 11 | label: 'São Paulo', 12 | value: 'São Paulo', 13 | }, { 14 | label: 'New York', 15 | value: 'New York', 16 | }, { 17 | label: 'New York', 18 | value: 'Berlin', 19 | }], 20 | multiple: false, 21 | filterable: false, 22 | value: '', 23 | clearable: false, 24 | }); 25 | 26 | wrapper.setData({ 27 | currentValue: '', 28 | }); 29 | }; 30 | 31 | beforeAll(() => { 32 | wrapper = mount(Select); 33 | }); 34 | 35 | afterEach(reset); 36 | 37 | it('should be a default select at startup', () => { 38 | const defaultClasses = ['o-select', 'o-select--normal']; 39 | const options = wrapper.findAll('.o-select__list-item'); 40 | 41 | expect(options.length).toEqual(0); 42 | expect(wrapper.classes()).toEqual(defaultClasses); 43 | expect(wrapper.isVisible()).toEqual(true); 44 | }); 45 | 46 | it('should select appear options when trigger space', () => { 47 | wrapper.trigger('keydown.space'); 48 | const options = wrapper.findAll('.o-select__list-item'); 49 | expect(options.length).toEqual(3); 50 | }); 51 | 52 | it('should select appear options when trigger click', () => { 53 | wrapper.trigger('click'); 54 | const options = wrapper.findAll('.o-select__list-item'); 55 | expect(options.length).toEqual(3); 56 | }); 57 | 58 | it('should select São Paulo when using keydown events', () => { 59 | wrapper.trigger('click'); 60 | wrapper.find('.o-select__list-item').trigger('click'); 61 | expect(wrapper.vm.$data.currentValue).toEqual('São Paulo'); 62 | }); 63 | 64 | it('should emit change event', () => { 65 | wrapper.trigger('click'); 66 | wrapper.find('.o-select__list-item').trigger('click'); 67 | expect(wrapper.emitted().change).toBeTruthy(); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /src/select/select.stories.js: -------------------------------------------------------------------------------- 1 | import { storiesOf } from '@storybook/vue'; 2 | 3 | import OSelect from './Select.vue'; 4 | 5 | 6 | storiesOf('Select', module) 7 | .add('Basic Usage', () => ({ 8 | components: { OSelect }, 9 | data() { 10 | return { 11 | options: [ 12 | { 13 | label: 'São Paulo', 14 | value: 'São Paulo', 15 | }, 16 | { 17 | label: 'London', 18 | value: 'London', 19 | }, 20 | { 21 | label: 'Berlin', 22 | value: 'Berlin', 23 | }, 24 | { 25 | label: 'New York', 26 | value: 'New York', 27 | }, 28 | ], 29 | }; 30 | }, 31 | template: ` 32 | `, 33 | })) 34 | .add('Multiple Selection', () => ({ 35 | components: { OSelect }, 36 | data() { 37 | return { 38 | options: [ 39 | { 40 | label: 'São Paulo', 41 | value: 'São Paulo', 42 | }, 43 | { 44 | label: 'London', 45 | value: 'London', 46 | }, 47 | { 48 | label: 'Berlin', 49 | value: 'Berlin', 50 | }, 51 | { 52 | label: 'New York', 53 | value: 'New York', 54 | }, 55 | ], 56 | }; 57 | }, 58 | template: '', 59 | })) 60 | .add('Filterable', () => ({ 61 | components: { OSelect }, 62 | data() { 63 | return { 64 | options: [ 65 | { 66 | label: 'São Paulo', 67 | value: 'São Paulo', 68 | }, 69 | { 70 | label: 'London', 71 | value: 'London', 72 | }, 73 | { 74 | label: 'Berlin', 75 | value: 'Berlin', 76 | }, 77 | { 78 | label: 'New York', 79 | value: 'New York', 80 | }, 81 | ], 82 | }; 83 | }, 84 | template: '', 85 | })) 86 | .add('Clearable', () => ({ 87 | components: { OSelect }, 88 | data() { 89 | return { 90 | options: [ 91 | { 92 | label: 'São Paulo', 93 | value: 'São Paulo', 94 | }, 95 | { 96 | label: 'London', 97 | value: 'London', 98 | }, 99 | { 100 | label: 'Berlin', 101 | value: 'Berlin', 102 | }, 103 | { 104 | label: 'New York', 105 | value: 'New York', 106 | }, 107 | ], 108 | }; 109 | }, 110 | template: '', 111 | })); 112 | -------------------------------------------------------------------------------- /src/storyshots.spec.js: -------------------------------------------------------------------------------- 1 | import initStoryshots from '@storybook/addon-storyshots'; 2 | 3 | initStoryshots(); 4 | --------------------------------------------------------------------------------